python数据结构基础(单链表,多链表,二叉树)
数据结构指数据对象中数据元素之间的关系
Python 给我们提供了很多现成的数据结构类型,这些系统自己定义好的,不需要我们自己去定义的数据结构叫做 Python 的内置数据结构,比如列表、元组、字典。而有些数据组织方式,Python 系统里面没有直接定义,需要我们自己去定义实现这些数据的组织方式,这些数据组织方式称之为 Python 的扩展数据结构,比如栈,队列等.
线性表:一组序列元素的组织形式,我们可以将其抽象为线性表。一个线性表是某类元素的一个集合,还记录着元素之间的一种顺序关系。线性表是最基本的数据结构之一。
根据线性表的实际存储方式,分为两种实现模型:顺序表和链表。Python 中的 list 和 tuple 两种类型采用了顺序表的实现技术。
顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活
链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理,常见的有单向链表和双向链表。
在 Python 的官方实现中,list 实现采用了如下的策略:在建立空表(或者很小的表)时,系统分配一块能容纳 8 个元素的存储区;在执行插入操作(insert 或 append)时,如果元素存储区满就换一块 4 倍大的存储区。但如果此时的表已经很大(目前的阀值为 50000),则改变策略,采用加一倍的方法。引入这种改变策略的方式,是为了避免出现过多空闲的存储位置。
单链表:
class Node():
‘’‘单链表节点类’’’
def init(self,elem):
self.elem = elem
self.next = None
class SLink():
def init(self,node=None):
if node is None:
self.__head = node
else:
self.__head = Node(node)
def is_empty(self):
return self.__head==None
def length(self):
count = 0
curNode = self.__head
while curNode != None:
count+=1
# self.__head = curNode.next
curNode = curNode.next
return count
#遍历
def travel(self):
curNode = self.__head
while curNode !=None:
print(curNode.elem,end=’\t’)
curNode= curNode.next
print()
#查找
def find(self,item):
node = Node(item)
curNode = self.__head
while curNode !=None:
if curNode.elem == node.elem:
return True
self.__head = curNode.next
curNode = curNode.next
return False
#头部添加
def add(self,item):
node = Node(item)
if self.__head == None:
self.__head=node
else:
curNode = self.__head
self.__head = node
node.next = curNode
#尾部插入
def append(self,item):
node = Node(item)
if self.__head == None:
self.__head = node
else:
curNode = self.__head
while curNode.next is not None:
curNode = curNode.next
curNode.next = node
#指定位置插入
def insert(self,num,item):
node = Node(item)
if self.__head ==None:
self.__head = node
else:
if num>self.length():
self.append(item)
return
if num<=0:
self.add(item)
return
curNode = self.__head
count = 1
p = None
while curNode is not None:
if count == num:
node.next = curNode
p.next = node
break
count+=1
p=curNode
curNode = curNode.next
#删除节点
def delete(self,item):
curNode = self.__head
preNode = None
while curNode is not None:
if curNode.elem == item:
#判断是不是头
if preNode == None:
self.__head = curNode.next
else:
preNode.next = curNode.next
return
else:
preNode = curNode
curNode = curNode.next
if name == ‘main’:
a = SLink(10)
print(a.is_empty())
print(a.length())
print(a.find(101))
a.add(1)
a.add(2)
a.add(3)
a.add(4)
a.append(5)
a.append(6)
a.append(7)
a.append(8)
a.travel()
a.insert(0,7)
a.insert(100, 7)
a.insert(4,100)
a.travel()
a.delete(100)
a.travel()
双链表
class Node():
def init(self,elem=None):
self.elem = elem
self.pre = None
self.next = None
class Dlink():
def init(self,elem=None):
if elem == None:
self.__head = None
else:
self.__head = Node(elem)
def length(self):
count = 0
curNode = self.__head
while curNode is not None:
count += 1
curNode = curNode.next
return count
def is_empty(self):
return self.__head == None
def travel(self):
if self.is_empty():
return None
curNode = self.__head
while curNode != None:
print(curNode.elem,end=’\t’)
curNode = curNode.next
print()
#头部添加
def add(self,item):
node = Node(item)
if self.is_empty():
self.__head=node
else:
curNode = self.__head
curNode.pre= node
node.next = curNode
self.__head= node
#尾部添加
def append(self,item):
node = Node(item)
if self.is_empty():
self.__head=node
else:
curNode = self.__head
while curNode.next is not None:
curNode = curNode.next
curNode.next = node
node.pre = curNode
#制定位置插入
def insert(self,num,item):
if num <= 0:
self.add(item)
elif num > self.length()-1:
self.append(item)
else:
node = Node(item)
curNode = self.__head
count = 0
while count < num-1:
count += 1
curNode = curNode.next
#这里需要注意顺序,指向会变得
node.pre = curNode
node.next = curNode.next
curNode.next.pre = node
curNode.next = node
def delete(self, item):
‘’‘删除节点’’’
curNode = self.__head
while curNode is not None:
if curNode.elem == item:
if curNode == self.__head:
self.__head = curNode.next
if curNode.next:
curNode.next.pre = None
else:
curNode.pre.next = curNode.next
if curNode.next:
curNode.next.pre = curNode.pre
break
else:
curNode = curNode.next
if name == ‘main’:
b = Dlink(10)
# print(b.length())
b.add(1)
b.add(2)
b.add(3)
b.add(4)
b.travel()
b.delete(3)
b.travel()
b.append(11)
b.append(22)
b.append(33)
b.append(44)
b.travel()
b.insert(0,100)
# b.travel()
b.insert(1, 200)
b.insert(100,300)
b.travel()
#删除节点
print(‘删除节点1’)
b.delete(1)
b.travel()
print(‘删除节点200’)
b.delete(200)
b.travel()
print(‘删除节点4’)
b.delete(4)
b.travel()
栈
栈(stack),有些地方称为堆栈,是一种容器,可存入数据元素、访问元素、删除元素,它的特点在于只能允许在容器的一端(称为栈顶端指标,英语:top)进行加入数据(英语:push)和输出数据(英语:pop)的运算。没有了位置概念,保证任何时候可以访问、删除的元素都是此前最后存入的那个元素,确定了一种默认的访问顺序。 由于栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。
队列
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 队列是一种先进先出的(First In First Out)的线性表,简称 FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作.
class Stack():
‘’‘栈的实现后进先出’’’
def init(self,):
self.__list = []
#压栈
def push(self,item):
self.__list.append(item)
#弹出元素
def pop(self,item):
return self.__list.pop()
#返回栈顶元素
def peek(self):
return self.__list[len(self.__list)-1]
#返回栈的大小
def size(self):
return len(self.__list)
def is_empty(self):
return self.__list==[]
class Queue():
‘’‘队列的实现先进先出’’’
def init(self):
self.__list=[]
def push(self,item):
self.__list.insert(0,item)
#self.list.append(item)
def pop(self):
return self.__list.pop()
#return self.__list.pop(0)
def is_empty(self):
return self.__list==[]
def size(self):
return len(self.__list)
树
树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>=1)个有限节点组成一个具有层次关系的集合
树的术语:
(1) 节点的度:一个节点含有的子树的个数称为该节点的度; (2) 树的度:一棵树中,最大的节点的度称为树的度; (3) 叶节点或终端节点:度为零的节点; (4) 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; (5) 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; (6) 兄弟节点:具有相同父节点的节点互称为兄弟节点; (7) 节点的层次:从根开始定义起,根为第 1 层,根的子节点为第 2 层,以此类推; (8) 树的高度或深度:树中节点的最大层次; (9) 堂兄弟节点:父节点在同一层的节点互为堂兄弟; (10)节点的祖先:从根到该节点所经分支上的所有节点; (11)子孙:以某节点为根的子树中任一节点都称为该节点的子孙。 (12)森林:由 m(m>=0)棵互不相交的树的集合称为森林;
树的种类
无序树: :树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
二叉树:每个节点最多含有两个子树的树称为二叉树;
完全二叉树:对于一颗二叉树,假设其深度为 d(d>1)。除了第 d 层外,其它各层的节点数目均已达最大值,且第 d 层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树,其中 满二 叉树的定义是所有叶节点都在最底层的完全二叉树;
平衡二叉树(AVL 树):当且仅当任何节点的两棵子树的高度差不大于 1 的二叉树;
排序二叉树(二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
霍夫曼树(用于信息编码):带权路径最短的二叉树称为哈夫曼树或最优二叉树;
B 树 :一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多余两个子树;
mysql数据库的索引方式之一(还有一种是hash);
二叉树:
性质 1: 在二叉树的第 i 层上至多有 2^(i-1)个节点(i>0) 性质 2: 深度为 k 的二叉树至多有 2^k - 1 个节点(k>0) 性质 3: 对于任意一棵二叉树,如果其叶节点数为 N0,而度数为 2 的结点总数为 N2,则 N0=N2+1; 性质 4:具有 n 个节点的完全二叉树的深度必为 log2(n+1) 性质 5:对完全二叉树,若从上至下、从左至右编号,则编号为 i 的结点,其左孩子编号必为 2i,其右孩子号必为 2i+1;其双亲的编号必为 i/2(i=1 时为根,除外)
(1)完全二叉树——若设二叉树的高度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
二叉树的节点及树的创建
#树结构
class Node():
‘’‘二叉树的节点类’’’
def init(self,elem):
self.elem = elem
self.lchild = None
self.rchild = None
#广度遍历,层次遍历 A,B,C,D,E,F,…
#判断A 的左节点,右节点
#判断b 的左节点,右节点
#…
class Tree():
def init(self):
self.root = None
def add(self,elem):
node = Node(elem)
#判断根节点是否存在
if self.root == None:
self.root =node
else:
queue = [self.root]
while queue:
curNode = queue.pop(0)
if curNode.lchild==None:
curNode.lchild=node
return
else:
queue.append(curNode.lchild)
if curNode.rchild==None:
curNode.rchild=node
return
else:
queue.append(curNode.rchild)
#广度优先遍历
def travel(self):
queue = []
#判断root节点是否存在
if self.root is None:
return
else:
queue.append(self.root)
while queue:
curNode = queue.pop(0)
print(curNode.elem,end='\t')
if curNode.lchild is not None:
queue.append(curNode.lchild)
if curNode.rchild is not None:
queue.append(curNode.rchild)
print()
#深度优先遍历
#先序遍历 根 左 右
def preOrder(self,root):
if root is None:
return
else:
print(root.elem,end='\t')
self.preOrder(root.lchild)
self.preOrder(root.rchild)
#中序遍历 左 根 右
def inOrder(self,root):
if root is None:
return
else:
self.inOrder(root.lchild)
print(root.elem,end='\t')
self.inOrder(root.rchild)
#后续遍历 左 右 根
def nextOrder(self,root):
if root is None:
return
else:
self.nextOrder(root.lchild)
self.nextOrder(root.rchild)
print(root.elem,end='\t')
if name==‘main’:
tree = Tree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
print(‘广度优先’)
tree.travel()
print(‘先序’)
tree.preOrder(tree.root)
print()
print(‘中序’)
tree.inOrder(tree.root)
print()
print(‘后序’)
tree.nextOrder(tree.root)