当前位置: 首页 > news >正文

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

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


任意位置删除元素

思路:

思路:

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=Noneself.size-=1else:q=self.headi=1while i<location-1:q=q.nexti+=1q.next=q.next.nextself.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=valueelse:q=self.headi=1while i<location-1:q=q.nexti+=1q.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('空表修改不了哦')returnq=self.headflag=0while q:if q.data == old_value:q.data=new_valueflag+=1q=q.nextif flag == 0:print('未匹配相关值,修改失败')else:print(f'修改了{flag}处')

测试以及结果:


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

分析:

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

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

空表情况无法遍历

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

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

伪代码如下:

遍历和记录:q=self.headflagbagsi=1while q:if q.data == value:bags追加iflag+=1q=q.nexti+=1循环结束的判断匹配是否成功:if flag == 0:查无此值return []else:查到flag个值return bags

上完整代码:

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

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

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


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

不多说了,直接看分析:

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

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

# 反转链表def reverse(self):prev = Noneq = self.headwhile 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:returnelse:prev=Noneq=self.headwhile q:next_q=q.nextq.next=prev #self.head=q        可在此处更新头结点为q(不过没必要),因为可在外部直接设置为prev(因为循环内部还未将prev更新为q)prev=qq=next_q self.head=prev          #此位置为外部设置新头结点


       注意

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

结果如下:

方法二:

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

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


链表思维导图


完整代码&测试样例

#结点的类
class Node(object):def __init__(self,data):self.data=dataself.next=None
#链表类
class LinkList(object):def __init__(self):self.head=Noneself.size=0
#判空def is_empty(self):return self.size == 0
#头插def add_head(self,value):node=Node(value)node.next=self.headself.head=nodeself.size+=1
#遍历def show_me(self):if self.is_empty():print('空链表,不用遍历')returnelse:q=self.headwhile q:print(q.data,end=' ')q=q.next
#尾插def add_tail(self,value):node=Node(value)if self.is_empty():self.head=nodeself.size+=1else:p=self.headwhile p.next:p=p.nextp.next=nodeself.size+=1
#任意位置插入def add_anywhere(self,location,value):node = Node(value)if location>self.size+1 or location<=0:print('插入位置有误')returnelse:r = self.head#第一个位置就头插if location == 1:self.add_head(value)else:i=1while i<location-1:r = r.nexti+=1node.next = r.nextr.next = nodeself.size += 1
#头删def del_head(self):if self.is_empty():print('删不了一点')returnself.head=self.head.nextself.size-=1
#尾删def del_tail(self):if self.is_empty():         #空表删不了print('删不了哦')elif self.size == 1:        #一个元素直接让self.head = Noneself.head = Noneself.size -= 1else:p = self.headwhile p.next.next:      #遍历到倒数第二个结点,#如果这种方式理解不了可以用 i=1 while i<self.size-1 然后内部i+=1 也可以p = p.nextp.next = Noneself.size -= 1
#任意位置删除def del_anywhere(self,location):if self.is_empty():print('空表删不了哦')elif self.size == 1:self.head=Noneelse:q=self.headi=1while i<location-1:q=q.nexti+=1q.next=q.next.nextself.size-=1
#按位置修改值def change_anywhere(self,location,value):if self.is_empty():print('空表无法修改元素')elif self.size == 1:self.head.data=valueelse:q=self.headi=1while i<location-1:q=q.nexti+=1q.next.data=value
#按值修改def change_value(self,old_value,new_value):if self.is_empty():print('空表修改不了哦')returnq=self.headflag=0while q:if q.data == old_value:q.data=new_valueflag+=1q=q.nextif flag == 0:print('未匹配相关值,修改失败')else:print(f'修改了{flag}处')
#按值返回位置def return_index(self,value):if self.is_empty():print('空表无法操作')returnq=self.headflag=0bags=[]i=1while q:if q.data == value:bags.append(i)flag+=1q=q.nexti+=1if flag == 0:print('查无此值')return []else:print(f'查到{flag}个值')return bags
# 反转链表def reverse(self):prev = Noneq = self.headwhile 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()



http://www.mrgr.cn/news/78082.html

相关文章:

  • 微信小程序组件详解:text 和 rich-text 组件的基本用法
  • 认识RabbitMq和RabbitMq的使用
  • 深度学习笔记1:自动微分与神经网络实现(附代码)
  • 报表工具功能对比:免费易上手的山海鲸报表 vs 庞大用户群体的Tableau
  • Unity 导出 Xcode 工程 修改 Podfile 文件
  • SPA 首屏加载慢的原因及解决方案:结合实际项目的详细讲解
  • Tkinter置顶弹窗提示操作成功
  • 分布式搜索引擎Elasticsearch(一)
  • Maven学习笔记
  • 设计模式——抽象工厂模式
  • 报表工具功能对比:免费易上手的山海鲸报表 vs 庞大用户群体的Tableau
  • [论文阅读-综述]Supervised Speech Separation Based on Deep Learning: An Overview
  • Android 应用测试的各种环境问题记录(Instrumentation测试)
  • [UE5学习] 一、使用源代码安装UE5.4
  • Dockerfile构建报错【ERROR: failed to solve: process】的解决办法
  • ES更新问题 Failed to close the XContentBuilder异常
  • 动态链接库工作原理 PLT GOT
  • 【数据挖掘】一、基于LDA的用户兴趣建模(兴趣标签生成模型)--用户兴趣挖掘模型
  • 《硬件架构的艺术》笔记(七):处理字节顺序
  • 车载显示display基础知识和评估
  • 02.02、返回倒数第 k 个节点
  • 如何制作项目网页
  • 【C++11】尽显锋芒
  • 指针测试总结(一)(一维数组)
  • CTF-RE 从0到 N: 高版本 APK 调试 + APK逻辑修改再打包 + os层调试[2024 强网杯青少年专项赛 Flip_over] writeup
  • Apollo9.0源码部署(Nvidia显卡)