[数据结构与算法] 链表的其他类型
时间:2022-05-08
本文章向大家介绍[数据结构与算法] 链表的其他类型,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
单链表是最简单的链表,单链表的一种变形就是循环单链表,其中最后一个结点的next域不用None,而是指向表的第一个结点,这样就形成了一种循环结构,所以叫循环单链表。
双链表:单链表只有1个方向的链接,只能做一个方向的扫描和逐步操作。单链表的next指针域指向下一个结点,而双链表结点除了具有next指针外,还有一个previous指针,指向上一个结点。单链表中查找元素只能从头结点开始,根据他的next指针域找到下一个结点,而双链表最大的区别在于不仅能找到下一个结点,还能找到上一个结点。
循环双链表:然后看下什么是循环双链表,循环单链表是把最后一个结点的next指针域指向了首结点,而循环双链表除了这个以外,还有首结点的previous指针域指向尾结点。这就是循环双链表。
下面用Python实现循环单链表和双链表。
Github : https://github.com/Alvin2580du/Data-Structures-and-Algorithms.git
# - * - coding:utf-8 - * -
"""定义节点类"""
class LNode:
def __init__(self, x, next_=None):
self.elem = x
self.next = next_
"""
定义单链表类
"""
class LList:
def __init__(self):
self._head = None
def length(self):
count = 0 # 数目
# 当前节点
current = self._head
while current != None:
count += 1
# 当前节点往后移
current = current.next
return count
def is_empty(self):
return self._head is None
def prepend(self, elem):
self._head = LNode(elem, self._head)
"""在链表头部添加元素"""
def add(self, elem):
node = LNode(elem)
# 结点的next指针域指向头结点
node.next = self._head
# 头结点称为新的结点
self._head = node
def pop(self):
if self._head is None:
raise ValueError("in pop")
e = self._head.elem
self._head = self._head.next
print("head is :%s" % self._head)
return e
# 后端操作
def append(self, elem):
# 当链表为空时
if self._head is None:
self._head = LNode(elem)
return
current = self._head
while current.next is not None:
current = current.next
current.next = LNode(elem)
def pop_last(self):
if self._head is None:
raise ValueError("in pop_last")
p = self._head
if p.next is None:
e = p.elem
self._head = None
return e
while p.next.next is not None:
p = p.next
e = p.next.elem
p.next = None
return e
def find(self, pred):
p = self._head
while p is not None:
if pred(p.elem):
return p.elem
p = p.next
def printall(self):
p = self._head
while p is not None:
if p.next is not None:
print(', ')
p = p.next
"""
定义循环单链表类
"""
class LCList:
def __init__(self):
self._head = None
def is_empty(self):
return self._head is None
# 求链表长度
def length(self):
if self.is_empty():
return 0
count = 1 # 数目
# 当前节点
current = self._head
# 当前节点的下一个节点不是头结点则继续增加
while current.next != self._head:
count += 1
# 当前节点往后移
current = current.next
return count
# add(elem) 链表头部添加元素
def add(self, elem):
node = LNode(elem)
if self.is_empty():
# 空链表
self.__head = node
node.next = node
else:
# 非空链表添加
current = self.__head
# 查找最后一个节点
while current.next != self.__head:
current = current.next
# 新节点的下一个节点为旧链表的头结点
node.next = self.__head
# 新链表的头结点为新节点
self.__head = node
# 最后节点的下一个节点指向新节点
current.next = node
def prepend(self, elem):
p = LNode(elem)
# 如果为空
if self._head is None:
p.next = p
self._head = p
else:
p.next = self._head.next
self._head.next = p
def append(self, elem):
self.prepend(elem)
self._head = self._head.next
def pop(self):
if self._head is None:
raise ValueError("in pop of CLList")
p = self._head.next
if self._head is p:
self._head = None
else:
self._head.next = p.next
return p.elem
# search(elem) 查找节点是否存在
def search(self, elem):
# 当前节点
if self.is_empty():
# 空链表直接返回False
return False
current = self.__head
while current.next != self.__head:
if current.elem == elem:
# 找到了
return True
else:
current = current.next
# 判断最后一个元素
if current.elem == elem:
return True
return False
def printall(self):
if self.is_empty():
return
p = self._head.next
while True:
print (p.elem)
if p is self._head:
break
p = p.next
"""定义双链表结点类,在LNode的基础上派生类"""
class DLNode(LNode):
def __init__(self, elem, prev=None, next_=None):
LNode.__init__(self, elem, next_)
self.prev = prev
"""
定义双链表类
"""
class Double_LList(LList):
def __init__(self):
LList.__init__(self)
def is_empty(self):
return self._head is None
# length() 链表长度
def length(self):
count = 0 # 数目
# 当前节点
current = self._head
while current != None:
count += 1
# 当前节点往后移
current = current.next
return count
# add(elem) 链表头部添加元素
def add(self, elem):
node = DLNode(elem)
# 新节点的下一个节点为旧链表的头结点
node.next = self.__head
# 新链表的头结点为新节点
self.__head = node
# 下一个节点的上一个节点指向新增的节点
# 相当于是第一个结点指向新添加结点
node.next.prev = node
def prepend(self, elem):
p = DLNode(elem, None, self._head)
if self._head is None:
self._head = p
else:
p.prev.prev = p
self._head = p
def append(self, elem):
p = DLNode(elem, self._head, None)
if self._head is None:
self._head = p
else:
p.prev.next = p
self._head = p
def pop(self):
if self._head is None:
raise ValueError("in pop_last of DDList")
e = self._head.elem
self._head = self._head.next
if self._head is not None:
self._head.prev = None
return e
def pop_last(self):
if self._head is None:
raise ValueError("in pop_last of DLList")
e = self._head.elem
self._head = self._head.prev
if self._head is None:
self._head = None
else:
self._head.next = None
return e
- 深入剖析-Oracle索引分支块的结构
- 【直播】我的基因组48:我可能测了一个假的全基因组
- 【直播】我的基因组47:测序深度和GC含量的关系
- 【直播】我的基因组47:测序深度和GC含量的关系
- SNV突变(96种)频谱的制作
- Golang语言社区--go语言执行cmd命令关机、重启等
- 【直播】我的基因组 45:SNV突变(6种)频谱的制作
- 【直播】我的基因组 44:比对文件画profile和heatmap图
- 做过1000遍RNA-seq的老司机告诉你如何翻车
- 【直播】我的基因组 43:简单粗糙的WGS数据分析流程
- 用谷歌搜索来使用ggplot2做可视化(下)
- 如何通过Google来使用ggplot2可视化
- 【直播】我的基因组54:把我的variation跟dbSNP数据库相比较
- 【翻译】MongoDB指南/引言
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 树莓派基础实验26:旋转编码器实验
- java web Session会话技术(原理图解+功能+与Cookie的区别+基本使用)
- JAVA创建对象有哪几种方式
- Apache IoTDB 系列教程-7:时序数据文件格式 TsFile
- XSS原理及代码分析
- 树莓派基础实验27:温湿度传感器DHT11 实验
- org.apache.jasper.JasperException: Unable to compile class for JSP
- 树莓派基础实验28:红外避障传感器实验
- Java Filter过滤器(拦截路径的配置+拦截方式的配置+生命周期+多个过滤器的先后执行顺序)
- Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念
- 树莓派基础实验29:I2C LCD1602实验
- Java Redis系列2 (redis的安装与使用+redis持久化的实现))
- Apache IoTDB 系列教程-1:数据模型
- Java Redis系列3(Jedis的使用+jedis连接池技术)
- kali中安装漏洞靶场Vulhub(超详细)