East China University of Science and Technology
《Algorithm and Data Structures》
Experiment Repot
2022~2023 Semester 2nd
Student No.
22013724
Name
Grade
龚嘉怡
Attention:The grading level is filled in by the teacher。
2023-4-12
1
Experiment 1 Lists and Stacks
Target:
Grasp the Application of Lists,Stacks.
Contents:
3.6 The Josephus problem is the following game: N people, numbered 1 to N, are
sitting in a circle. Starting at person 1, a hot potato is passed. After M passes, the
person holding the hot potato is eliminated, the circle closes ranks, and the game
continues with the person who was sitting after the eliminated person picking up
the hot potato. The last remaining person wins. Thus, if M = 0 and N = 5, players
are eliminated in order, and player 5 wins. If M = 1 and N = 5, the order of
elimination is 2, 4, 1, 5.
a. Write a program to solve the Josephus problem for general values of M and N.
Try to make your program as efficient as possible. Make sure you dispose of
cells.
b. What is the running time of your program?
3.11 Assume that a singly linked list is implemented with a header node, but no tail
node, and that it maintains only a reference to the header node. Write a class that
includes methods to
a. return the size of the linked list
b. print the linked list
c. test if a value x is contained in the linked list
d. add a value x if it is not already contained in the linked list
e. remove a value x if it is contained in the linked list
3.12 Repeat Exercise 3.11, maintaining the singly linked list in sorted order.
Write main function for each application, and provide testing examples for your
program.
1. Code
3.6
def josephus_problem(N, M):
# Create a list of people
people = list(range(1, N + 1))
# Start with the first person
2
current_index = 0
while len(people) > 1:
# Find the next person to eliminate
current_index = (current_index + M) % len(people)
# Remove the person
eliminated = people.pop(current_index)
# Print the eliminated person (for debugging or understanding the
sequence)
# print(f"Eliminated: {eliminated}")
# The last remaining person
return people[0]
# Example usage:
N = 5
M = 1
print(f"The winner is: {josephus_problem(N, M)}")
O(N2)
3.11
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.header = Node()
# 初始化头节点(不存储实际数据)
# a. 返回链表的大小
def size(self):
current = self.header.next
count = 0
# 跳过头节点
while current:
count += 1
current = current.next
return count
# b. 打印链表
def print_list(self):
current = self.header.next
# 跳过头节点
3
elements = []
while current:
elements.append(current.data)
current = current.next
print(elements)
# c. 测试链表中是否包含值 x
def contains(self, x):
current = self.header.next
while current:
# 跳过头节点
if current.data == x:
return True
current = current.next
return False
# d. 如果链表中不包含值 x,则添加该值
def add(self, x):
if not self.contains(x):
new_node = Node(x)
new_node.next = self.header.next
self.header.next = new_node
# 将新节点插入头节点之后
# e. 如果链表中包含值 x,则移除该值
def remove(self, x):
current = self.header
while current.next:
if current.next.data == x:
current.next = current.next.next
return # 移除第一个匹配的节点
current = current.next
# 示例用法
linked_list = SinglyLinkedList()
linked_list.add(3)
linked_list.add(5)
linked_list.add(7)
print("链表大小:", linked_list.size())
linked_list.print_list()
# 链表大小: 3
# 打印: [7, 5, 3]
print("是否包含 5:", linked_list.contains(5))
linked_list.remove(5)
print("链表大小:", linked_list.size())
linked_list.print_list()
# 是否包含 5: True
# 链表大小: 2
# 打印: [7, 3]
print("是否包含 5:", linked_list.contains(5))
3.12
4
# 是否包含 5: False
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class SortedSinglyLinkedList:
def __init__(self):
self.header = Node()
# 初始化头节点(不存储实际数据)
# a. 返回链表的大小
def size(self):
current = self.header.next
count = 0
# 跳过头节点
while current:
count += 1
current = current.next
return count
# b. 打印链表
def print_list(self):
current = self.header.next
elements = []
# 跳过头节点
while current:
elements.append(current.data)
current = current.next
print(elements)
# c. 测试链表中是否包含值 x
def contains(self, x):
current = self.header.next
while current:
# 跳过头节点
if current.data == x:
return True
current = current.next
return False
# d. 如果链表中不包含值 x,则添加该值 (保持有序)
def add(self, x):
if not self.contains(x):
new_node = Node(x)
current = self.header
while current.next and current.next.data < x:
current = current.next
5
new_node.next = current.next
current.next = new_node
# e. 如果链表中包含值 x,则移除该值
def remove(self, x):
current = self.header
while current.next:
if current.next.data == x:
current.next = current.next.next
return # 移除第一个匹配的节点
current = current.next
# 主函数及测试示例
def main():
linked_list = SortedSinglyLinkedList()
linked_list.add(5)
linked_list.add(3)
linked_list.add(7)
linked_list.add(1)
print("链表大小:", linked_list.size())
linked_list.print_list()
# 链表大小: 4
# 打印: [1, 3, 5, 7]
print("是否包含 5:", linked_list.contains(5))
linked_list.remove(5)
print("链表大小:", linked_list.size())
linked_list.print_list()
# 是否包含 5: True
# 链表大小: 3
# 打印: [1, 3, 7]
print("是否包含 5:", linked_list.contains(5))
# 执行主函数
if __name__ == "__main__":
main()
2. Testing Examples and Results
6
# 是否包含 5: False
7
8
Experiment 2 Lists and Queues
Target:
Grasp the Application of Lists and Queues.
Contents:
3.32 Efficiently implement a queue class using a singly linked list, with no header
or tail nodes.
3.33 Efficiently implement a queue class using a circular array.
Write main function for each application, and provide testing examples for your
program.
1. Code
3.32
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class Queue:
def __init__(self):
self.front = None
# 队列头节点
self.rear = None
# 队列尾节点
self._size = 0
# 队列大小
# 检查队列是否为空
def is_empty(self):
return self.front is None
# 返回队列大小
def size(self):
return self._size
# 入队操作
def enqueue(self, x):
new_node = Node(x)
if self.is_empty():
9
self.front = self.rear = new_node
else:
self.rear.next = new_node
self.rear = new_node
self._size += 1
# 出队操作
def dequeue(self):
if self.is_empty():
raise IndexError("dequeue from an empty queue")
removed_data = self.front.data
self.front = self.front.next
if self.front is None:
self.rear = None
# 如果队列为空,更新尾节点
self._size -= 1
return removed_data
# 查看队列头部元素
def peek(self):
if self.is_empty():
raise IndexError("peek from an empty queue")
return self.front.data
# 测试示例
def main():
queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
print("队列大小:", queue.size())
# 输出: 队列大小: 3
print("队列头部元素:", queue.peek())
# 输出: 队列头部元素: 1
print("出队元素:", queue.dequeue())
# 输出: 出队元素: 1
print("队列大小:", queue.size())
# 输出: 队列大小: 2
print("队列头部元素:", queue.peek())
queue.enqueue(4)
print("队列大小:", queue.size())
# 输出: 队列头部元素: 2
# 输出: 队列大小: 3
print("出队元素:", queue.dequeue())
# 输出: 出队元素: 2
print("队列头部元素:", queue.peek())
# 输出: 队列头部元素: 3
# 执行主函数
if __name__ == "__main__":
main()
3.33
10
class CircularQueue:
def __init__(self, capacity):
self.capacity = capacity
self.queue = [None] * capacity
self.front = 0
self.rear = 0
self.size = 0
# 检查队列是否为空
def is_empty(self):
return self.size == 0
# 检查队列是否已满
def is_full(self):
return self.size == self.capacity
# 返回队列大小
def get_size(self):
return self.size
# 入队操作
def enqueue(self, x):
if self.is_full():
raise OverflowError("enqueue to a full queue")
self.queue[self.rear] = x
self.rear = (self.rear + 1) % self.capacity
self.size += 1
# 出队操作
def dequeue(self):
if self.is_empty():
raise IndexError("dequeue from an empty queue")
removed_data = self.queue[self.front]
self.queue[self.front] = None # 可选:清除已出队元素
self.front = (self.front + 1) % self.capacity
self.size -= 1
return removed_data
# 查看队列头部元素
def peek(self):
if self.is_empty():
raise IndexError("peek from an empty queue")
return self.queue[self.front]
11
# 打印队列
def print_queue(self):
if self.is_empty():
print("Queue is empty")
else:
index = self.front
items = []
for _ in range(self.size):
items.append(self.queue[index])
index = (index + 1) % self.capacity
print("Queue:", items)
# 测试示例
def main():
queue = CircularQueue(5)
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
queue.enqueue(4)
print("队列大小:", queue.get_size())
queue.print_queue()
# 输出: 队列大小: 4
# 输出: Queue: [1, 2, 3, 4]
print("队列头部元素:", queue.peek())
# 输出: 队列头部元素: 1
print("出队元素:", queue.dequeue())
# 输出: 出队元素: 1
print("队列大小:", queue.get_size())
# 输出: 队列大小: 3
queue.print_queue()
# 输出: Queue: [2, 3, 4]
queue.enqueue(5)
queue.enqueue(6)
print("队列大小:", queue.get_size())
queue.print_queue()
# 输出: 队列大小: 5
# 输出: Queue: [2, 3, 4, 5, 6]
# 尝试在满队列中入队,应该抛出异常
try:
queue.enqueue(7)
except OverflowError as e:
print(e)
# 输出: enqueue to a full queue
print("出队元素:", queue.dequeue())
# 输出: 出队元素: 2
print("出队元素:", queue.dequeue())
# 输出: 出队元素: 3
queue.print_queue()
# 输出: Queue: [4, 5, 6]
queue.enqueue(7)
queue.print_queue()
# 输出: Queue: [4, 5, 6, 7]
12
print("队列大小:", queue.get_size())
# 执行主函数
if __name__ == "__main__":
main()
2. Testing Examples and Results
13
# 输出: 队列大小: 4
14
Experiment 3 Trees
Target:
Grasp the Application of Trees, such as Binary Trees, Binary Search Trees,etc,.
Contents:
4.11 Write an implementation of the TreeSet class, with associated iterators using a
binary search tree. Add to each node a link to the parent node.
4.13 Write an implementation of the TreeSet class, with associated iterators, using
a binary search tree. Add to each node a link to the next smallest and next largest
node. To make your code simpler, add a header and tail node which are not part
of the binary search tree, but help make the linked list part of the code simpler.
4.31 Write efficient methods that take only a reference to the root of a binary tree,
T, and compute: a. The number of nodes in T. b. The number of leaves in T. c.
The number of full nodes in T. What is the running time of your routines?
Write main function for each application, and provide testing examples for your
program.
1. Code
4.11
class TreeNode:
def __init__(self, data, parent=None):
self.data = data
self.left = None
self.right = None
self.parent = parent
class TreeSet:
def __init__(self):
self.root = None
self.size = 0
def _insert(self, node, data):
if node is None:
return TreeNode(data)
if data < node.data:
if node.left is None:
node.left = TreeNode(data, node)
15
else:
self._insert(node.left, data)
elif data > node.data:
if node.right is None:
node.right = TreeNode(data, node)
else:
self._insert(node.right, data)
return node
def add(self, data):
if self.root is None:
self.root = TreeNode(data)
else:
self._insert(self.root, data)
self.size += 1
def _find_min(self, node):
while node.left is not None:
node = node.left
return node
def _delete_node(self, node, data):
if node is None:
return node
if data < node.data:
node.left = self._delete_node(node.left, data)
elif data > node.data:
node.right = self._delete_node(node.right, data)
else:
if node.left is None:
temp = node.right
if temp:
temp.parent = node.parent
return temp
elif node.right is None:
temp = node.left
if temp:
temp.parent = node.parent
return temp
temp = self._find_min(node.right)
node.data = temp.data
node.right = self._delete_node(node.right, temp.data)
return node
16
def remove(self, data):
if self.root:
self.root = self._delete_node(self.root, data)
self.size -= 1
def contains(self, data):
current = self.root
while current:
if data < current.data:
current = current.left
elif data > current.data:
current = current.right
else:
return True
return False
def __len__(self):
return self.size
def inorder_traversal(self):
result = []
self._inorder_helper(self.root, result)
return result
def _inorder_helper(self, node, result):
if node:
self._inorder_helper(node.left, result)
result.append(node.data)
self._inorder_helper(node.right, result)
class TreeSetIterator:
def __init__(self, root):
self.stack = []
self._push_left(root)
def _push_left(self, node):
while node:
self.stack.append(node)
node = node.left
def __iter__(self):
return self
def __next__(self):
17
if not self.stack:
raise StopIteration
node = self.stack.pop()
result = node.data
if node.right:
self._push_left(node.right)
return result
def main():
tree_set = TreeSet()
elements = [20, 9, 25, 5, 12, 11, 14]
for elem in elements:
tree_set.add(elem)
print("TreeSet contains 12:", tree_set.contains(12))
# 输出: True
print("TreeSet contains 15:", tree_set.contains(15))
# 输出: False
print("TreeSet size:", len(tree_set))
# 输出: 7
print("Inorder traversal of TreeSet:")
print(tree_set.inorder_traversal())
# 输出: [5, 9, 11, 12, 14, 20, 25]
print("Removing 12")
tree_set.remove(12)
print("TreeSet contains 12:", tree_set.contains(12))
# 输出: False
print("TreeSet size:", len(tree_set)) # 输出: 6
print("Inorder traversal of TreeSet:")
print(tree_set.inorder_traversal())
# 输出: [5, 9, 11, 14, 20, 25]
print("Iterating through TreeSet:")
iterator = TreeSetIterator(tree_set.root)
for value in iterator:
print(value, end=" ")
# 输出: 5 9 11 14 20 25
if __name__ == "__main__":
main()
4.13
class TreeNode:
def __init__(self, data, parent=None):
self.data = data
self.left = None
18
self.right = None
self.parent = parent
self.prev = None
# 指向前驱节点
self.next = None
class TreeSet:
# 指向后继节点
def __init__(self):
self.root = None
self.size = 0
self.header = TreeNode(None)
# 头节点
self.tail = TreeNode(None)
# 尾节点
self.header.next = self.tail
self.tail.prev = self.header
def _insert(self, node, data):
if node is None:
return TreeNode(data)
if data < node.data:
if node.left is None:
new_node = TreeNode(data, node)
node.left = new_node
self._insert_into_linked_list(node, new_node)
else:
self._insert(node.left, data)
elif data > node.data:
if node.right is None:
new_node = TreeNode(data, node)
node.right = new_node
self._insert_into_linked_list(node, new_node)
else:
self._insert(node.right, data)
return node
def _insert_into_linked_list(self, node, new_node):
# 插入新节点到链表
if new_node.data < node.data:
prev_node = node.prev
next_node = node
else:
prev_node = node
next_node = node.next
prev_node.next = new_node
new_node.prev = prev_node
new_node.next = next_node
19
next_node.prev = new_node
def add(self, data):
if self.root is None:
new_node = TreeNode(data)
self.root = new_node
self.header.next = new_node
new_node.prev = self.header
new_node.next = self.tail
self.tail.prev = new_node
else:
self._insert(self.root, data)
self.size += 1
def _find_min(self, node):
while node.left is not None:
node = node.left
return node
def _delete_node(self, node, data):
if node is None:
return node
if data < node.data:
node.left = self._delete_node(node.left, data)
elif data > node.data:
node.right = self._delete_node(node.right, data)
else:
if node.left is None:
temp = node.right
if temp:
temp.parent = node.parent
self._remove_from_linked_list(node)
return temp
elif node.right is None:
temp = node.left
if temp:
temp.parent = node.parent
self._remove_from_linked_list(node)
return temp
temp = self._find_min(node.right)
node.data = temp.data
node.right = self._delete_node(node.right, temp.data)
return node
20
def _remove_from_linked_list(self, node):
# 从链表中移除节点
prev_node = node.prev
next_node = node.next
prev_node.next = next_node
next_node.prev = prev_node
def remove(self, data):
if self.root:
self.root = self._delete_node(self.root, data)
self.size -= 1
def contains(self, data):
current = self.root
while current:
if data < current.data:
current = current.left
elif data > current.data:
current = current.right
else:
return True
return False
def __len__(self):
return self.size
def inorder_traversal(self):
result = []
self._inorder_helper(self.root, result)
return result
def _inorder_helper(self, node, result):
if node:
self._inorder_helper(node.left, result)
result.append(node.data)
self._inorder_helper(node.right, result)
def print_linked_list(self):
current = self.header.next
result = []
while current != self.tail:
result.append(current.data)
current = current.next
21
print(result)
class TreeSetIterator:
def __init__(self, header, tail):
self.current = header.next
self.tail = tail
def __iter__(self):
return self
def __next__(self):
if self.current == self.tail:
raise StopIteration
data = self.current.data
self.current = self.current.next
return data
def main():
tree_set = TreeSet()
elements = [20, 9, 25, 5, 12, 11, 14]
for elem in elements:
tree_set.add(elem)
print("TreeSet contains 12:", tree_set.contains(12))
# 输出: True
print("TreeSet contains 15:", tree_set.contains(15))
# 输出: False
print("TreeSet size:", len(tree_set))
# 输出: 7
print("Inorder traversal of TreeSet:")
print(tree_set.inorder_traversal())
# 输出: [5, 9, 11, 12, 14, 20, 25]
print("Linked list traversal of TreeSet:")
tree_set.print_linked_list()
# 输出: [5, 9, 11, 12, 14, 20, 25]
print("Removing 12")
tree_set.remove(12)
print("TreeSet contains 12:", tree_set.contains(12))
print("TreeSet size:", len(tree_set))
# 输出: False
# 输出: 6
print("Inorder traversal of TreeSet:")
print(tree_set.inorder_traversal())
# 输出: [5, 9, 11, 14, 20, 25]
print("Linked list traversal of TreeSet:")
tree_set.print_linked_list()
# 输出: [5, 9, 11, 14, 20, 25]
22
print("Iterating through TreeSet:")
iterator = TreeSetIterator(tree_set.header, tree_set.tail)
for value in iterator:
print(value, end=" ")
# 输出: 5 9 11 14 20 25
if __name__ == "__main__":
main()
4.31
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def count_nodes(root):
if root is None:
return 0
return 1 + count_nodes(root.left) + count_nodes(root.right)
def count_leaves(root):
if root is None:
return 0
if root.left is None and root.right is None:
return 1
return count_leaves(root.left) + count_leaves(root.right)
def count_full_nodes(root):
if root is None:
return 0
if root.left is not None and root.right is not None:
return 1 + count_full_nodes(root.left) +
count_full_nodes(root.right)
return count_full_nodes(root.left) + count_full_nodes(root.right)
# Test the methods
def main():
# Constructing a binary tree
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
23
root.left.right = TreeNode(5)
root.right.left = TreeNode(6)
root.right.right = TreeNode(7)
# a. Number of nodes in the tree
print("Number of nodes:", count_nodes(root))
# Output: 7
# b. Number of leaves in the tree
print("Number of leaves:", count_leaves(root))
# Output: 4
# c. Number of full nodes in the tree
print("Number of full nodes:", count_full_nodes(root))
if __name__ == "__main__":
main()
2. Testing Examples and Results
24
# Output: 3
25
Experiment 4
Sorting Algorithm
Target:
`Grasp the Application of sorting Algorithm.,.
Contents:
7.16 How would you implement mergesort without using recursion?
Write main function for each application, and provide testing examples for your
program.
1. Code
7.16
def merge_sort(arr):
if len(arr) <= 1:
return arr
# Initialize a variable for the subarray size
subarray_size = 1
# Iterate until the subarray size exceeds the length of the array
while subarray_size < len(arr):
# Iterate over the array in steps of double the subarray size
for start in range(0, len(arr), 2 * subarray_size):
mid = start + subarray_size - 1
end = min(start + 2 * subarray_size - 1, len(arr) - 1)
merge(arr, start, mid, end)
# Double the subarray size
subarray_size *= 2
return arr
def merge(arr, start, mid, end):
left_size = mid - start + 1
26
right_size = end - mid
left_arr = arr[start:mid + 1]
right_arr = arr[mid + 1:end + 1]
i = j = 0
k = start
while i < left_size and j < right_size:
if left_arr[i] <= right_arr[j]:
arr[k] = left_arr[i]
i += 1
else:
arr[k] = right_arr[j]
j += 1
k += 1
while i < left_size:
arr[k] = left_arr[i]
i += 1
k += 1
while j < right_size:
arr[k] = right_arr[j]
j += 1
k += 1
# Test the merge_sort function
def main():
arr = [12, 11, 13, 5, 6, 7]
print("Original array:", arr)
sorted_arr = merge_sort(arr)
print("Sorted array:", sorted_arr)
if __name__ == "__main__":
main()
27
2. Testing Examples and Results
3.
28
Experiment 5
Graph
Target:
`Grasp the Application of Algorithm of Graph, such as searching the Shortest path.
Contents:
Refer to page 372 of the book for the algorithm description of Dijkstra, and
implement the algorithm using a JAVA program
Write main function for each application, and provide testing examples for your
program.
4. Code
5. Testing Examples and Results
29
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )