python实现双向链表

python实现双向链表

双向链表:

在单链表的节点中只有一个指向其后继节点的指针域next,因此若已知某节点的指针为p,其后继节点的指针为p->next,而找其前驱节点则只能从该链表的头指针开始顺着各节点的next域进行,也就是说找后记的时间性能是O(1),找前驱的节点为O(n),如果也希望找到前驱的时间性能是O(1),则可以通过付出空间为代价,每一个节点再加一个指向前驱的指针域。因此这就是双向链表
在这里插入图片描述

双向链表实现的功能

1、判断是否为空

    def is_empty(self):
        """判断是否为空"""
        return self.__head is None

2、求长度

    def length(self):
        """链表长度"""
        #cur游标,用来移动遍历节点
        cur=self.__head
        #count记录数量
        count=0
        while cur!=None:
            count+=1
            cur=cur.next
        return count

3、头插入

    def add(self,data):
        """链表头部添加元素,头插法"""
        #第一种方法
        node=Node(data)
        node.next=self.__head
        self.__head=node
        node.next.prev=node
        #第二种方法
        #node.next=self.__head
        #self.__head.prev=node
        #self.__head=node

分析:

对于头插入来说,我们首先需要对传入进来的数据进行封装成Node型,变成一个有三个域的节点,我们以第一种方法为例,请看如图
在这里插入图片描述
在这里插入图片描述
为了不改变链表原有的状态,我们需要对刚转换过来的node进行操作,那么首先需要将node的next域指向头节点所指向的节点(node.next=self.__head),然后把头指针指向node(self.__head=node),为了让其变为双向链表我们需要100的前驱指向node,( node.next.prev=node),那么100的前驱就是node.next.prev。

4、尾插入

       def append(self,data):
        """链表尾部添加元素,尾插入"""
        node=Node(data)
        if self.is_empty():
            self.__head=node
        else:
            cur=self.__head
            while cur.next !=None:
                cur=cur.next
            cur.next=node
            node.prev=cur

在这里插入图片描述
尾插入与头插入类似,但是这里要考虑链表为空的情况如果链表为空,我们直接将node插入到头节点上去,一般情况下,我们需要找到最后一个节点,所以我们就用到了cur来标记,直到cur为空就是最后一个节点,

5、索引插入

       def insert(self,pos,data):
        """指定位置添加元素"""
        if pos<=0:
            self.add(data)
        elif pos>(self.length()-1):
            self.append(data)
        else:
            cur=self.__head
            count=0
            while count<pos:
                count+=1
                cur=cur.next
            #当循环退出后,cur指向pos
            #第一种写法
            node=Node(data)
            node.next=cur
            node.prev=cur.prev
            cur.prev=node
            cur.prev.next=node
            cur.prev=node
            #第二种写法
            #node.next=cur
            #ndoe.prev=cur.prev
            #cur.pre=node
            #node.prev.next=node

在这里插入图片描述

在这里插入图片描述
对于索引插入来说,有三种情况:
(1)当插入的位置小于或者等于0相当于头插入。
(2)当插入的位置大于或者等于双向链表长度-1相当于尾部插入。
(3)一般的插入。
那对于一般插入来说,我们需要找到需要插入的地方,那么就需要用到一个count用来计数,知道count等于pos时就找到了插入的地方,在双向链表里不同与单链表的地方在于我们只需要用到一个cur标记就可以了,而对于单向链表还需要用到一个pre来标记前一个节点。
下面是对于循环单链表的插入的
在这里插入图片描述

6、删除指定元素

    def remove(self,data):
        """删除节点"""
        cur=self.__head
        while cur!=None:
            if cur==data:
                #先判断此节点是否是头节点
                #头节点
                if cur==self.__head:
                    self.__head=cur.next
                    if cur.next:
                        #判断链表是否只有一个节点
                        cur.next.prev=None
                else:
                    cur.prev.next=cur.next
                    #处理最后一个节点考虑的情况
                    if cur.next:
                        cur.next.prev=cur.prev
                break
            else:
                    pre=cur
                    cur=cur.next

这里笔者不在一一分析

7、查询元素

   def search(self,data):
        """查找节点是否存在"""
        cur=self.__head
        while cur!=None:
            if cur.data==data:
                return True
            else:
                cur=cur.next
            return False

8、遍历双向链表

    def travel(self):
        """遍历整个链表"""
        cur=self.__head
        while cur!=None:
            print(cur.elem,end=" ")
            cur=cur.next
        print(" ")

在双向链表与单链表当中 1 ,2,8,三个操作完全相同,可以使用面向对象技术通过继承来实现,这里未用到。

9、主函数:

if __name__=="__main__":
    ll=DoubleLink()
    print(ll.is_empty())
    print(ll.length())
    
    ll.append(1)
    print(ll.is_empty())
    print(ll.length())

    ll.append(2)
    ll.add(8)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    #8 1 2 3 4 5 6
    ll.insert(-1,9)#9 8 1 23456
    ll.travel()
    ll.insert(3,200)#9 8 1 100 2 3456
    ll.travel()
    ll.insert(10,200)#9 8 1 100 23456
    ll.travel()
    ll.remove(9)
    ll.travel()
    ll.remove(200)
    ll.travel()
    
    
    
    print(ll.is_empty())
    print(ll.length())    

实现的结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

William_Tao(攻城狮)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值