链表

链表与栈,队列不一样,它是由一个个节点构成的,每个节点存储着本身的一些信息,也存储着其他一个或多个节点的引用,可以从一个节点找到其他的节点,节点与节点之间就像是有链连在一起一样,这种数据结构就叫做链表

单向链表

单向链表是链表的最简单形式,链表的第一个节点叫做头结点,最后一个节点叫做尾节点,每个节点都指向下一个节点,尾节点的指向为空,下面是其具体实现


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实现数据结构之链表的更多相关文章

  1. python实现数据结构单链表

    #python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...

  2. Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现

    单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...

  3. Python与数据结构[0] -> 链表/LinkedList[1] -> 双链表与循环双链表的 Python 实现

    双链表 / Doubly Linked List 目录 双链表 循环双链表 1 双链表 双链表和单链表的不同之处在于,双链表需要多增加一个域(C语言),即在Python中需要多增加一个属性,用于存储指 ...

  4. Python与数据结构[0] -> 链表/LinkedList[2] -> 链表有环与链表相交判断的 Python 实现

    链表有环与链表相交判断的 Python 实现 目录 有环链表 相交链表 1 有环链表 判断链表是否有环可以参考链接, 有环链表主要包括以下几个问题(C语言描述): 判断环是否存在: 可以使用追赶方法, ...

  5. python 与数据结构

    在上面的文章中,我写了python中的一些特性,主要是简单为主,主要是因为一些其他复杂的东西可以通过简单的知识演变而来,比如装饰器还可以带参数,可以使用装饰类,在类中不同的方法中调用,不想写的太复杂, ...

  6. python 数据结构中的链表操作

    链表的定义: 链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址.由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就 ...

  7. 学习javascript数据结构(二)——链表

    前言 人生总是直向前行走,从不留下什么. 原文地址:学习javascript数据结构(二)--链表 博主博客地址:Damonare的个人博客 正文 链表简介 上一篇博客-学习javascript数据结 ...

  8. [0x00 用Python讲解数据结构与算法] 概览

    自从工作后就没什么时间更新博客了,最近抽空学了点Python,觉得Python真的是很强大呀.想来在大学中没有学好数据结构和算法,自己的意志力一直不够坚定,这次想好好看一本书,认真把基本的数据结构和算 ...

  9. Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET

    Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET Python -- 堆数据结构 heapq 分类: Python 2012-09 ...

随机推荐

  1. 关于jquery中prev()和next()的用法

    用prev()和next()方法动态的添加class.以达到当前元素的前面几个元素或后面的几个元素添加class <body> <ul> <li>1</li& ...

  2. Django--cookie操作

    day74 会话跟踪技术 什么是会话跟踪 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而 ...

  3. Lock接口

    Lock与synchronized Lock和synchronized在功能上是一样的.不过Lock提供了一些其他功能,包括定时的锁等待.可中断的锁等待.公平性,以及实现非块结构的加锁. 从性能上Lo ...

  4. 使用 JRebel 进行远程热部署

    JRebel支持热部署,和远程热部署,本文我们来搭建一下远程热部署. 一.服务器安装 JRebel 1.官网下载最新的 JRebel 安装包,下载链接:https://zeroturnaround.c ...

  5. Android_GLSurfaceView

    使用open GL ES 绘制三角形 首先自定义一个GLSurfaceView class MyGLSurceView extends GLSurfaceView { public MyGLSurce ...

  6. 全网最详细的Eclipse和MyEclipse里对于Java web项目发布到Tomcat上运行成功的对比事宜【博主强烈推荐】【适合普通的还是Maven方式创建的】(图文详解)

    不多说,直接上干货! 首先,大家要明确,IDEA.Eclipse和MyEclipse等编辑器之间的新建和运行手法是不一样的. 全网最详细的MyEclipse里如何正确新建普通的Java web项目并发 ...

  7. Java并发编程笔记之ReentrantLock源码分析

    ReentrantLock是可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞后放入该锁的AQS阻塞队列里面. 首先我们先看一下ReentrantLock的类图结构,如下图所示 ...

  8. CentOS7修改默认启动级别

    如上个随笔所言,Linux分为7个启动级别: 0 - 系统停机状态 1 - 单用户工作状态 2 - 多用户状态(没有NFS) 3 - 多用户状态(有NFS) 4 - 系统未使用,留给用户 5 - 图形 ...

  9. mybatis教程1(基本使用)

    官方网站 一.什么是 MyBatis ? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果 ...

  10. 理解运用JS的闭包、高阶函数、柯里化

    JS的闭包,是一个谈论得比较多的话题了,不过细细想来,有些人还是理不清闭包的概念定义以及相关的特性. 这里就整理一些,做个总结. 一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执 ...