链表
(单链表 双链表 循环链表)只是一个定义的结构而已 (数据结构不一样而已)
具体的对这个定义的操作要到这个定义实现的类当中去调用而已

概念区分
-
头结点:是为了方便操作链表而附设的,头结点数据域通常用来保存跟链表有关的信息,比如链表的长度;
-
首元结点:就是链表里“正式”的第一个结点,即链表的开始结点。形如a1,a2,a3,…an;
-
头指针:头指针是指向链表的基地址。如果链表存在头结点则头指针就是指向头结点的地址,反之指向首元结点的地址。
#定义节点类型
class Node(object):
def __init__(self,elem,next_=None):
self.elem=elem
self.next=next_
#定义单链表
class Linklist(object):
def __init__(self,none=None):
self.head=none
#判断链表是否为空
def is_empty(self):
return self.head==None
#获取链表长度
def length(self):
cur=self.head#获取首元节点
count=0
while cur!=None:
count+=1
cur=cur.next
return count
#遍历链表
def travel(self):
cur=self.head
while cur!=None:
print(cur.elem,end=" ")
cur =cur.next
#输出一个换行
print('')
#首部加元素
def add(self,item):
#将数据转换为节点类型
node=Node(item)
#新的节点指向首元节点
node.next=self.head
#新的节点变成首元节点
self.head=node
#尾部加元素
def append(self,item):
node=Node(item)
#判断是否为空
if self.is_empty():
#为空此节点就是首元节点
self.head=node
else:
cur=self.head
while cur.next!=None:
# 遍历到最后一个节点
cur=cur.next
cur.next=node
#在指定位置添加节点
def insert(self,pos,item):
if pos<0:
self.add(item)
elif pos>(self.length()-1):
self.append(item)
else:
node=Node(item)
cur=self.head
count=0
while count<(pos-1):
count+=1
cur= cur.next
node.next=cur.next
cur.next=node
#删除指定值的节点
def remove(self,item):
cur=self.head
pre=None
while cur != None:
if cur.elem==item:
#如果当前节点的值符合要求
if cur==self.head:
#如果符合的节点是首元节点
self.head=cur.next
break
else:
#从当前节点的前一个节点直接指向当前节点的下一个节点
pre.next=cur.next
break
else:
#当前节点不符合
pre=cur#记录当前节点的位置
cur=cur.next
#查询某个值是否存在
def search(self,item):
cur=self.head
while cur!=None:
if cur.elem==item:
return True
else:
cur=cur.next
return False
if __name__=='__main__':
linklist=Linklist()
for i in range(5):
linklist.append(i)
linklist.travel()
linklist.insert(3,7)
linklist.travel()
print(linklist.search(4))
linklist.remove(7)
linklist.travel()
栈
特点:插入和删除操作只能在一个位置进行的表,该位置是表的末端,称为栈的顶(top)。
先进后出
具体操作
- Stack() 创建一个新的空栈
- push(item) 添加一个新的元素item到栈顶
- pop() 弹出栈顶元素
- peek() 返回栈顶元素
- is_empty() 判断栈是否为空
- size() 返回栈的元素个数
"""
Stack() 创建一个新的空栈
push(item) 添加一个新的元素item到栈顶
pop() 弹出栈顶元素
peek() 返回栈顶元素
is_empty() 判断栈是否为空
size() 返回栈的元素个数
"""
class Stack(object):
def __init__(self):
self.items=[]
def is_empty(self):
return self.items==[]
#入栈
def push(self,item):
self.items.append(item)
#弹出栈顶
def pop(self):
if self.is_empty():
raise IndexError
self.items.pop()
#返回栈顶元素
def peek(self):
return self.items[self.size()-1]
#获取栈长度
def size(self):
return len(self.items)
if __name__=='__main__':
stack=Stack()
for i in range(0,10):
stack.push(i)
print(stack.size())
print(stack.is_empty())
print(stack.peek())
stack.pop()
print(stack.peek())
队列
特点:插入和删除在不同的端进行。队列的基本操作是Enqueue(入队),在表的末端(rear)插入一个元素,还有出列(Dequeue),删除表开头的元素。
先进先出.
"""
Queue() 创建一个新的空栈
enqueue(item) 添加一个新的元素item到队列底部
delqueue() 弹出队首元素
is_empty() 判断队列是否为空
size() 返回队列的元素个数
"""
class Queue(object):
def __init__(self):
self.queues=[]
def is_empty(self):
return self.queues==[]
def enqueue(self,queue):
self.queues.append(queue)
def delqueue(self):
if self.is_empty():
raise IndexError
val=self.queues[0]
self.queues.remove(val)
return val
def size(self):
return len(self.queues)
if __name__=='__main__':
queue=Queue()
print(queue.is_empty())
for i in range(10):
queue.enqueue(i)
print(queue.size())
print(queue.delqueue())
print(queue.delqueue())
树
(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
- 每个节点有零个或多个子节点;
- 没有父节点的节点称为根节点;
- 每一个非根节点有且只有一个父节点;
- 除了根节点外,每个子节点可以分为多个不相交的子树;
树的术语
- 节点的度:一个节点含有的子树的个数称为该节点的度;
- 树的度:一棵树中,最大的节点的度称为树的度;
- 叶节点或终端节点:度为零的节点;
- 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
- 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
- 兄弟节点:具有相同父节点的节点互称为兄弟节点;
- 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
- 树的高度或深度:树中节点的最大层次;
- 堂兄弟节点:父节点在同一层的节点互为堂兄弟;
- 节点的祖先:从根到该节点所经分支上的所有节点;
- 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
- 森林:由m(m>=0)棵互不相交的树的集合称为森林;
树的种类
- 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
- 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
- 二叉树:每个节点最多含有两个子树的树称为二叉树;
- 完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树x
- 满二叉树:所有分支节点的度都是2
- 平衡二叉树(AVL树):当且仅当任何节点的两棵子树的高度差不大于1的二叉树;
- 排序二叉树(二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
- 霍夫曼树(用于信息编码):带权路径最短的二叉树称为哈夫曼树或最优二叉树;
- B树:一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多余两个子树。
树的存储与表示
顺序存储:将数据结构存储在固定的数组中,然在遍历速度上有一定的优势,但因所占空间比较大,是非主流二叉树。二叉树通常以链式存储。
常见的一些树的应用场景
- xml,html等,那么编写这些东西的解析器的时候,不可避免用到树
- 路由协议就是使用了树的算法
- mysql数据库索引
- 文件系统的目录结构
- 所以很多经典的AI算法其实都是树搜索,此外机器学习中的decision tree也是树结构
#定义树的节点
class Node(object):
def __init__(self,item):
self.elem=item
self.lchild=None
self.rchild=None
#定义树
class Tree():
def __init__(self):
self.root=None
#添加树
def add(self,item):
node=Node(item)
if self.root==None:
#如果根节点为空
self.root=node
else:
queue=[]
queue.append(self.root)
while queue:
cur_node=queue.pop(0)
#取出列表第一个元素额
if cur_node.lchild is None:
cur_node.lchild=node
return
else:
#如果当前节点的左子树不为空将其添加至列表中
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild =node
return
else:
queue.append(cur_node.rchild)
#广度遍历非递归
def breadth_travel(self):
if self.root==None:
return
queue=[]
queue.append(self.root)
while queue:
node=queue.pop(0)
print(node.elem,end=' ')
if node.lchild!=None:
queue.append(node.lchild)
if node.rchild!=None:
queue.append(node.rchild)
print('')
def breadth_travel_two(self):
if self.root==None:
return
queue=[]
queue.append(self.root)
while queue:
length=len(queue)
for i in range(length):
node=queue.pop(0)
print(node.elem,end=' ')
if node.lchild != None:
queue.append(node.lchild)
if node.rchild != None:
queue.append(node.rchild)
print('')
#深度遍历 非递归 前序遍历 根 左 右
def deep_travel_qianxu(self):
if self.root==None:
return
queue=[]
queue.append(self.root)
while queue:
cur=queue.pop()
print(cur.elem,end=' ')
#前序遍历 根 左 右
#先放入右节点再放入作节点
if cur.rchild is not None:
queue.append(cur.rchild)
if cur.lchild is not None:
queue.append(cur.lchild)
print('')
#左根右
"""
1. 使用一个栈保存结点(列表实现);
2. 如果结点存在,入栈,然后将当前指针指向左子树,直到为空;
3. 当前结点不存在,则出栈栈顶元素,并把当前指针指向栈顶元素的右子树;
4. 栈不为空,循环2、3。
"""
def deep_travel_zhongxu(self):
if not self.root:
return
stack = []
cur=self.root
while cur or stack:
#将当前节点的左节点都入栈
while cur:
stack.append(cur)
cur = cur.lchild
# 获取当前最左节点
if stack:
a = stack.pop()
cur = a.rchild
print(a.elem,end=' ')
print('')
#左 右 根
def deep_travel_houxu(self):
cur=self.root
stack = [cur]
stack2 = []
while len(stack) > 0:
cur = stack.pop()
stack2.append(cur)
if cur.lchild:
stack.append(cur.lchild)
if cur.rchild:
stack.append(cur.rchild)
while len(stack2) > 0:
node = stack2.pop()
print(node.elem,end=' ')
print('')
#深度遍历递归
def preorder(self, node):
# 先序遍历 根 左 右
if node == None:
return
print(node.elem, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
def inorder(self, node):
# 中序遍历 左 根 右
if node == None:
return
self.inorder(node.lchild)
print(node.elem, end=" ")
self.inorder(node.rchild)
def proorder(self, node):
# 后序遍历 左 右 根
if node == None:
return
self.inorder(node.lchild)
self.inorder(node.rchild)
print(node.elem, end=" ")
if __name__=='__main__':
tree=Tree()
for i in range(7):
tree.add(i)
tree.breadth_travel_two()
print("*"*20)
tree.deep_travel_qianxu()
print("*" * 20)
tree.deep_travel_zhongxu()
print("*"*20)
tree.deep_travel_houxu()
277

被折叠的 条评论
为什么被折叠?



