用面向对象实现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. px转vw和vh的工具(对前端同学有用)

    CSS3中有两个新尺寸单位vw和vh, 这两个单位非常适合于开发移动端自适应页面. 假如说有一个设计师做了一张1136x750px的页面,这长页面是针对iPhone6的屏幕设计的. 前端开发工程师将这 ...

  2. event模拟数据库链接

    from threading import Thread,Event,currentThread import time e = Event() def conn_mysql(): count = 1 ...

  3. coursera_poj_魔兽世界终结版

    五个下午的时间!!!!终于过了!!有史以来做的最复杂的一个题这是我迄今为止做的最复杂也最具有挑战的一个oj作业.虽然之前做过比这个规模一些作业项目,但是往往有简单的模块框架,模块之前的关系也只是有些简 ...

  4. 【JAVA零基础入门系列】Day9 Java中的那个大数值

    什么是大数值?用脚趾头想也知道,当然是"大"的数值(233).Java中有两个用于表示大数值的类,BigInteger和BigDecimal,那到底能表示多大的数值呢?理论上,可以 ...

  5. Spring 3 AOP 概念及完整示例

    AOP概念 AOP(Aspect Oriented Programming),即面向切面编程(也叫面向方面编程,面向方法编程).其主要作用是,在不修改源代码的情况下给某个或者一组操作添加额外的功能.像 ...

  6. LINUX 笔记-find 命令常用用法

    命令格式: find path -option [-print] [-exec -ok] -print:find 命令将匹配的文件输出到标准输出 -exec:find 命令对匹配的文件执行该参数所给出 ...

  7. 脚本div实现拖放功能

    脚本div实现拖放功能 网页上有很多拖曳的操作,比如拖动树状列表,可拖曳的图片等. 1.原生拖放实现 <!doctype html> <html lang="en" ...

  8. hibernate和mybatis区别

    看图    Hibernate mybatis 难易度 难 简单,容易上手 编码 良好的映射机制,不需要关心 需要手动编写sql,resultMap 调优 制定合理的缓存策略: 尽量使用延迟加载特性: ...

  9. LeetCode 697. Degree of an Array (数组的度)

    Given a non-empty array of non-negative integers nums, the degree of this array is defined as the ma ...

  10. LeetCode 461. Hamming Distance (汉明距离)

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...