用面向对象实现Linkedlist链表

单向链表实现append、iternodes

双向链表实现append、pop、insert、remove、iternodes

单向链表与双向链表

单向链表:

就好比小朋友在操场上,手拉着手。

分为数据域和指针域,指针域指向下一个数据,代码中分别用val 和next 表示。

整个链表用一个容器来存储,因为单向链表的数据虽然真正在内存中是散落的,但是某种关系可以把这些数据有序的组织起来,所以最合适的数据结构应该是列表。列表存储还支持追加和索引,容器在代码中用self.nodes=[] 表示。

如图:内存中的数据散落存储,5表示头head,9表示tail尾。

在链表为空时,需要定义头和尾,来表示前一个数据和下一个数据,头和尾在代码中用head 和tail 分别表示,前一个数据和下一个数据用prev 和next 分别表示。

0)链表数据为空时,顺序是:head --> tail,头和尾都可以用None表示;

1)链表中有一个数据时,顺序就变成了:  head--> 数据1 -->tail;

2)链表有两个数据时,顺序变成了:head -->数据1 -->数据2 -->tail;

3)链表有三个数据时,顺序变成了:head -->数据1 -->数据2 -->数据3 -->tail

以此类推。。。

代码:

class SingleNode:
"""代表一个节点""" def __init__(self, val, next=None, prev=None):
self.val = val
self.next = next
self.prev = prev def __repr__(self):
return str(self.val) def __str__(self):
return str(self.val) class LinkedList:
"""容器类,某种方式存储一个个节点""" def __init__(self):
self.nodes = []
# 不需要插入的列表来说,检索方便,但是insert、remove不合适
self.head = None
self.tail = None def __len__(self):
return len(self.nodes) def __getitem__(self, item):
return self.nodes[item] def append(self, val):
node = SingleNode(val) # 实例化的一个新节点
prev = self.tail
if prev is None:
self.head = node
else:
prev.next = node
self.nodes.append(val)
self.tail = node def iternodes(self, reverse=False):
current = self.head
while current:
yield current
current = current.next ll = LinkedList()
ll.append(5)
ll.append(7) for node in ll.iternodes():
print(node) print(ll[0])
print(ll[1])

  

  

双向链表:

0) append 尾部追加

1) pop 尾部弹出

2) insert 头部插入、中间插入、尾部插入

3) remove 头部删除、中间删除、尾部删除

class SingleNode:
def __init__(self,val,next=None,prev=None):
self.val = val
self.next = next
self.prev = prev def __repr__(self):
return str(self.val) def __str__(self):
return str(self.val) class LinkedList:
def __init__(self):
# self.nodes = []
self.head = None
self.tail = None def append(self,val):
node = SingleNode(val)
# prev = self.tail
# if prev is None:
if self.head is None: #only one
self.head = node
else: # >1
self.tail.next = node
node.prev = self.tail
# self.nodes.append(node)
self.tail = node def iternodes(self,reverse=False):
current = self.tail if reverse else self.head
while current:
yield current
current = current.prev if reverse else current.next def pop(self):
if self.tail is None: #0个数据
raise Exception('Empty')
tail = self.tail
prev = tail.prev
# next = tail.next #尾的下一个恒定为None
if prev is None: # =0, =1
self.head = None
self.tail = None
else: # >1
self.tail = prev
prev.next = None
return tail.val def getitem(self,index): #index不考虑传入str类型,全当做int类型
if index < 0:
return None
current = None
for i,node in enumerate(self.iternodes()):
if i == index:
current = node
break
if current is not None:
return current def insert(self,index,val):
if index < 0: #不考虑负索引
raise Exception('Error')
current = None
for i, node in enumerate(self.iternodes()):
if i == index:
current = node
break
if current is None: #考虑元素为空、为一个
self.append(val)
return
#尾部、头部、中间追加
prev = current.prev
next = current.next node = SingleNode(val)
if prev is None: #头部插入
self.head = node
# node.next = current
# current.prev = node
else:
node.prev = prev
# node.next = current #和前面条件共同部分抽出来放后面
# current.prev = node
prev.next = node
node.next = current
current.prev = node def remove(self,index):
if self.tail is None:
raise Exception('Empty')
if index < 0:
raise ValueError('Wrong Index {}'.format(index)) current = None
for i,node in enumerate(self.iternodes()):
if i == index:
current = node
break
if current is None: #Not found
raise ValueError('Wrong Index {}. Out of boundary'.format(index)) prev = current.prev
next = current.next if prev is None and next is None: #only one node
self.head = None
self.tail = None
elif prev is None: #删头部
self.head = next
next.prev = None
elif next is None: #删尾部
self.tail = prev
prev.next = None
else: #中间
prev.next = next
next.prev = prev del current # def __getitem__(self, item):
# return self.nodes[item] ll = LinkedList()
ll.append('abc')
ll.append(1)
ll.append(2)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append('def') ll.insert(6,6) #边界
ll.insert(7,7) #尾部
ll.insert(8,8) #尾部
ll.insert(0,123) #头部
ll.insert(100,100) #超界 # ll.remove(100) # ll.pop()
# ll.pop() for node in ll.iternodes(False): #False
print(node)
print('~'*30)
# print(ll[0])
# print(ll[1])
ll.remove(5)
ll.remove(6)
ll.remove(0)
ll.remove(1)
for node in ll.iternodes(False): #False
print(node)

  

  

