双向循环链表是在双向链表的基础上发展的,双向链表的最后一个节点指向起始节点,起始节点的上一个节点指向最后一个节点,就得到双向循环链表。

双向循环链表比双向链表具有更多的优势,节点的增加和删除有很多优化的地方,从起点开始不必循环完整个链表就可以增加或删除节点。

首先定义双向链表的基本类和节点的基本类:

image

class Node:

def __init__(self, item):

self.item = item # 该节点值

self.next = None # 连接一下一个节点

self.prev = None # 上一个节点值

class DoubleCircularLinkedList:

"""双向循环列表类"""

def __init__(self):

self._head = None

下面我们添加基本属性方法的逻辑,注意判断是否为最后一个节点的方式是:最后一个节点的下一个节点是否指向头部指向的节点。

class Node:

def __init__(self, item):

self.item = item # 该节点值

self.next = None # 连接一下一个节点

self.prev = None # 上一个节点值

class DoubleCircularLinkedList:

"""双向循环列表类"""

def __init__(self):

self._head = None

@property

def is_empty(self):

"""

判断链表是否为空

:return:

"""

return not self._head

@property

def length(self):

"""

链表长度

:return:

"""

if self.is_empty:

return 0

else:

cur = self._head.next

n = 1

while cur != self._head:

cur = cur.next

n += 1

return n

@property

def ergodic(self):

"""

遍历链表

:return:

"""

if self.is_empty:

raise ValueError("ERROR NULL")

else:

cur = self._head.next

print(self._head.item)

while cur != self._head:

print(cur.item)

cur = cur.next

链表类的操作有几个核心的地方,第一个是判断是否为最后一个节点,通过链表的相关特性,如单向链表最后一个节点的next属性为None、单向循环链表的最后一个节点的next属性等于头部节点;第二个是使用游标来替代节点指向,这个在操作节点的时候需要有时还需要两个游标,但是对于双向节点而言只需要一个游标,通过当前节点的属性可以找到上下节点。

继续给对象添加方法:头部插入节点、尾部添加节点、任意位置插入节点。

class Node:

def __init__(self, item):

self.item = item # 该节点值

self.next = None # 连接一下一个节点

self.prev = None # 上一个节点值

class DoubleCircularLinkedList:

"""双向循环列表类"""

def __init__(self):

self._head = None

@property

def is_empty(self):

"""

判断链表是否为空

:return:

"""

return not self._head

@property

def length(self):

"""

链表长度

:return:

"""

if self.is_empty:

return 0

else:

cur = self._head.next

n = 1

while cur != self._head:

cur = cur.next

n += 1

return n

@property

def ergodic(self):

"""

遍历链表

:return:

"""

if self.is_empty:

raise ValueError("ERROR NULL")

else:

cur = self._head.next

print(self._head.item)

while cur != self._head:

print(cur.item)

cur = cur.next

def add(self, item):

"""

头部添加节点

:return:

"""

node = Node(item)

if self.is_empty:

node.next = node

node.prev = node

self._head = node

else:

node.next = self._head

node.prev = self._head.prev

self._head.prev.next = node

self._head.prev = node

self._head = node

def append(self, item):

"""

尾部添加节点

:param item:

:return:

"""

if self.is_empty:

self.add(item)

else:

node = Node(item)

cur = self._head.next

while cur.next != self._head:

cur = cur.next

cur.next = node

node.prev = cur

node.next = self._head

self._head.prev = node

def insert(self, index, item):

"""

任意位置插入节点

:param item:

:return:

"""

if index == 0:

self.add(item)

elif index+1 >= self.length:

self.append(item)

else:

cur = self._head.next

n = 1

while cur.next != self._head:

if n == index:

break

cur = cur.next

n += 1

node = Node(item)

node.prev = cur.prev

cur.prev.next = node

node.next = cur

cur.prev = node

接着实现判断节点是否存在以及删除指定节点。

class Node:

def __init__(self, item):

self.item = item # 该节点值

self.next = None # 连接一下一个节点

self.prev = None # 上一个节点值

class DoubleCircularLinkedList:

"""双向循环列表类"""

def __init__(self):

self._head = None

@property

def is_empty(self):

"""

判断链表是否为空

:return:

"""

return not self._head

@property

def length(self):

"""

链表长度

:return:

"""

if self.is_empty:

return 0

else:

cur = self._head.next

n = 1

while cur != self._head:

cur = cur.next

n += 1

return n

@property

def ergodic(self):

"""

遍历链表

:return:

"""

if self.is_empty:

raise ValueError("ERROR NULL")

else:

cur = self._head.next

print(self._head.item)

while cur != self._head:

print(cur.item)

cur = cur.next

def add(self, item):

"""

头部添加节点

:return:

"""

node = Node(item)

if self.is_empty:

node.next = node

node.prev = node

self._head = node

else:

node.next = self._head

node.prev = self._head.prev

self._head.prev.next = node

self._head.prev = node

self._head = node

def append(self, item):

"""

尾部添加节点

:param item:

:return:

"""

if self.is_empty:

self.add(item)

else:

node = Node(item)

cur = self._head.next

while cur.next != self._head:

cur = cur.next

cur.next = node

node.prev = cur

node.next = self._head

self._head.prev = node

def insert(self, index, item):

"""

任意位置插入节点

:param item:

:return:

"""

if index == 0:

self.add(item)

elif index+1 >= self.length:

self.append(item)

else:

cur = self._head.next

n = 1

while cur.next != self._head:

if n == index:

break

cur = cur.next

n += 1

node = Node(item)

node.prev = cur.prev

