欢迎来到数据结构学习专栏~实践和项目:解决实际问题时,选择合适的数据结构和算法
- ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒
- ✨博客主页:IT·陈寒的博客
- 该系列文章专栏:数据结构学习
- 其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习
- 文章作者技术和水平有限,如果文中出现错误,希望大家能指正
- 欢迎大家关注! ❤️
在计算机科学中,数据结构和算法是两个非常重要的概念。数据结构是用来存储和组织数据的方式,而算法则是解决特定问题的步骤和操作。在实际应用中,选择合适的数据结构和算法对于提高程序的效率和解决实际问题的能力至关重要。
在计算机科学中,数据结构和算法是两个非常重要的概念。数据结构是用来存储和组织数据的方式,而算法则是解决特定问题的步骤和操作。在实际应用中,选择合适的数据结构和算法对于提高程序的效率和解决实际问题的能力至关重要。
数据结构的选择取决于具体的问题和场景。以下是一些常见的情况和对应的数据结构:
数组是一种线性数据结构,它存储连续的元素,并可以通过索引直接访问。由于数组在内存中是连续存储的,因此访问数组元素的速度非常快。当需要快速访问元素时,数组是一种非常合适的数据结构。
下面是一个使用数组的示例代码片段:
# 创建一个包含10个整数的数组
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 访问数组中的元素
print(arr[0]) # 输出:1
print(arr[5]) # 输出:6
链表是一种非连续的数据结构,它由一系列节点组成,每个节点包含一个指向下一个节点的指针。链表适用于需要动态分配内存的情况,因为可以在运行时动态地添加或删除节点。
下面是一个使用链表的示例代码片段:
public class Node {
int value;
Node next;
public Node(int value) {
this.value = value;
this.next = null;
}
}
public class LinkedList {
private Node head;
public void add(int value) {
Node newNode = new Node(value);
if (head == null) {
head = newNode;
} else {
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = newNode;
}
}
public void remove(int value) {
if (head == null) {
return;
}
if (head.value == value) {
head = head.next;
return;
}
Node current = head;
while (current.next != null && current.next.value != value) {
current = current.next;
}
if (current.next != null) {
current.next = current.next.next;
}
}
}
栈是一种后入先出(FILO)的数据结构。它遵循“先进后出”(LIFO)的原则,即最后一个插入的元素是第一个被删除的元素。栈适用于需要先入后出(FILO)的数据处理。例如,后入先出的队列就可以用栈来实现。
下面是一个使用栈的示例代码片段:
stack = []
stack.append(1) # 插入元素1
stack.append(2) # 插入元素2
print(stack.pop()) # 删除并返回元素2,输出:2
print(stack.pop()) # 删除并返回元素1,输出:1
队列是一种先入先出(FIFO)的数据结构。它遵循“先进先出”(FIFO)的原则,即第一个插入的元素是第一个被删除的元素。队列适用于需要先入先出(FIFO)的数据处理。例如,操作系统的任务调度就可以用队列来实现。
下面是一个使用队列的示例代码片段:
queue = []
queue.append(1) # 插入元素1
queue.append(2) # 插入元素2
print(queue.pop(0)) # 删除并返回元素1,输出:1
print(queue.pop(0)) # 删除并返回元素2,输出:2
树是一种层次结构,由节点和连接节点的边组成。树中的每个节点可能有多个子节点,根节点没有父节点。树适用于需要层次结构和快速查找的情况。例如,文件系统就是用树来存储文件的。
下面是一个使用树的示例代码片段:
class TreeNode:
def __init__(self, value):
self.value = value
self.children = []
self.parent = None
self.is_root = False
self.is_leaf = False
self.level = None
def add_child(self, child):
child.parent = self
child.is_root = False
child.level = self.level
if not self.children:
self.is_root = True
child.parent = self
self.children.append(child)
def get_root(node):
if node.is_root:
return node
else:
return node.parent.get_root(node)
图是一种无限制的数据结构,由节点和连接节点的边组成。图中的节点和边可以带有权重或其他属性。图适用于需要表示复杂关系的情况。例如,社交网络就可以用图来表示。
下面是一个使用图的示例代码片段:
class Graph:
def __init__(self):
self.nodes = set()
self.edges = {}
def add_node(self, node):
self.nodes.add(node)
self.edges[node] = []
def add_edge(self, from_node, to_node, weight=1):
if from_node not in self.nodes or to_node not in self.nodes:
raise ValueError("Both nodes need to be in graph")
self.edges[from_node].append((to_node, weight))
self.edges[to_node].append((from_node, weight))
哈希表是一种数据结构,它使用哈希函数将键映射到桶中,并在每个桶中存储相应的值。哈希表适用于需要快速查找键值对应关系的情况。例如,字典查找就可以用哈希表来实现。
下面是一个使用哈希表的示例代码片段:
class HashTable:
def __init__(self):
self.table = {}
def put(self, key, value):
hash_key = hash(key) % len(self.table)
bucket = self.table[hash_key]
for i, kv in enumerate(bucket):
if kv[0] == key:
bucket[i] = ((key, value))
return True
return False
算法的选择同样取决于具体的问题和场景。以下是一些常见的情况和对应的算法:
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
def linear_search(arr, x):
for i in range(len(arr)):
if arr[i] == x:
return i
return -1
def binary_search(arr, low, high, x):
if high >= low:
mid = (high + low) // 2
if arr[mid] == x:
return mid
elif arr[mid] > x:
return binary_search(arr, low, mid - 1, x)
else:
return binary_search(arr, mid + 1, high, x)
else:
return -1
这里以Dijkstra的最短路径算法为例:Dijkstra算法是一个用于解决给定节点到图中所有其他节点的最短路径问题的算法。它假设所有的边权重都是正数。
def dijkstra(graph, start_vertex):
D = {v:float('infinity') for v in graph}
D[start_vertex] = 0
queue = [(0, start_vertex)]
while queue:
current_distance, current_vertex = min(queue, key=lambda x:x[0])
queue.remove((current_distance, current_vertex))
if current_distance > D[current_vertex]:
continue
for neighbor, weight in graph[current_vertex].items():
old_distance = D[neighbor]
new_distance = current_distance + weight
if new_distance < oldDistance:
D[neighbor] = newDistance
queue.append((newDistance, neighbor))
return D #returns dictionary of shortest distances from start node to every other node in the graph.
def knapsack(weights, values, W):
n = len(weights)
dp = [[0 for _ in range(W+1)] for _ in range(n+1)]
for i in range(1, n+1):
for w in range(1, W+1):
if weights[i-1] <= w:
dp[i][w] = max(dp[i-1][w], dp[i-1][w-weights[i-1]] + values[i-1])
else:
dp[i][w] = dp[i-1][w]
return dp[n][W]
这里以归并排序为例:归并排序是一种分治算法,它将一个数组分成两个子数组,然后对子数组进行递归排序,最后将两个已排序的子数组合并成一个已排序的数组。
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
class HuffmanNode:
def __init__(self, freq, char=None):
self.freq = freq
self.char = char
self.left = None
self.right = None
self.huff = None
def __cmp__(self, other):
if(other == None):
return -1
if(self.freq == other.freq):
return 0
elif(self.freq > other.freq):
return 1
else:
return -1
def build_heap(arr):
n = len(arr)
for i in range(n//2 - 1, -1, -1):
heapify(arr, n, i)
def heapify(arr, n, i):
smallest = i
left = 2*i + 1
right = 2*i + 2
if left < n and arr[smallest].freq > arr[left].freq:
smallest = left
if right < n and arr[smallest].freq < arr[right].freq:
smallest = right
if smallest != i:
arr[i], arr[smallest] = arr[smallest], arr[i] # swap
heapify(arr, n, smallest) # call heapify for the smallest element at root.
def huffman_encode(arr):
arr_min = None # to store the minimum frequency object
heap = [] # to store the heap minimum at the root of heap. //创建最小堆,根节点为最小值。 //将数组转化为最小堆。 build_heap(heap) for item in arr: heap.append(item) build_heap(heap) //删除重复的元素 arr_min = heap[0] //将频率最小的元素移除 heap.remove(arr_min) //添加到 huffman tree 中 if arr_min.charif arr_min.char == None:
arr_min = heap[0]
heap.remove(arr_min)
tree.add_node(arr_min)
else:
tree.add_node(arr_min)
heap.remove(arr_min)
# The function to print the binary tree.
def print_binary_tree(root):
if root is not None:
print_binary_tree(root.left)
print(root.data, end=" ")
print_binary_tree(root.right)
# The main function to find the Huffman编码 of a string.
def find_huffman_encoding(text):
# Create a frequency table for all characters in the text.
char_freq = {}
for char in text:
char_freq[char] = char_freq.get(char, 0) + 1
# Create a priority queue to store the nodes of the Huffman tree.
# The priority of a node is defined by the sum of the frequencies
# of its two children.
pq = []
for char, freq in char_freq.items():
pq.append((freq, char))
heapq.heapify(pq)
# Create an empty Huffman tree and add the nodes to it in a way
# that maintains the property that the priority of a node is
# defined by the sum of the frequencies of its two children.
while len(pq) > 1:
left = heapq.heappop(pq)
right = heapq.heappop(pq)
merge_node = HuffmanNode(left[0] + right[0], None)
merge_node.left = HuffmanNode(left[0], left[1])
merge_node.right = HuffmanNode(right[0], right[1])
heapq.heappush(pq, merge_node)
# The last element in the priority queue is the root of the Huffman tree.
root = pq[-1]
# Now, we can build the Huffman encoding by traversing the Huffman tree.
huff_enc = []
print_binary_tree(root)print("Huffman encoding for text: ")
huff_enc.reverse() # reverse the list because the traversal is in reverse order.
print(huff_enc)
这个Python程序通过创建一个优先级队列(在Python中使用heapq
实现)来存储每个字符的频率,然后通过合并频率最低的两个节点来构建霍夫曼树。一旦构建了霍夫曼树,就可以使用简单的遍历来为输入字符串生成霍夫曼编码。
选择合适的数据结构和算法是解决实际问题的重要步骤。以下是一些实践和项目,可以帮助你锻炼和应用所学知识:
总之,通过参与实践和项目,你可以更深入地了解各种数据结构和算法的应用场景和优劣性,从而提高你的程序设计和问题解决能力。
结尾 ❤️ 感谢您的支持和鼓励!
您可能感兴趣的内容:
- 【Java面试技巧】Java面试八股文 - 掌握面试必备知识(目录篇)
- 【Java学习路线】2023年完整版Java学习路线图
- 【AIGC人工智能】Chat GPT是什么,初学者怎么使用Chat GPT,需要注意些什么
- 【Java实战项目】SpringBoot+SSM实战:打造高效便捷的企业级Java外卖订购系统
- 【数据结构学习】从零起步:学习数据结构的完整路径