Python 单向链表、双向链表的更多相关文章

  1. Python单向链表的实现

    链表由一系列不必在内存中相连的结构构成,这些对象按线性顺序排序.每个结构含有表元素和指向后继元素的指针.最后一个单元的指针指向NULL.为了方便链表的删除与插入操作,可以为链表添加一个表头. 删除操作 ...

  2. python 单向链表实现

    单链表的操作 is_empty() 链表是否为空 length() 链表长度 travel() 遍历整个链表 add(item) 链表头部添加元素 append(item) 链表尾部添加元素 inse ...

  3. python 单向链表

    import sys import random class employee: def __init__(self): self.num= self.salary= self.name='' sel ...

  4. Python链表的实现与使用(单向链表与双向链表)

    参考[易百教程]用Python实现链表及其功能 """ python链表的基本操作:节点.链表.增删改查 """ import sys cl ...

  5. 用Python写单向链表和双向链表

    链表是一种数据结构,链表在循环遍历的时候效率不高,但是在插入和删除时优势比较大. 链表由一个个节点组成. 单向链表的节点分为两个部分:存储的对象和对下一个节点的引用.注意是指向下一个节点. 而双向链表 ...

  6. python数据结构链表之单向链表

    单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. 表元素域ele ...

  7. 玩转C线性表和单向链表之Linux双向链表优化

    前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ...

  8. 用python实现单向链表

    单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. 表元素域ele ...

  9. Java-链表(单向链表、双向链表)

    Java-链表 1.什么是链表? 2.链表的特点是什么? 3.链表的实现原理? 4.如何自己写出一个链表? 1.什么是链表? 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过 ...

随机推荐

  1. 【特效】hover向上翻转效果

    前段时间做了很多有关css3动画的项目.虽然当时都较圆满的完成了,但事后还是要总结一下的,趁着近期工作不忙,系统的学习了一些动画理论,重点看了transform3D变换,学习了translate平移. ...

  2. 【特效】jquery选项卡插件,页面多个选项卡统一调用

    把选项卡整合了一下,写成个插件,这样可以整个站,或整个页面有多个选项卡时,统一调用.代码的具体注意事项已经写进注释了.用于js获取元素的class名称必须有,选项卡本身的样式,另再取一个名字来设置(本 ...

  3. PHP中header的作用

    1.跳转: //若等待时间为0,则与header("location:")等效.  //Header("Location:http://localhost//sessio ...

  4. eclispe中安装hibernate插件

    用eclispe玩ee的朋友,写配置文件的时候没有提示非常苦恼,而配置dtd文件还是没有得到解决,最后试了试安装插件解决了问题 地址:http://download.jboss.org/jbossto ...

  5. 【ASP.NET MVC 学习笔记】- 09 Area的使用

    本文参考:http://www.cnblogs.com/willick/p/3331519.html 1.ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,这对于大的工程非常有用, ...

  6. 07-从零玩转JavaWeb-对象内存分析

    上篇看了关于数组的内存分析,接下来看一下对象的内存分析 假定有如下类:  第一步会把Person的字节码放到方法区   执行main方法,把main方法的栈帧放到栈当中   Person zly = ...

  7. 【Telerik控件学习】-建立自己的图形编辑工具(Diagram)

    Telerik提供了RadDiagram控件,用于图形元素的旋转,拖拽和缩放.更重要的是,它还拓展了许多绑定的命令(复制,剪切,粘贴,回退等等). 我们可以用来组织自己的图形编辑工具. Step1.定 ...

  8. Vue源码后记-其余内置指令(2)

    -- 指令这个讲起来还有点复杂,先把html弄上来: <body> <div id='app'> <div v-if="vIfIter" v-bind ...

  9. 版本控制之二:SVN的初步使用(转)

    转自http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407979.html 上一篇介绍了VisualSVN Server和Tortoise ...

  10. A - 棋盘问题 POJ - 1321

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. ...