1.python数据结构及算法基础学习笔记思维导图

2.程序代码演示
1.链表模型:linklist.py
1 """
2 功能: 实现单链表的构建和操作
3
4 """
5
6 # 创建节点类
7 class Node:
8 """
9 思路 : *自定义类视为节点类,类中的属性为数据内容
10 *写一个next属性,用来和下一个 节点建立关系
11 """
12 def __init__(self,val,next = None):
13 """
14 val: 有用数据
15 next: 下一个节点引用
16 """
17 self.val = val
18 self.next = next
19
20
21 # 链式线性表操作类
22 class LinkList:
23 """
24 思路 : 生成单链表,通过实例化的对象就代表一个链表
25 可以调用具体的操作方法完成各种功能
26 """
27 def __init__(self):
28 # 链表的初始化节点,没有有用数据,但是便于标记链表的开端
29 self.head = Node(None)
30
31 # 初始化链表,添加一组节点
32 def init_list(self,list_):
33 p = self.head # p 作为移动变量
34 for i in list_:
35 # 遍历到一个值就创建一个节点
36 p.next = Node(i)
37 p = p.next
38
39 # 遍历链表
40 def show(self):
41 p = self.head.next # p代表第一个有值的节点
42 while p is not None:
43 print(p.val)
44 p = p.next # p向后移动
45
46 # 判断链表为空
47 def is_empty(self):
48 if self.head.next is None:
49 return True
50 else:
51 return False
52
53 # 清空链表
54 def clear(self):
55 self.head.next = None
56
57 # 尾部插入
58 def append(self,val):
59 p = self.head
60 # p移动到最后一个节点
61 while p.next is not None:
62 p = p.next
63 p.next = Node(val) # 最后添加节点
64
65 # 头部插入
66 def head_insert(self,val):
67 node = Node(val)
68 node.next = self.head.next
69 self.head.next = node
70
71 # 指定位置插入
72 def insert(self,index,val):
73 # 设置个p 移动到待插入位置的前一个
74 p = self.head
75 for i in range(index):
76 # 如果index超出了最大范围跳出循环
77 if p.next is None:
78 break
79 p = p.next
80 # 插入节点
81 node = Node(val)
82 node.next = p.next
83 p.next = node
84
85 # 删除节点
86 def remove(self,val):
87 p = self.head
88 # p 移动,待删除节点上一个
89 while p.next is not None and p.next.val != val:
90 p = p.next
91
92 if p.next is None:
93 raise ValueError("x not in linklist")
94 else:
95 p.next = p.next.next
96
97
98 # 获取某个节点的值 (通过索引获取)
99 def search(self,index):
100 if index < 0:
101 raise IndexError("index out of range")
102
103 p = self.head.next
104 # 循环移动p
105 for i in range(index):
106 if p is None:
107 raise IndexError("index out of range")
108 p = p.next
109 return p.val
110
111
112 if __name__ == "__main__":
113 # 想有一个链表
114 link = LinkList()
115 # 初始化一组数据
116 l = [1,2,3,4]
117 link.init_list(l)
118 # link.clear()
119 print(link.search(0))
120 # 链表遍历
121 # link.show()
122 # link.insert(2,88)
123 # link.show()
124 # link.clear()
125 # print(link.is_empty())
126 # Abby = Node((1,'Abby',18,'w'))
127 # Emma = Node((2,'Emma',17,'w'))
128 # Alex = Node((3,'Alex',19,'m'))
129 # Abby.next = Emma
130 # Emma.next = Alex
2.栈的顺序存储:sstack.py
"""
栈模型的顺序存
思路 :
1. 顺序存储可以使用列表实现,但是列表功能丰富,不符合栈模型要求
2. 将列表功能封装,实现顺序栈的类,只提供栈的操作功能
功能: 出栈, 入栈,判断栈空,查看栈顶元素
"""
# 自定义异常
class StackError(Exception):
pass
# 顺序栈
class SStack:
def __init__(self):
# 空列表就是栈的存储空间
# 列表的最后一个元素作为栈顶元素
self.__elems = []
# 入栈
def push(self,val):
self.__elems.append(val)
# 判断栈空
def is_empty(self):
return self.__elems == []
# 出栈
def pop(self):
if self.is_empty():
raise StackError("pop from empty stack")
return self.__elems.pop()
# 查看栈顶
def top(self):
if self.is_empty():
raise StackError("pop from empty stack")
return self.__elems[-1]
if __name__ == '__main__':
st = SStack()
st.push(10)
st.push(20)
st.push(30)
while not st.is_empty():
print(st.pop())
st.pop()
3.栈的链式存储:lstack.py
1 """
2 栈的链式模型
3
4 思路:
5 1. 通过节点存储数据达到链式存储的目的
6 2. 封装方法,实现栈的基本操作(入栈,出栈,栈空,查看栈顶)
7 3. top为栈顶,在链表的头作为栈顶位置 (不许要遍历)
8 """
9
10 # 自定义异常
11 class StackError(Exception):
12 pass
13
14 # 节点类
15 class Node:
16 def __init__(self,val,next = None):
17 self.val = val
18 self.next = next
19
20 # 链式栈模型
21 class LStack:
22 def __init__(self):
23 # top作为栈顶的标记
24 self.__top = None
25
26 def is_empty(self):
27 return self.__top is None
28
29 # 入栈
30 def push(self,val):
31 self.__top = Node(val,self.__top)
32
33 # node = Node(val)
34 # node.next = self.__top
35 # self.__top = node
36
37 # 出栈
38 def pop(self):
39 if self.__top is None:
40 raise StackError("pop from empty stack")
41 data = self.__top.val
42 self.__top = self.__top.next
43 return data
44
45 # 查看栈顶元素
46 def top(self):
47 if self.__top is None:
48 raise StackError("pop from empty stack")
49 return self.__top.val
50
51
52 if __name__ == '__main__':
53 ls = LStack()
54 ls.push(10)
55 ls.push(20)
56 ls.push(30)
57 print(ls.pop())
58 print(ls.pop())
4.队列的顺序存储:squeue.py
1 """
2 队列的顺序存储
3
4 思路 :
5 1. 基于列表完成数据存储
6 2. 对列表功能进行封装
7 3. 列表的头部作为队头,尾部作为队尾
8 功能: 入队(enqueue),出队(dequeue),判断队列为空
9 """
10
11 # 自定义异常
12 class QueueError(Exception):
13 pass
14
15 class SQueue:
16 # 设置空列表作为队列存储空间
17 def __init__(self):
18 self.__elems = []
19
20 # 判断队列是否为空
21 def is_empty(self):
22 return self.__elems == []
23
24 # 入队
25 def enqueue(self,val):
26 self.__elems.append(val)
27
28 # 出对
29 def dequeue(self):
30 if not self.__elems:
31 raise QueueError("Queue is empty")
32 return self.__elems.pop(0)
33
34 if __name__ == '__main__':
35 sq = SQueue()
36
37 sq.enqueue(10)
38 sq.enqueue(20)
39 sq.enqueue(30)
40
41 while not sq.is_empty():
42 print(sq.dequeue())
5.队列的链式存储:lqueue.py
1 """
2 链式队列
3
4 思路:
5 1. 基于链表构建队列模型
6 2. 链表的开端作为队头, 结尾作为队尾
7 3. 对头队尾分别添加标记,避免每次插入数据都遍历链表
8 4. 队头和队尾重叠时认为队列为空
9 """
10
11 # 自定义异常
12 class QueueError(Exception):
13 pass
14
15 # 节点类
16 class Node:
17 def __init__(self,val,next = None):
18 self.val = val
19 self.next = next
20
21 # 队列操作
22 class LQueue:
23 def __init__(self):
24 # 定义队头,队尾
25 self.front = self.rear = Node(None)
26
27 def is_empty(self):
28 return self.front == self.rear
29
30 # 如队 rear动
31 def enqueue(self,val):
32 self.rear.next = Node(val)
33 self.rear = self.rear.next
34
35 # 出队 front动
36 def dequeue(self):
37 if self.front == self.rear:
38 raise QueueError("Queue is empty")
39
40 # front移动到的节点已经出队
41 self.front = self.front.next
42 return self.front.val
43
44 if __name__ == '__main__':
45 lq = LQueue()
46 lq.enqueue(10)
47 lq.enqueue(20)
48 lq.enqueue(30)
49 print(lq.dequeue())
6.递归函数:recursion.py
1 """ 2 求一个数的阶乘 n! 3 """ 4 5 def fun(n): 6 result = 1 7 for i in range(1, n + 1): 8 result *= i 9 return result 10 11 12 def recursion(n): 13 if n <= 1: 14 return 1 15 return n * recursion(n - 1) 16 17 18 print(fun(5)) 19 print(recursion(5))
7.二叉树的链式存储:btree.py
1 """
2 二叉树的遍历实践
3
4 思路分析:
5 1. 使用链式结构存储二叉树的节点数据
6 2. 节点中存储 数据, 左孩子链接,右孩子链接 三个属性
7 """
8 from squeue import *
9
10 # 二叉树节点类
11 class Node:
12 def __init__(self,val,left=None,right=None):
13 self.val = val
14 self.left = left
15 self.right = right
16
17 # 二叉树遍历方法
18 class Bitree:
19 def __init__(self,root):
20 self.root = root
21
22 # 先序遍历
23 def preOrder(self,node):
24 if node is None:
25 return
26 print(node.val)
27 self.preOrder(node.left)
28 self.preOrder(node.right)
29
30 # 中序遍历
31 def inOrder(self, node):
32 if node is None:
33 return
34 self.inOrder(node.left)
35 print(node.val)
36 self.inOrder(node.right)
37
38 # 后序遍历
39 def postOrder(self, node):
40 if node is None:
41 return
42 self.postOrder(node.left)
43 self.postOrder(node.right)
44 print(node.val)
45
46 # 层次遍历
47 def levelOrder(self,node):
48 """
49 node先入队,循环判断,队列不为空时,出队表示遍历,
50 同时让出队元素的左右孩子入队
51 """
52 sq = SQueue()
53 sq.enqueue(node)
54 while not sq.is_empty():
55 node = sq.dequeue()
56 print(node.val) # 遍历元素
57 if node.left:
58 sq.enqueue(node.left)
59 if node.right:
60 sq.enqueue(node.right)
61
62
63
64 if __name__ == '__main__':
65 b = Node('B')
66 f = Node('F')
67 g = Node('G')
68 d = Node('D',f,g)
69 h = Node('H')
70 i = Node('I')
71 e = Node('E',h,i)
72 c = Node('C',d,e)
73 a = Node('A',b,c) # 整个树根
74
75 bt = Bitree(a) # 把a作为根节点进行遍历
76
77 bt.preOrder(bt.root)
78 print("========================")
79 bt.inOrder(bt.root)
80 print("========================")
81 bt.postOrder(bt.root)
82 print("========================")
83 bt.levelOrder(bt.root)
8.排序算法选择、冒泡、插入、归并、快速排序:sort.py
1 def selection_sort(arr): 2 """ 3 1.选择排序:外层循环一次,就可排好一个数,从前往后排。 4 用选定元素与其后的所有元素进行比较,较大(小)交换 5 """ 6 for i in range(len(arr) - 1): # 需要比较n-1轮 7 for j in range(i + 1, len(arr)): # 每一轮需要比较j次 8 if arr[i] > arr[j]: # 升序排列 9 arr[i], arr[j] = arr[j], arr[i] 10 11 12 def buble_sort(arr): 13 """ 14 2.冒泡排序:外层循环一次,就可排好最后一个数,从后往前排。 15 所有相邻元素依次进行比较,较大(小)交换 16 """ 17 for i in range(len(arr) - 1): # 需要比较n-1轮 18 for j in range(len(arr) - 1 - i): # 每轮比较中,索引j的取值0到(n-1)-i 19 if arr[j] > arr[j + 1]: 20 arr[j], arr[j + 1] = arr[j + 1], arr[j] 21 22 23 def insert_sort(arr): 24 """ 25 3.插入排序:将第一个元素看做有序序列,从后向前扫描有序序列,将为排序元素依次插入对应位置 26 """ 27 for i in range(1, len(arr)): # 只需要对第二个到最后一个元素进行排序 28 preindex = i - 1 29 current = arr[i] 30 while preindex >= 0 and arr[preindex] > current: 31 arr[preindex + 1] = arr[preindex] # 将前一个元素赋值给当前元素位置上 32 preindex -= 1 33 arr[preindex + 1] = current # 将当前元素赋值给“对应”位置上 34 35 36 def merge_sort(arr): 37 """ 38 4.归并排序:递归的将arr一分为二的拆分为一个二叉树(每个叶子节点只有一个数), 39 定义空列表result=[],回归的将叶子结点合并到result中,回归到根节点 40 """ 41 if len(arr) < 2: 42 return arr # 递归结束条件:拆分后的最终列表中只有一个元素 43 middle = len(arr) // 2 44 left, right = arr[:middle], arr[middle:] 45 return merge(merge_sort(left), merge_sort(right)) 46 47 48 def merge(left, right): 49 result = [] 50 while left and right: # 回归阶段:将左右子节点合并到父节点 51 if left[0] <= right[0]: 52 result.append(left.pop(0)) 53 else: 54 result.append(right.pop(0)) 55 while left: 56 result.append(left.pop(0)) 57 while right: 58 result.append(right.pop(0)) 59 return result 60 61 62 def quick_sort(arr): 63 """ 64 5.快速排序:选定第一个元素为基准,将后面的元素“依次”与基准比较, 65 较大的放基准右边区域,较小的放基准左边区域。 66 递归的对左右区域进行分区操作,直至该区域中只有一个元素了 67 """ 68 sort(arr, 0, len(arr) - 1) 69 70 71 def sort(arr, left, right): 72 if left >= right: # 递归终止条件:被分区区域内只有1个元素了 73 return 74 pivot = partition(arr, left, right) 75 # 递归的进行分区 76 sort(arr, left, pivot - 1) 77 sort(arr, pivot + 1, right) 78 79 80 # 分区,返回基准值的索引 81 def partition(arr, left, right): 82 pivotkey = arr[left] # 选定第一个元素为基准值 83 while left < right: 84 while arr[right] >= pivotkey and right > left: 85 right -= 1 86 arr[left] = arr[right] # 小于基准值的元素放到左边区域:小的往前甩 87 while arr[left] < pivotkey and left < right: 88 left += 1 89 arr[right] = arr[left] # 大于等于基准值的元素放到右边区域:大的往后甩 90 arr[left] = pivotkey 91 return left 92 93 94 arr = [9, 8, 7, 6, 5, 4, 3, 2, 1] 95 # selection_sort(arr) 96 # buble_sort(arr) 97 # insert_sort(arr) 98 # print(merge_sort(arr)) 99 quick_sort(arr) 100 print(arr)
9.二分法查找:search.py
1 def search(l,val):
2 low,high = 0,len(l) - 1 # 查找范围的开始和结束索引位
3 # 循环查找,每次去除一半
4 while low <= high:
5 mid = (low + high) // 2 # 中间数索引
6 if l[mid] < val:
7 low = mid + 1
8 elif l[mid] > val:
9 high = mid - 1
10 else:
11 return mid
12
13
14 l = [1,2,3,4,5,6,7,8,9,10]
15 print("Key index:",search(l,666))