数据结构-链表-双向链表

数据结构-链表-双向链表

单向链表和环形链表都是属于拥有方向性的链表,只能单向遍历,如果由于某种原因造成了某个连接断裂,那后面的链表数据便会遗失而无法复原。所以,我们可以将两个方向不同的链表结合起来,除了存放数据的字段之外,它还有两个指针变量,除了类似于单向链表的下一个指针next外,还需要一个指针指向上一个数据,这样的链表就是双向链表(Double Linked List)

由于每个节点都有两个指针,可以双向通行,因此可以轻松地找到前后节点,同时从链表中任意的节点都可以找到其他节点,而不需要经过反转或者对比节点等处理,执行速度较快。

  1. 双向链表的建立

    双向链表的数据结构中,对于每个节点来说,具有3个字段,两个指针变量,一个数据字段,指针变量分别指向左右(前后)指针,使用llink和rlink表示,llink指向上一个节点(可以看做是left link),rlink指向下一个节点(可以看做right link)

    llinkdatarlink
    指向上一个节点节点指向下一个节点

    实际情况中,双向链表可以是环形的,也可以不是环形的,如果最后一个节点的右指针指向了首节点,而首节点的左指针指向尾节点,这样的链表就是环形双向链表

    class student:
    		def __init__ (self):
    				self.name = ''
    				self.no = 0
    				self.llink = None
    				self.rlink = None
    				
    		head = student()	#声明头指针
    		head.llink = None	#头指针的左指针指向None
    		head.rlink = None	#头指针的右指针指向None
    		ptr = head	#设置存取指针开始的位置
    		select = 0
    		while True:
    				select = int(input('(1) 新增 (2) 离开'))
    				if select == 2:
    						break
    				if select == 1:
    						new_data = student()
    						new_data.name = input('请输入姓名:')
    						new_data.no = input('请输入学号:')
    						ptr.rlink = new_data	#右指针指向new_data
    						new_data.llink = ptr	#新节点的左指针指向ptr
    						new_data.rlink = None	#新节点的右指针设置为None
    						ptr = new_data	#指针设置为新元素的位置
    
  2. 双向链表的遍历

    双向链表因为有两个指针,所以可以双向遍历,在单向链表中如果想要逆向遍历就需要反转链表才可以实现,而在双向链表中可以根据llink和rlink来进行双向遍历

    • 从左向右遍历(使用rlink)

      ptr = head.rlink
      while ptr != None:
      		print(ptr.name,ptr.no)
      		ptr = ptr.rlink	#指针右移
      
    • 从右向左遍历(使用llink)

      ptr = head.rlink
      while ptr != None:
      		ptr = ptr.rlink		#找到最右侧的节点
      while ptr != head:
      		print(ptr.name,ptr.no)
      		ptr = ptr.llink		#指针左移
      
  3. 双向链表插入新节点

    双向链表的节点插入可以分为三种情况

    • 将新节点加入双向链表的第一个节点之前:将新节点的右指针(rlink)指向原链表的第一个节点,接着将原链表第一个节点的左指针(llink)指向新节点,将原链表的链表头指针指向新节点

      Xheadrlink
      插入的节点(新head)链表原来的第一个节点下一个节点
      X.rlink = head
      head.llink = X
      head = X
      
    • 将新节点加入双向链表的末尾:将原链表的最后一个节点的右指针指向新节点,将新节点的左指针指向原链表的最后一个节点,并将新节点的右指针指向None

      llinkPtrX
      上一个节点原链表的尾节点新节点
      ptr.rlink = X
      X.llink = ptr
      X.rlink = None
      
    • 将新节点加入链表中的ptr节点之后:首先将ptr节点的右指针指向新节点,再将新节点的左指针指向ptr节点,接着将ptr节点的下一个节点的左指针指向新节点,最后将新节点的右指针指向ptr的下一个节点

      ptrXptr.rlink
      原链表的上一个节点新节点原链表的下一个节点
      ptr.rlink.llink = X
      X.rlink = ptr.rlink
      X.llink = ptr
      ptr.rlink = X
      

      注意:此次插入的过程中出现的三个变量互换,一定要注意互换的前后顺序,如果先ptr.rlink = X,就会出现ptr.rlink再使用时指向的是X,而不是原链表的下一个节点

  4. 双向链表删除节点

    双向链表的删除节点和单向链表的删除节点相似,也可以分为三种情况

    • 删除双向链表的第一个节点:将链表头指针head指向原链表的第二个节点,再将新链表头的左指针指向None

      headhead.rlink
      原链表的第一个指针新链表的head
      head = head.rlink
      head.llink = None
      
    • 删除双向链表的最后一个节点:将原链表最后一个节点之前的一个节点的右指针指向None即可

      end.llinkend
      新链表最后一个节点原链表最后一个节点
      end.llink.rlink = None
      
    • 删除双向链表的中间节点X:将X节点的前一个节点的右指针指向X节点的下一个节点,再将X节点的下一个节点的左指针指向X节点的上一个节点

      X.llinkXX.rlink
      上一个节点删除的中间节点下一个节点
      X.llink.rlink = X.rlink
      X.rlink.llink = X.llink
      
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牧码文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值