小杰数据结构(three day)——静以修身,俭以养德。
1.单向链表
5.查找
思路:
position = 0
遍历
如果相等
return position
不等
position + = 1
遍历结束没找到
return -1
6.删除
移动伪头引用,使其指向删除位置的前一个结点
指定位置删除
指定数据删除
与删除指定位置思想一致。一定要让伪头引用在删除结点前。
7.修改
修改指定位置数据
class Node:"""创建单链表节点"""def __init__(self, data=None, next_node=None):self.data = dataself.next = next_nodeclass LinkedList:def __init__(self):# 初始化一个头节点,它不包含实际数据,仅作为链表的起始标志self.head = Node()# 2.向单向链表的指定位置插入数据# post 插入的位置 data插入的数据def insert(self, position, data):# 容错判断if position < 0 or position > self.length():print("insert error")return# node新节点new_node = Node(data)# 移动伪指针到插入位置的前一个位置current = self.headfor _ in range(position):current = current.next# 插入动作(先连后面,再连前面)new_node.next = current.nextcurrent.next = new_node# 3.遍历单向链表def show(self):current = self.headwhile current.next:current = current.nextprint(current.data, end=' ')print()# 4.求单向链表长度的函数def length(self):current = self.headlength = 0while current.next:current = current.nextlength += 1return length# 5.删除单向链表中指定位置的数据 post 代表的是删除的位置def delete_position(self, position):# 容错判断if self.is_empty() or position < 0 or position >= self.length():print("delete_position error")returncurrent = self.head# current走到删除位置的前一个位置for _ in range(position):current = current.next# 删除动作current.next = current.next.next# 6.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除def delete_data(self, data):if self.is_empty():print("delete_data error")returncurrent = self.headwhile current.next:if current.next.data == data:current.next = current.next.nextelse:current = current.next# 7.判断单向链表是否为空 1代表空 0代表非空def is_empty(self):return self.head.next is None# 8.修改指定位置的数据 post 被修改的位置 data修改成的数据def change_data(self, position, data):# 容错判断if self.is_empty() or position < 0 or position >= self.length():print("change_data error")returncurrent = self.headfor _ in range(position + 1):current = current.nextcurrent.data = data# 9.查找指定数据出现的位置 data被查找的数据 //search 查找def search_data(self, data):if self.is_empty():print("search_data error")returncurrent = self.headposition = 0while current.next:current = current.nextif current.data == data:return positionposition += 1return -1# 10.转置链表def reverse(self):# 断开前,保存头节点的下一个节点的地址current = self.head.next# 断开链表self.head.next = None# 遍历无头单向链表,把无头单向链表的节点头插到有头空链表中while current:# 提前将current的下一个节点保存起来next_node = current.next# 先连后面,再连前面, 将无头表的节点插入头结点的下一个位置current.next = self.head.nextself.head.next = current# 将current移动,指向下一个节点current = next_node# 11.清空单向链表def clear(self):pass# endifif __name__ == '__main__':link_list = LinkedList()link_list.insert(0, 999)link_list.insert(1, 888)link_list.insert(2, 888)link_list.show()link_list.insert(0, 666)link_list.show()link_list.insert(1, 777)link_list.show()link_list.reverse()link_list.show()link_list.delete_position(0)link_list.show()link_list.insert(0, 666)link_list.show()link_list.delete_data(666)link_list.show()link_list.change_data(1,666)link_list.show()print(link_list.search_data(777))
输出
999 888 888
666 999 888 888
666 777 999 888 888
888 888 999 777 666
888 999 777 666
666 888 999 777 666
888 999 777
888 666 777
2Process finished with exit code 0
2.单向循环链表
约瑟夫问题:
设编号为1
,2
,……n
的n
个人围坐一圈,约定编号为k (1≤k≤n)
的人从1
开始报数,数到m
的那个人出列。它的下一位继续从1
开始报数,数到m
的人出列,依次类推,最后剩下一个为猴王。
假设n=6
总共6人,k=1
从第一个人开始,m=5
,每次从1
数到5
。
class Node:"""创建单链表节点"""def __init__(self, data=None):self.data = dataself.next = Nonedef Josepy(self):all_num = 6 # 猴子总数start_num = 1 # 从几号猴子开始数kill_num = 5 # 数到几杀死猴head = Node(1)p_tail = head # 尾指针指向当前的第一个结点for i in range(2, all_num + 1):new_node = Node(i) # 实例化新结点且装上数据p_tail.next = new_node # 链接到链表的尾p_tail = new_node # 尾指针继续指向当前链表的尾p_tail.next = head # 形成单向循环链表# 开始杀猴子# 将头指针移动到开始猴子的号码处for i in range(0, start_num - 1):head = head.next# 循环进行杀猴子while head != head.next:for i in range(0, kill_num - 2):head = head.nextp_del = head.next# 跨过要删除的节点head.next = p_del.nextprint("kill is -------------=", p_del.data)# 杀死猴子后,从下一个节点开始继续开始数, 将头指针移动到开始数的地方head = head.nextprint("king is=================== ", head.data)if __name__ == '__main__':linklist = Node()linklist.Josepy()
3.栈
(1)顺序栈
杯子逻辑:
只能在一端进行插入和删除操作的线性表(又称为堆栈),进行插入和删除操作的一端称为栈顶(杯子顶部),另一端称为栈底(杯子底部)
特点:
先进后出FILO first in last out top始终标记栈顶,表示栈顶最后一个元素
逻辑结构:线性结构
物理结构:顺序存储
整体代码操作
class Stack:max_len = 32 # 保存栈的最大长度# 始终代表当前栈内最后一个有效元素的下标,称为栈顶指针top = -1data = [0] * max_len # 顺序栈的存储空间# 1、判断是否为满, 满返回True,未满返回Falsedef is_full(self):return self.top + 1 == self.max_len# 2. 入栈def push(self, data: int): # data代表入栈的数据if self.is_full():print("push error")returnself.top += 1self.data[self.top] = data# 3.判断栈是否为空def is_empty(self):return self.top == -1# 4.出栈def pop(self):if self.is_empty():print("pop error")returnself.top -= 1return self.data[self.top + 1]# 5. 清空栈def clear(self):self.top = -1# 6.获取栈顶数据(注意不是出栈操作,如果出栈,相当于删除了栈顶数据,只是将栈顶的数据获取到,不需要移动栈针)def get_top(self):if self.is_empty():print("get_top error")returnreturn self.data[self.top]# 7. 求栈的有限长度def get_length(self):return self.top + 1if __name__ == '__main__':seq_stack = Stack()for i in range(6):seq_stack.push(i)print("top_data",seq_stack.get_top())print("stack_len",seq_stack.get_length())for _ in range(6):print(seq_stack.pop())
输出:
top_data 5
stack_len 6
5
4
3
2
1
0Process finished with exit code 0
(2)链式栈
链式栈Link
Stack
- 逻辑结构:线性结构
- 物理结构:链式存储
- 栈的特点:后进先出
栈具有后进先出的特点,我们使用链表来实现栈,即链式栈。那么栈顶是入栈和出栈的地方,单向链表有头有尾,在头部即起始结点进行插入或删除时,仅需头引用找到链表的起始结点,而无需遍历整个链表。
链式栈的入栈、出栈都是通过对链表进行头插、头删来实现。
无头单向链表的头就是栈顶,故栈针是指向无头单向链表的起始结点的,所以我们在链式栈中将头引用H称做栈针top。top栈针永远指向无头单向链表的第一个节点,栈空的时候除外。
对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间。
对于空栈来说,链表即H == None,链式栈即top == None
顺序栈需要判满,但链式栈无需判满
整体代码操作
class Node:"""链式栈节点类"""def __init__(self, data):self.data = dataself.next = Noneclass LinkStack:def __init__(self):self.top = None# 2.入栈,data是入栈的数据def push(self, data):new_node = Node(data)new_node.next = self.topself.top = new_node# 3.判断栈是否为空def is_empty(self):return self.top is None# 4.出栈def pop(self):if self.is_empty():print("pop error")returndata = self.top.dataself.top = self.top.nextreturn data# 5.清空栈def clear(self):self.top = None# 6.求栈的长度def length(self):current = self.toplength = 0while current:length += 1current = current.nextreturn length# 7.获取栈顶数据,不是出栈,不需要移动topdef get_top(self):if self.is_empty():print("get_top error")returnreturn self.top.dataif __name__ == '__main__':link_stack = LinkStack()for i in range(6):link_stack.push(i)print("top_data",link_stack.get_top())print("stack_length",link_stack.length())for _ in range(6):print("data", link_stack.pop())
输出:
top_data 5
stack_length 6
data 5
data 4
data 3
data 2
data 1
data 0Process finished with exit code 0
(3)笔试题(核心)
1.若进栈顺序为1 2 3 4
以下四种情况不可能出现的出栈序列是 ( )
A. 1 4 3 2
先1,再1出;再2、3、4,出4、3、2
B. 2 3 4 1
C. 3 1 4 2
D. 3 4 2 1
2.下列叙述正确的是 ( )
A. 线性表是线性结构
B. 栈与队列是非线性结构
C. 线性链表是非线性结构
D. 二叉树是线性结构
3.下列关于栈叙述正确的是( )
A. 在栈中只能插入数据
B. 在栈中只能删除数据
C. 栈是先进先出的线性表
D. 栈是先进后出的线性表