【数据结构】链表的基本操作

本篇从链表的任意位置删除元素开始讲述,前面相关操作可以看文末完整代码


任意位置删除元素

思路:

思路:

1、既然我们要删除任意位置,所需的参数肯定有:表示位置的location。

2、链表中删除,我们使用删除结点的前一个结点的next指向要删除的结点的后一个结点。

即要同时找到图中的q和location

伪代码如下:

找q部分:                                          

q=head

i=i

while i<location-1:

        q=q.next

        i+=1

删除操作核心部分:

q.next=q.next.next

size-=1

最后考虑一下几个特殊点:

①删除位置是否合法:空表,删不了,location小于零或者大于元素个数,删不了

②单结点:因为无法进入循环也无法用q删除,所以我们直接调用写好的删头(尾)结点函数或者直接head=None

③删末尾元素:本情况已包含在代码里

④是否对size自减,while循环i是否自增?

那么我们直接上代码:

#任意位置删除
    def del_anywhere(self,location):
        if self.is_empty() or location<0 or location>self.size:
            print('空表删不了哦')
        elif self.size == 1 or location == 1:
            self.head=None
            self.size-=1
        else:
            q=self.head
            i=1
            while i<location-1:
                q=q.next
                i+=1
            q.next=q.next.next
            self.size-=1

测试案例以及结果如下:


按位置修改元素

思路:

1、我们需要什么参数?------------位置参数location你总得要吧,修改的新值value才能改吧

2、怎么修改?我们要找到location位置的结点,这时候需要它前一个结点的next指向才可以,所以又用到了我们的 q

3、找到q,修改即可

4、考虑一下特殊情况

伪代码如下:

找q部分:                                          

q=head

i=i

while i<location-1:

        q=q.next

        i+=1

该值部分:

q.next.data=value

考虑特殊点:

①空表:改不了

②单结点:无法进入循环,直接head.data赋值

③删末尾元素:无特例

④size不用变,while的i记得自增

 上代码:

#按位置修改值
    def change_anywhere(self,location,value):
        if self.is_empty():
            print('空表无法修改元素')
        elif self.size == 1:
            self.head.data=value
        else:
            q=self.head
            i=1
            while i<location-1:
                q=q.next
                i+=1
            q.next.data=value

测试案例以及结果:


按值修改元素(小细节很多建议反复看)🏆

思路:

1、既然是按值修改,那么就要遍历以获取有多少所匹配的元素

2、所需的参数为匹配的data值和要改的新data

3、遍历到底

4、空表无法修改

5、遍历完了我们需要知道是否改了值,那么可以再循环内加个  flag  记录

万事俱备,直接上伪代码:

遍历:

q=head                        

while q:                        #这里q到了最后一轮循环会指向None,自动退出循环

        q=q.next

        

匹配旧值部分:

if q.data == old_value:

匹配成功赋新值:

q.data=new_value 

记录遍历过程是否改了值:(细节部分)

flag=0

while .......:

        if........:

                ..........

                flag+=1

if flag=0:

        没有改值

else:

        改了flag次        

        

上封装函数代码:

#按值修改
    def change_value(self,old_value,new_value):
        if self.is_empty():
            print('空表修改不了哦')
            return
        q=self.head
        flag=0
        while q:
            if q.data == old_value:
                q.data=new_value
                flag+=1
            q=q.next
        if flag == 0:
            print('未匹配相关值,修改失败')
        else:
            print(f'修改了{flag}处')

测试以及结果:


按值查找返回位置(同样有很多细节)

分析:

①遍历链表,而且要遍历充分

②链表没有索引下标,所以要自己记录下标

空表情况无法遍历

④可以用 flag 记录匹配成功次数,若为0记录为匹配失败

⑤设置一个  bag[ ]  列表用于存储可能有多个的下标,并且有返回值

伪代码如下:

遍历和记录:
        q=self.head
        flag
        bags
        i=1
        while q:
            if q.data == value:
                bags追加i
                flag+=1
            q=q.next
            i+=1

循环结束的判断匹配是否成功:
        if flag == 0:
           查无此值
            return []
        else:
            查到flag个值
            return bags

上完整代码:

#按值返回位置
    def return_index(self,value):
        if self.is_empty():
            print('空表无法操作')
            return
        q=self.head
        flag=0
        bags=[]
        i=1
        while q:
            if q.data == value:
                bags.append(i)
                flag+=1
            q=q.next
            i+=1
        if flag == 0:
            print('查无此值')
            return []
        else:
            print(f'查到{flag}个值')
            return bags

结果如下:(查找值为20的位置)

返回了一个列表包含两个值


链表转置(用到了双指针)

不多说了,直接看分析:

为了编写一个反转链表的函数,我们可以保持您现有的链表类和节点类不变,并添加一个新的方法来执行反转操作。

反转链表的核心思想是迭代地遍历链表,同时改变每个节点的 next 指针,使其指向前一个节点

# 反转链表
    def reverse(self):
        prev = None
        q = self.head
        while q:
            next_node = q.next  # 保存对下一个节点的引用
            q.next = prev       # 反转当前节点的指针
            prev = q            # 移动 prev 指针到当前节点
            q = next_node       # 移动 q 指针到下一个节点
        self.head = prev              # 更新头节点为新的头节点(原来的尾节点)
def reverse(self):
    if self.is_empty() or self.size==1:
        return
    else:
        prev=None
        q=self.head
        while q:
            next_q=q.next
            q.next=prev
            #self.head=q        可在此处更新头结点为q(不过没必要),因为可在外部直接设置为prev(因为循环内部还未将prev更新为q)
            prev=q
            q=next_q
        self.head=prev          #此位置为外部设置新头结点


       注意