cur.prev.next = node

node.next = cur

cur.prev = node

def search(self, item):

"""

查找节点是否存在

:return:

"""

if self.is_empty:

return False

else:

cur = self._head.next

if self._head.item == item:

return True

else:

while cur != self._head:

if cur.item == item:

return True

else:

cur = cur.next

return False

def delete(self, item):

"""

删除指定值的节点

:param item:

:return:

"""

if self.is_empty:

raise ValueError("ERROR NULL")

else:

if self._head.item == item:

if self.length == 1:

self._head = Node

else:

self._head.prev.next = self._head.next

self._head.next.prev = self._head.prev

self._head = self._head.next

cur = self._head.next

while cur != self._head:

if cur.item == item:

cur.prev.next = cur.next

cur.next.prev = cur.prev

cur = cur.next

只以基本的思路实现基本的方法,对于双向循环链表而言还有很多可以优化的地方,正向遍历和逆向遍历获得结果的时间是不一样的。

image

python 双向循环链表实现_python实现双向循环链表基本结构及其基本方法相关推荐

  1. python rsa 公钥解密_python利用rsa库做公钥解密的方法教程

    前言 对于RSA的解密,即密文的数字的 D 次方求mod N 即可,即密文和自己做 D 次乘法,再对结果除以 N 求余数即可得到明文.D 和 N 的组合就是私钥(private key). 算法的加密 ...

  2. python编写ATM类_Python中编写类的各种技巧和方法

    有关 Python 内编写类的各种技巧和方法(构建和初始化.重载操作符.类描述.属性访问控制.自定义序列.反射机制.可调用对象.上下文管理.构建描述符对象.Pickling).你可以把它当作一个教程, ...

  3. python 字符串去空格_Python去除、替换字符串空格的处理方法

    个人想到的解决方法有两种,一种是 .replace(' old ',' new ') 第一个参数是需要换掉的内容比如空格,第二个是替换成的内容,可以把字符串中的空格全部替换掉. 第二种方法是像这样 s ...

  4. python读取txt文件_python实现读写txt文件的几种方法

    一.读写模式: w:向文件中写入内容,w会清空原来文本内容 a:向文件中追加内容 r:从文件中读取内容 wb:以二进制形式写入内容. rb:以二进制形式读文件内容 ab:以二进制形式追加内容 a+.r ...

  5. python数据库安装教程_python MySQLdb Windows下安装教程及问题解决方法

    使用python访问mysql,需要一系列安装 linux下MySQLdb安装见 Python MySQLdb在Linux下的快速安装 https://www.jb51.net/article/657 ...

  6. python获取输入数字_python获取从命令行输入数字的方法

    本文实例讲述了python获取从命令行输入数字的方法.分享给大家供大家参考.具体如下: #---------------------------------------- # Name: numeri ...

  7. python处理文本格式_python linecache 处理固定格式文本数据的方法

    小程序大功能 对一批报文要处理要处理里面的得分,发现python linecache ,特记录如下. #!/usr/bin/env python # -*- coding: utf-8 -*- ''' ...

  8. python控制台不能输入_python实现在控制台输入密码不显示的方法

    本文实例讲述了python实现在控制台输入密码不显示的方法.分享给大家供大家参考.具体实现方法如下: import console; namespace console{ //控制台读取密码,并显示星 ...

  9. math python 向上取整_Python的数值基本运算和其它数学运算方法

    数值基本运算 支持最基本的数学运算符号:+ - * / % **.取正负+x -x,地板除法//,除法和取模divmod(x, y): 12345678910111213141516171819202 ...

最新文章

  1. 23 岁的 Java 成为编程界的扛把子,网友回复:这就是实力
  2. java常用数据类型之间转换
  3. 如何用笔记本建立wifi热点
  4. cf1208E. Let Them Slide
  5. 速达服务器账套定期维护么,速达软件常见操作问题解决方法
  6. debian dhcp服务启动不了_网刻批量装系统pxe启动教程全自动分区装系统
  7. css背景图充满整个屏幕
  8. [Asp.net]Uploadify上传大文件,Http error 404 解决方案 - wolfy
  9. c语言程序设计逗号作用,逗号运算符C语言程序设计.pdf
  10. 命令行删除RMS SCP 连接点
  11. thinkPHP框架
  12. tableau实战系列(十二)-使用盒须图查看你的数据分布
  13. python天眼查爬虫_学习Python3 天眼查 爬虫
  14. 第一次开发EOS区块链的经验总结
  15. 【面试总结】JNI层MediaScanner的分析,挥泪整理面经
  16. 服务器更新维护公告语,6月1日阴阳师服务器更新维护内容公告
  17. 在C语言中如何产生随机数
  18. Android游戏源码合集(主要是AndEngine和Libgdx的)
  19. 编写ESM风格的nodejs应用
  20. Windows 如何配置 scratch 3.0 GUI

热门文章

  1. 2020年的风口来了!传统企业如何做数字化转型?
  2. 飞鸽传书下载 分析企业OpenEIM
  3. 努力的钻研深层次的【飞鸽传书】技术
  4. 企业巧妙运用飞秋提高工作效率
  5. 程序员救赎之路:从“996”到微软“4天6小时工作制”
  6. 清华2020计算机系张晨,2020清华特奖入围名单公布:电子系学霸两篇顶会一作
  7. php xmldom扩展,如何使用比根更深入的PHP DOM向XML添加新元素?
  8. 机器学习 | 网络搜索及可视化
  9. 图像入门二之视频操作
  10. 复现原文(一):Single-cell RNA sequencing of human kidney(step by step)