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())    

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

### 解决PyCharm无法加载Conda虚拟环境的方法 #### 配置设置 为了使 PyCharm 能够成功识别并使用 Conda 创建的虚拟环境,需确保 Anaconda 的路径已正确添加至系统的环境变量中[^1]。这一步骤至关重要,因为只有当 Python 解释器及其关联工具被加入 PATH 后,IDE 才能顺利找到它们。 对于 Windows 用户而言,在安装 Anaconda 时,默认情况下会询问是否将它添加到系统路径里;如果当时选择了否,则现在应该手动完成此操作。具体做法是在“高级系统设置”的“环境变量”选项内编辑 `Path` 变量,追加 Anaconda 安装目录下的 Scripts 文件夹位置。 另外,建议每次新建项目前都通过命令行先激活目标 conda env: ```bash conda activate myenvname ``` 接着再启动 IDE 进入工作区,这样有助于减少兼容性方面的问题发生概率。 #### 常见错误及修复方法 ##### 错误一:未发现任何解释器 症状表现为打开 PyCharm 新建工程向导页面找不到由 Conda 构建出来的 interpreter 列表项。此时应前往 Preferences/Settings -> Project:...->Python Interpreter 下方点击齿轮图标选择 Add...按钮来指定自定义的位置。按照提示浏览定位到对应版本 python.exe 的绝对地址即可解决问题。 ##### 错误二:权限不足导致 DLL 加载失败 有时即使指定了正确的解释器路径,仍可能遇到由于缺乏适当的操作系统级许可而引发的功能缺失现象。特别是涉及到调用某些特定类型的动态链接库 (Dynamic Link Library, .dll) 时尤为明显。因此拥有管理员身份执行相关动作显得尤为重要——无论是从终端还是图形界面触发创建新 venv 流程均如此处理能够有效规避此类隐患。 ##### 错误三:网络连接异常引起依赖下载超时 部分开发者反馈过因网速慢或者其他因素造成 pip install 操作中途断开进而影响整个项目的初始化进度条卡住的情况。对此可尝试调整镜像源加速获取速度或是离线模式预先准备好所需资源包后再继续后续步骤。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

William_Tao(攻城狮)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值