标红处之所以我们可以直接放到循环外部,因为不论是内部还是外部该语句都是更新头结点,循环内部是不断一步步更新,放循环外部是一步更新头结点

结果如下:

方法二:

    def reverse2(self):
        if self.is_empty():
            print('空表')
        else:
            q=self.head
            self.head=None
            while q:
                self.add_head(q.data)
                q=q.next

直接把头结点拿出来之后用q遍历每个结点进行头插即可


链表思维导图


完整代码&测试样例

#结点的类
class Node(object):
    def __init__(self,data):
        self.data=data
        self.next=None
#链表类
class LinkList(object):
    def __init__(self):
        self.head=None
        self.size=0
#判空
    def is_empty(self):
        return self.size == 0
#头插
    def add_head(self,value):
        node=Node(value)
        node.next=self.head
        self.head=node
        self.size+=1
#遍历
    def show_me(self):
        if self.is_empty():
            print('空链表,不用遍历')
            return
        else:
            q=self.head
            while q:
                print(q.data,end=' ')
                q=q.next
#尾插
    def add_tail(self,value):
        node=Node(value)
        if self.is_empty():
            self.head=node
            self.size+=1
        else:
            p=self.head
            while p.next:
                p=p.next
            p.next=node
            self.size+=1
#任意位置插入
    def add_anywhere(self,location,value):
        node = Node(value)
        if location>self.size+1 or location<=0:
            print('插入位置有误')
            return
        else:
            r = self.head
            #第一个位置就头插
            if location == 1:
                self.add_head(value)
            else:
                i=1
                while i<location-1:
                    r = r.next
                    i+=1
                node.next = r.next
                r.next = node
                self.size += 1
#头删
    def del_head(self):
        if self.is_empty():
            print('删不了一点')
            return
        self.head=self.head.next
        self.size-=1
#尾删
    def del_tail(self):
        if self.is_empty():         #空表删不了
            print('删不了哦')
        elif self.size == 1:        #一个元素直接让self.head = None
            self.head = None
            self.size -= 1
        else:
            p = self.head
            while p.next.next:      #遍历到倒数第二个结点,
                                    #如果这种方式理解不了可以用 i=1 while i<self.size-1 然后内部i+=1 也可以
                p = p.next
            p.next = None
            self.size -= 1
#任意位置删除
    def del_anywhere(self,location):
        if self.is_empty():
            print('空表删不了哦')
        elif self.size == 1:
            self.head=None
        else:
            q=self.head
            i=1
            while i<location-1:
                q=q.next
                i+=1
            q.next=q.next.next
            self.size-=1
#按位置修改值
    def change_anywhere(self,location,value):
        if self.is_empty():
            print('空表无法修改元素')
        elif self.size == 1:
            self.head.data=value
        else:
            q=self.head
            i=1
            while i<location-1:
                q=q.next
                i+=1
            q.next.data=value
#按值修改
    def change_value(self,old_value,new_value):
        if self.is_empty():
            print('空表修改不了哦')
            return
        q=self.head
        flag=0
        while q:
            if q.data == old_value:
                q.data=new_value
                flag+=1
            q=q.next
        if flag == 0:
            print('未匹配相关值,修改失败')
        else:
            print(f'修改了{flag}处')
#按值返回位置
    def return_index(self,value):
        if self.is_empty():
            print('空表无法操作')
            return
        q=self.head
        flag=0
        bags=[]
        i=1
        while q:
            if q.data == value:
                bags.append(i)
                flag+=1
            q=q.next
            i+=1
        if flag == 0:
            print('查无此值')
            return []
        else:
            print(f'查到{flag}个值')
            return bags
# 反转链表
    def reverse(self):
        prev = None
        q = self.head
        while q:
            next_node = q.next  # 保存对下一个节点的引用
            q.next = prev       # 反转当前节点的指针
            prev = q            # 移动 prev 指针到当前节点
            q = next_node       # 移动 q 指针到下一个节点
        self.head = prev              # 更新头节点为新的头节点(原来的尾节点)



if __name__ =='__main__':
    new_l=LinkList()
    print('头插')
    new_l.add_head(10)
    new_l.add_head(20)
    new_l.add_head(30)
    new_l.show_me()
    print()

    print('尾插')
    new_l.add_tail(10)
    new_l.add_tail(20)
    new_l.add_tail(40)
    new_l.show_me()
    print()

    print('任意位置')
    new_l.add_anywhere(6,30)
    new_l.show_me()
    print()

    print('任意位置(尾部)')
    new_l.add_anywhere(8,50)
    new_l.show_me()
    print()

    print('任意位置(头部)')
    new_l.add_anywhere(1,0)
    new_l.show_me()
    print()

    print('头删')
    new_l.del_head()
    new_l.show_me()
    print()

    print('尾删')
    new_l.del_tail()
    new_l.show_me()
    print()

    print('任意位置删(这里删的10)')
    new_l.del_anywhere(4)
    new_l.show_me()
    print()

    print('任意位置该元素')
    new_l.change_anywhere(3,1)
    new_l.show_me()
    print()

    print('按值修改')
    new_l.change_value(1,666)
    new_l.show_me()
    print()

    print('查下标')
    print(new_l.return_index(20))

    print('反转链表前')
    new_l.show_me()
    print()

    # 反转链表
    new_l.reverse()

    print('反转链表后')
    new_l.show_me()
    print()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值