用Python实现数据结构之链表
链表
链表与栈,队列不一样,它是由一个个节点构成的,每个节点存储着本身的一些信息,也存储着其他一个或多个节点的引用,可以从一个节点找到其他的节点,节点与节点之间就像是有链连在一起一样,这种数据结构就叫做链表
单向链表
单向链表是链表的最简单形式,链表的第一个节点叫做头结点,最后一个节点叫做尾节点,每个节点都指向下一个节点,尾节点的指向为空,下面是其具体实现
class Empty(Exception):
pass
class LinkedList():
class Node():
def __init__(self,element,next):
self.element = element
self.next = next
def __init__(self):
self.head = None
self.size = 0
def add_head(self,e):
new = self.Node(e,self.head)
self.head = new
self.size +=1
def remove_first(self):
if self.size == 0:
raise Empty('linkedlist is empty')
self.head = self.head.next
self.size -= 1
这个链表没有保存尾指针,并且添加与删除只在头部进行,节点类的定义嵌套在了其中
循环链表
循环链表即为单向链表的尾部不再指向空,而是指向头部,这样就不再需要头指针和尾指针了,只需要一个指向尾部的就行,下面是一个用循环链表实现的队列
class CircularQueue():
"""
使用循环链表实现的队列
"""
class Node():
def __init__(self, element, next):
self.element = element
self.next = next
def __init__(self):
self.tail = None
self.size = 0
def __len__(self):
return self.size
def is_empty(self):
return self.size == 0
def first(self):
if self.is_empty():
raise Empty('Queue is empty')
return self.tail.next.element
def dequeue(self):
if self.is_empty():
raise Empty('Queue is empty')
old_head = self.tail.next
if self.size == 1:
self.tail = None
else:
self.tail.next = old_head.next
self.size -= 1
return old_head.element
def enqueue(self, e):
new = self.Node(e, None)
if self.is_empty():
new.next = new
else:
new.next = self.tail.next
self.tail.next = new
self.tail = new
self.size += 1
def rotate(self):
"""
将队列的头部变为尾部,循环移动一位
"""
if self.size > 0:
self.tail = self.tail.next
这里需要注意些的地方就是队列的插入与删除,因为涉及到节点指向的变换,其实手动画画图的话还是非常容易理解的
双向链表
前边的单向链表,循环链表,都是每一个节点为其后继节点维护一个引用,这样就会导致一些限制,即如果给定链表中的一个节点的引用,我们很难将其删掉,因为它并没有存储前驱节点的引用,对于这样的问题,我们会想到使用一种既存储前驱也存储后继的节点,这就是双向链表
实现的想法
之前的两种链表都是直接存储了头结点的引用,这样使我们在执行某些方法时,必须要判断一下是不是头结点,是不是为节点,为了避免这些特殊情况我们可以在链表的头部与尾部分别追加一个存储为空的头部节点与存储为空的尾部节点,我们叫它头哨兵与尾哨兵,这两个哨兵并不在序列中,并且只占用很少的空间,但却可以简化许多有关节点的操作。
具体实现
class DoubleLinkedList():
"""
具有头哨兵与尾哨兵的双向链表
"""
class Node():
def __init__(self,element,prev,next):
self.element = element
self.prev = prev
self.next = next
def __init__(self):
self.head = self.Node(None,None,None)
self.tail = self.Node(None,None,None)
self.head.next = self.tail
self.tail.prev = self.head
self.size = 0
def __len__(self):
return self.size
def is_empty(self):
return self.size == 0
def insert_between(self,e,predecessor,successor):
new = self.Node(e,predecessor,successor)
predecessor.next = new
successor.prev = new
self.size += 1
return new
def delete_node(self,node):
predecessor = node.prev
successor = node.next
predecessor.next = successor
successor.prev = predecessor
element = node.element
self.size -= 1
node.prev=node.next=None
return element
insert_between传入的是元素与前驱节点和后继节点
delete_node传入的是要删除的节点
参考《数据结构与算法Python语言实现》
用Python实现数据结构之链表的更多相关文章
- python实现数据结构单链表
#python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...
- Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现
单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...
- Python与数据结构[0] -> 链表/LinkedList[1] -> 双链表与循环双链表的 Python 实现
双链表 / Doubly Linked List 目录 双链表 循环双链表 1 双链表 双链表和单链表的不同之处在于,双链表需要多增加一个域(C语言),即在Python中需要多增加一个属性,用于存储指 ...
- Python与数据结构[0] -> 链表/LinkedList[2] -> 链表有环与链表相交判断的 Python 实现
链表有环与链表相交判断的 Python 实现 目录 有环链表 相交链表 1 有环链表 判断链表是否有环可以参考链接, 有环链表主要包括以下几个问题(C语言描述): 判断环是否存在: 可以使用追赶方法, ...
- python 与数据结构
在上面的文章中,我写了python中的一些特性,主要是简单为主,主要是因为一些其他复杂的东西可以通过简单的知识演变而来,比如装饰器还可以带参数,可以使用装饰类,在类中不同的方法中调用,不想写的太复杂, ...
- python 数据结构中的链表操作
链表的定义: 链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址.由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就 ...
- 学习javascript数据结构(二)——链表
前言 人生总是直向前行走,从不留下什么. 原文地址:学习javascript数据结构(二)--链表 博主博客地址:Damonare的个人博客 正文 链表简介 上一篇博客-学习javascript数据结 ...
- [0x00 用Python讲解数据结构与算法] 概览
自从工作后就没什么时间更新博客了,最近抽空学了点Python,觉得Python真的是很强大呀.想来在大学中没有学好数据结构和算法,自己的意志力一直不够坚定,这次想好好看一本书,认真把基本的数据结构和算 ...
- Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET
Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET Python -- 堆数据结构 heapq 分类: Python 2012-09 ...
随机推荐
- webServlet("/") 和 webServlet("/*") 的区别
“/” 默认放行了jsp,也就是jsp文件不执行下面的service方法,其他都执行 “/*” 全部执行
- 【OSX】解决编译AOSP时需要10.5/10.6 SDK下载
有人遇到的是需要10.6的sdk. 公司网快下载了xcode, 把里面的10.5sdk和10.6sdk拿出来, 一共才一百多兆…… 下载链接: http://pan.baidu.com/s/1gdxG ...
- [Java初探外篇]__关于正则表达式
正则表达式通常用于判断语句之中,用来检测一段字符串是否满足某一个格式.在日常生活中被广泛的用于各种用户输入信息的检测上. 而正则表达式实际上是一些具有特殊意义的字符序列.通过这些特殊字符构成的特殊序列 ...
- AOP技术基础(转)
1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...
- 图片人脸检测——OpenCV版(二)
图片人脸检测 人脸检测使用到的技术是OpenCV,上一节已经介绍了OpenCV的环境安装,点击查看. 往期目录 视频人脸检测——Dlib版(六)OpenCV添加中文(五)图片人脸检测——Dlib版(四 ...
- Go 标准库 —— sync.Mutex 互斥锁
Mutex 是一个互斥锁,可以创建为其他结构体的字段:零值为解锁状态.Mutex 类型的锁和线程无关,可以由不同的线程加锁和解锁. 方法 func (*Mutex) Lock func (m *Mut ...
- 如何调试Javascript代码以及网页代码
做过网页开发的都知道,不过你是用php还是asp.net以及java开发的网站,在开发过程中,web网页展示页面肯定会出现或多或少的问题.这里我推荐使用谷歌浏览器进行Web网页的调试以及错误信息定位. ...
- C# 循环语句 for
循环:反复执行某段代码. 循环四要素:初始条件,循环条件,循环体,状态改变. for格式 for(初始条件;循环条件;状态改变) { 循环体 } break ——中断循环,跳出整个循环 continu ...
- JavaSE Lambda表达式(JDK1.8新特性)
在前面有一篇写到了Lambda表达式,现在可以给你们介绍什么是Lambda表达式 现在有很多老程序员都不喜欢这个函数式编程思想 主要就一点 : 老程序员习惯了 面向过程 写程序,而Lambda表达式是 ...
- 第一个SpringBoot程序
第一个SpringBoot程序 例子来自慕课网廖师兄的免费课程 2小时学会SpringBoot Spring Boot进阶之Web进阶 使用IDEA新建工程,选择Spring Initializr,勾 ...