372.Delete Node in the Middle of Singly Linked List-在O(1)时间复杂度删除链表节点(容易题)

在O(1)时间复杂度删除链表节点

  1. 题目

    给定一个单链表中的一个等待被删除的节点(非表头或表尾)。请在在O(1)时间复杂度删除该链表节点。

  2. 样例

    给定 1->2->3->4,和节点 3,删除 3 之后,链表应该变为 1->2->4。

  3. 题解

如本题样例所示,需删除节点3,则先将3的val变成后继节点4的val,再删除节点4即可。

/**
 * Definition for ListNode.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int val) {
 *         this.val = val;
 *         this.next = null;
 *     }
 * }
 */ 
public class Solution {
    /**
     * @param node: the node in the list should be deleted
     * @return: nothing
     */
    public void deleteNode(ListNode node) {
        node.val = node.next.val;
        node.next = node.next.next;
    }
}

Last Update 2016.9.13

设计Python代码验证⽤list类实现的动态数组与⽤ListNode类实现的链表的 运⾏⽤时差异。请⾄少测试以下三种操作:插⼊(包含头部插⼊、中间插⼊、尾部插⼊)、删除(包含 头部删除、中间删除、尾部删除)与随机访问。请说明在不同数据规模时各种操作的性能差异,解释如 何利⽤timeit模块测量操作性能,并观察实验结果是否与理论分析是否⼀致。以下是能符合理论时间复杂度的完整代码这个代码能否解决以上问?是否还要测量空间复杂度说明性能差异?import timeit import random import time import matplotlib.pyplot as plt import matplotlib from matplotlib import font_manager import numpy as np # 设置中文字体 - 更稳健的方法 def setup_chinese_font(): """设置中文字体支持""" try: # 方法1: 直接设置支持中文的字体 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun', 'Arial Unicode MS'] plt.rcParams['axes.unicode_minus'] = False # 测试是否成功 test_fig, test_ax = plt.subplots(figsize=(1, 1)) test_ax.text(0.5, 0.5, '测试', fontsize=12) plt.close(test_fig) print("中文字体设置成功") return True except: print("中文字体设置失败,使用英文显示") plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Arial'] return False # 在文件开头调用字体设置 chinese_supported = setup_chinese_font() class ListNode: """链表节点类""" def __init__(self, val=0, next=None): self.val = val self.next = next class LinkedList: """链表实现 - 无尾指针优化""" def __init__(self): self.head = None self.size = 0 def insert_head(self, val): """头部插入 O(1)""" new_node = ListNode(val) new_node.next = self.head self.head = new_node self.size += 1 def insert_tail(self, val): """尾部插入 O(n) - 需要遍历找到尾部""" new_node = ListNode(val) if self.head is None: self.head = new_node else: current = self.head while current.next is not None: current = current.next current.next = new_node self.size += 1 def insert_mid(self, val, index): """中间插入 O(n)""" if index <= 0: self.insert_head(val) return if index >= self.size: self.insert_tail(val) return new_node = ListNode(val) current = self.head for _ in range(index - 1): current = current.next new_node.next = current.next current.next = new_node self.size += 1 def delete_head(self): """头部删除 O(1)""" if not self.head: return None val = self.head.val self.head = self.head.next self.size -= 1 return val def delete_tail(self): """尾部删除 O(n) - 需要遍历找到尾部前一个节点""" if not self.head: return None if self.head.next is None: return self.delete_head() current = self.head while current.next.next is not None: current = current.next val = current.next.val current.next = None self.size -= 1 return val def delete_mid(self, index): """中间删除 O(n)""" if index <= 0: return self.delete_head() if index >= self.size - 1: return self.delete_tail() current = self.head for _ in range(index - 1): current = current.next val = current.next.val current.next = current.next.next self.size -= 1 return val def random_access(self, index): """随机访问 O(n)""" if index < 0 or index >= self.size: return None current = self.head for _ in range(index): current = current.next return current.val def __len__(self): return self.size class OptimizedLinkedList: """优化的链表实现 - 使用尾指针优化尾部插入""" def __init__(self): self.head = None self.tail = None self.size = 0 def insert_head(self, val): """头部插入 O(1)""" new_node = ListNode(val) new_node.next = self.head self.head = new_node if self.tail is None: self.tail = new_node self.size += 1 def insert_tail(self, val): """尾部插入 O(1) - 使用尾指针优化""" new_node = ListNode(val) if self.tail is None: self.head = self.tail = new_node else: self.tail.next = new_node self.tail = new_node self.size += 1 def insert_mid(self, val, index): """中间插入 O(n)""" if index <= 0: self.insert_head(val) return if index >= self.size: self.insert_tail(val) return new_node = ListNode(val) current = self.head for _ in range(index - 1): current = current.next new_node.next = current.next current.next = new_node self.size += 1 def delete_head(self): """头部删除 O(1)""" if not self.head: return None val = self.head.val self.head = self.head.next if self.head is None: self.tail = None self.size -= 1 return val def delete_tail(self): """尾部删除 O(n) - 即使有尾指针,单链表也无法O(1)删除尾部""" if not self.head: return None if self.head == self.tail: return self.delete_head() current = self.head while current.next != self.tail: current = current.next val = self.tail.val current.next = None self.tail = current self.size -= 1 return val def delete_mid(self, index): """中间删除 O(n)""" if index <= 0: return self.delete_head() if index >= self.size - 1: return self.delete_tail() current = self.head for _ in range(index - 1): current = current.next val = current.next.val current.next = current.next.next self.size -= 1 return val def random_access(self, index): """随机访问 O(n)""" if index < 0 or index >= self.size: return None current = self.head for _ in range(index): current = current.next return current.val def __len__(self): return self.size def create_linked_list(size): """创建普通链表测试数据""" ll = LinkedList() for i in range(size): ll.insert_tail(i) return ll def create_optimized_linked_list(size): """创建优化链表测试数据""" ll = OptimizedLinkedList() for i in range(size): ll.insert_tail(i) return ll def get_user_sizes(): """获取用户选择的数据规模""" print("\n选择测试数据规模:") print("1. 小规模测试 (100, 500, 1000)") print("2. 中规模测试 (500, 1000, 2000)") print("3. 自定义规模") choice = input("请选择 (1-3): ").strip() if choice == '1': return [100, 500, 1000, 5000, 10000] # 修改为包含10000的规模 elif choice == '2': return [500, 1000, 2000, 5000, 10000] # 修改为包含10000的规模 elif choice == '3': try: sizes_input = input("请输入数据规模 (用逗号分隔,如: 100,500,1000,5000,10000): ") sizes = [int(x.strip()) for x in sizes_input.split(',')] return [min(size, 10000) for size in sizes] # 提高最大规模限制到10000 except ValueError: print("输入格式错误,使用默认的小规模测试") return [100, 500, 1000, 5000, 10000] # 修改为包含10000的规模 else: print("无效选择,使用默认的小规模测试") return [100, 500, 1000, 5000, 10000] # 修改为包含10000的规模 def plot_performance_results(insert_results, delete_results, random_results): """绘制性能测试结果图表""" print("\n正在生成性能图表...") sizes = insert_results['sizes'] # 根据字体支持情况选择标签语言 if chinese_supported: titles = { 'main': '动态数组 vs 链表性能对比', 'insert_head': '头部插入性能\nList: O(n) vs LinkedList: O(1)', 'insert_mid': '中间插入性能\nList: O(n) vs LinkedList: O(n)', 'insert_tail': '尾部插入性能\nList: O(1) vs LinkedList: O(n)', 'delete_head': '头部删除性能\nList: O(n) vs LinkedList: O(1)', 'delete_mid': '中间删除性能\nList: O(n) vs LinkedList: O(n)', 'delete_tail': '尾部删除性能\nList: O(1) vs LinkedList: O(n)', 'random_batch': '批量随机访问 (50次)\nList: O(1) vs LinkedList: O(n)', 'random_single': '单次随机访问\nList: O(1) vs LinkedList: O(n)', 'xlabel': '数据规模', 'ylabel': '平均操作时间 ()' } else: titles = { 'main': 'Array vs LinkedList Performance Comparison', 'insert_head': 'Head Insert Performance\nList: O(n) vs LinkedList: O(1)', 'insert_mid': 'Middle Insert Performance\nList: O(n) vs LinkedList: O(n)', 'insert_tail': 'Tail Insert Performance\nList: O(1) vs LinkedList: O(n)', 'delete_head': 'Head Delete Performance\nList: O(n) vs LinkedList: O(1)', 'delete_mid': 'Middle Delete Performance\nList: O(n) vs LinkedList: O(n)', 'delete_tail': 'Tail Delete Performance\nList: O(1) vs LinkedList: O(n)', 'random_batch': 'Batch Random Access (50 times)\nList: O(1) vs LinkedList: O(n)', 'random_single': 'Single Random Access\nList: O(1) vs LinkedList: O(n)', 'xlabel': 'Data Size', 'ylabel': 'Average Operation Time (s)' } # 创建子图 - 调整布局 fig, axes = plt.subplots(2, 3, figsize=(20, 12)) if chinese_supported: fig.suptitle('动态数组 vs 链表性能对比', fontsize=16, fontweight='bold') else: fig.suptitle('Array vs LinkedList Performance Comparison', fontsize=16, fontweight='bold') # 插入操作对比 axes[0, 0].plot(sizes, insert_results['head_list'], 'o-', label='List', linewidth=2, markersize=6) axes[0, 0].plot(sizes, insert_results['head_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[0, 0].set_title(titles['insert_head'], fontsize=12) axes[0, 0].set_xlabel(titles['xlabel'], fontsize=10) axes[0, 0].set_ylabel(titles['ylabel'], fontsize=10) axes[0, 0].legend(fontsize=9) axes[0, 0].grid(True, alpha=0.3) axes[0, 1].plot(sizes, insert_results['mid_list'], 'o-', label='List', linewidth=2, markersize=6) axes[0, 1].plot(sizes, insert_results['mid_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[0, 1].set_title(titles['insert_mid'], fontsize=12) axes[0, 1].set_xlabel(titles['xlabel'], fontsize=10) axes[0, 1].set_ylabel(titles['ylabel'], fontsize=10) axes[0, 1].legend(fontsize=9) axes[0, 1].grid(True, alpha=0.3) axes[0, 2].plot(sizes, insert_results['tail_list'], 'o-', label='List', linewidth=2, markersize=6) axes[0, 2].plot(sizes, insert_results['tail_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[0, 2].set_title(titles['insert_tail'], fontsize=12) axes[0, 2].set_xlabel(titles['xlabel'], fontsize=10) axes[0, 2].set_ylabel(titles['ylabel'], fontsize=10) axes[0, 2].legend(fontsize=9) axes[0, 2].grid(True, alpha=0.3) # 删除操作对比 axes[1, 0].plot(sizes, delete_results['head_list'], 'o-', label='List', linewidth=2, markersize=6) axes[1, 0].plot(sizes, delete_results['head_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[1, 0].set_title(titles['delete_head'], fontsize=12) axes[1, 0].set_xlabel(titles['xlabel'], fontsize=10) axes[1, 0].set_ylabel(titles['ylabel'], fontsize=10) axes[1, 0].legend(fontsize=9) axes[1, 0].grid(True, alpha=0.3) axes[1, 1].plot(sizes, delete_results['mid_list'], 'o-', label='List', linewidth=2, markersize=6) axes[1, 1].plot(sizes, delete_results['mid_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[1, 1].set_title(titles['delete_mid'], fontsize=12) axes[1, 1].set_xlabel(titles['xlabel'], fontsize=10) axes[1, 1].set_ylabel(titles['ylabel'], fontsize=10) axes[1, 1].legend(fontsize=9) axes[1, 1].grid(True, alpha=0.3) axes[1, 2].plot(sizes, delete_results['tail_list'], 'o-', label='List', linewidth=2, markersize=6) axes[1, 2].plot(sizes, delete_results['tail_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[1, 2].set_title(titles['delete_tail'], fontsize=12) axes[1, 2].set_xlabel(titles['xlabel'], fontsize=10) axes[1, 2].set_ylabel(titles['ylabel'], fontsize=10) axes[1, 2].legend(fontsize=9) axes[1, 2].grid(True, alpha=0.3) plt.tight_layout() plt.show() # 随机访问性能单独绘制 fig2, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6)) if chinese_supported: fig2.suptitle('随机访问性能对比', fontsize=16, fontweight='bold') else: fig2.suptitle('Random Access Performance Comparison', fontsize=16, fontweight='bold') ax1.plot(sizes, random_results['batch_list'], 'o-', label='List', linewidth=2, markersize=6) ax1.plot(sizes, random_results['batch_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) ax1.set_title(titles['random_batch'], fontsize=12) ax1.set_xlabel(titles['xlabel'], fontsize=10) ax1.set_ylabel(titles['ylabel'], fontsize=10) ax1.legend(fontsize=9) ax1.grid(True, alpha=0.3) ax2.plot(sizes, random_results['single_list'], 'o-', label='List', linewidth=2, markersize=6) ax2.plot(sizes, random_results['single_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) ax2.set_title(titles['random_single'], fontsize=12) ax2.set_xlabel(titles['xlabel'], fontsize=10) ax2.set_ylabel(titles['ylabel'], fontsize=10) ax2.legend(fontsize=9) ax2.grid(True, alpha=0.3) plt.tight_layout() plt.show() print("性能图表生成完成!") def test_insert_operations(sizes): """使用timeit测试插入操作性能 - 修正版""" if chinese_supported: print("插入操作性能测试") print("时间复杂度说明:") print(" - 头部插入: List O(n) vs LinkedList O(1)") print(" - 中间插入: List O(n) vs LinkedList O(n)") print(" - 尾部插入: List O(1) vs LinkedList O(n)") else: print("Insert Operation Performance Test") print("Time Complexity:") print(" - Head Insert: List O(n) vs LinkedList O(1)") print(" - Middle Insert: List O(n) vs LinkedList O(n)") print(" - Tail Insert: List O(1) vs LinkedList O(n)") print("=" * 80) # 存储测试结果用于绘图 insert_results = { 'sizes': sizes, 'head_list': [], 'head_linked': [], 'mid_list': [], 'mid_linked': [], 'tail_list': [], 'tail_linked': [] } for size in sizes: if chinese_supported: print(f"\n数据规模: {size}") else: print(f"\nData Size: {size}") print("-" * 50) # 动态调整测试次数 - 对于大尺寸减少操作次数 operations = min(500, max(50, 10000 // size * 100)) if size > 1000 else min(1000, max(100, size // 10)) # 头部插入测试 list_time = min(timeit.repeat( "data.insert(0, -1)", setup=f"data = list(range({size}))", number=operations, repeat=3 )) / operations linked_time = min(timeit.repeat( "ll.insert_head(-1)", setup=f""" from __main__ import create_linked_list ll = create_linked_list({size}) """, number=operations, repeat=3 )) / operations insert_results['head_list'].append(list_time) insert_results['head_linked'].append(linked_time) if chinese_supported: print(f"头部插入 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Head Insert - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") # 中间插入测试 mid_index = max(1, size // 2) list_time = min(timeit.repeat( f"data.insert({mid_index}, -1)", setup=f"data = list(range({size}))", number=operations, repeat=3 )) / operations linked_time = min(timeit.repeat( f"ll.insert_mid(-1, {mid_index})", setup=f""" from __main__ import create_linked_list ll = create_linked_list({size}) """, number=operations, repeat=3 )) / operations insert_results['mid_list'].append(list_time) insert_results['mid_linked'].append(linked_time) if chinese_supported: print(f"中间插入 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Middle Insert - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") # 尾部插入测试 list_time = min(timeit.repeat( "data.append(-1)", setup=f"data = list(range({size}))", number=operations, repeat=3 )) / operations linked_time = min(timeit.repeat( "ll.insert_tail(-1)", setup=f""" from __main__ import create_linked_list ll = create_linked_list({size}) """, number=operations, repeat=3 )) / operations insert_results['tail_list'].append(list_time) insert_results['tail_linked'].append(linked_time) if chinese_supported: print(f"尾部插入 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Tail Insert - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") return insert_results def test_delete_operations(sizes): """删除操作测试 - 修正版:统一操作次数""" if chinese_supported: print("\n\n删除操作性能测试") print("时间复杂度说明:") print(" - 头部删除: List O(n) vs LinkedList O(1)") print(" - 中间删除: List O(n) vs LinkedList O(n)") print(" - 尾部删除: List O(1) vs LinkedList O(n)") else: print("\n\nDelete Operation Performance Test") print("Time Complexity:") print(" - Head Delete: List O(n) vs LinkedList O(1)") print(" - Middle Delete: List O(n) vs LinkedList O(n)") print(" - Tail Delete: List O(1) vs LinkedList O(n)") print("=" * 80) delete_results = { 'sizes': sizes, 'head_list': [], 'head_linked': [], 'mid_list': [], 'mid_linked': [], 'tail_list': [], 'tail_linked': [] } for size in sizes: if chinese_supported: print(f"\n数据规模: {size}") else: print(f"\nData Size: {size}") print("-" * 50) # 统一操作次数 - 根据数据规模动态调整,对于大尺寸减少操作次数 operations = min(200, max(20, 10000 // size * 50)) if size > 1000 else min(500, max(50, size // 20)) # 头部删除测试 list_head_time = min(timeit.repeat( "if data: del data[0]", setup="data = list(range(size))", globals={'size': size}, number=operations, repeat=3 )) / operations linked_head_time = min(timeit.repeat( "if ll.head: ll.delete_head()", setup=""" from __main__ import LinkedList ll = LinkedList() for i in range(size): ll.insert_tail(i) """, globals={'size': size}, number=operations, repeat=3 )) / operations delete_results['head_list'].append(list_head_time) delete_results['head_linked'].append(linked_head_time) if chinese_supported: print(f"头部删除 - List: {list_head_time:.8f}s, LinkedList: {linked_head_time:.8f}s") else: print(f"Head Delete - List: {list_head_time:.8f}s, LinkedList: {linked_head_time:.8f}s") # 中间删除测试 mid_index = size // 2 if size > 0 else 0 list_mid_time = min(timeit.repeat( f"if len(data) > {mid_index}: del data[{mid_index}]", setup="data = list(range(size))", globals={'size': size}, number=operations, repeat=3 )) / operations linked_mid_time = min(timeit.repeat( f"if ll.size > {mid_index}: ll.delete_mid({mid_index})", setup=""" from __main__ import LinkedList ll = LinkedList() for i in range(size): ll.insert_tail(i) """, globals={'size': size}, number=operations, repeat=3 )) / operations delete_results['mid_list'].append(list_mid_time) delete_results['mid_linked'].append(linked_mid_time) if chinese_supported: print(f"中间删除 - List: {list_mid_time:.8f}s, LinkedList: {linked_mid_time:.8f}s") else: print(f"Middle Delete - List: {list_mid_time:.8f}s, LinkedList: {linked_mid_time:.8f}s") # 尾部删除测试 list_tail_time = min(timeit.repeat( "if data: data.pop()", setup="data = list(range(size))", globals={'size': size}, number=operations, repeat=3 )) / operations linked_tail_time = min(timeit.repeat( "if ll.head: ll.delete_tail()", setup=""" from __main__ import LinkedList ll = LinkedList() for i in range(size): ll.insert_tail(i) """, globals={'size': size}, number=operations, repeat=3 )) / operations delete_results['tail_list'].append(list_tail_time) delete_results['tail_linked'].append(linked_tail_time) if chinese_supported: print(f"尾部删除 - List: {list_tail_time:.8f}s, LinkedList: {linked_tail_time:.8f}s") else: print(f"Tail Delete - List: {list_tail_time:.8f}s, LinkedList: {linked_tail_time:.8f}s") return delete_results def test_random_access(sizes): """随机访问性能测试 - 修正版""" if chinese_supported: print("\n\n随机访问性能测试") print("时间复杂度说明:") print(" - 随机访问: List O(1) vs LinkedList O(n)") else: print("\n\nRandom Access Performance Test") print("Time Complexity:") print(" - Random Access: List O(1) vs LinkedList O(n)") print("=" * 80) random_results = { 'sizes': sizes, 'batch_list': [], 'batch_linked': [], 'single_list': [], 'single_linked': [] } for size in sizes: if chinese_supported: print(f"\n数据规模: {size}") else: print(f"\nData Size: {size}") print("-" * 50) # 预创建测试数据 list_data = list(range(size)) linked_list = create_linked_list(size) # 生成随机索引 random_indices = [random.randint(0, size-1) for _ in range(min(50, size))] # 测试列表随机访问 list_time = min(timeit.repeat( lambda: [list_data[i] for i in random_indices], number=100, repeat=3 )) / 100 # 测试链表随机访问 linked_time = min(timeit.repeat( lambda: [linked_list.random_access(i) for i in random_indices], number=100, repeat=3 )) / 100 random_results['batch_list'].append(list_time) random_results['batch_linked'].append(linked_time) if chinese_supported: print(f"批量随机访问 {len(random_indices)} 次 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Batch Random Access {len(random_indices)} times - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") # 单次访问测试 test_index = max(0, min(size-1, size // 2)) # 列表单次访问 list_time = min(timeit.repeat( lambda: list_data[test_index], number=1000, repeat=3 )) / 1000 # 链表单次访问 linked_time = min(timeit.repeat( lambda: linked_list.random_access(test_index), number=1000, repeat=3 )) / 1000 random_results['single_list'].append(list_time) random_results['single_linked'].append(linked_time) if chinese_supported: print(f"单次访问测试 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Single Access Test - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") return random_results def main(): """主函数""" if chinese_supported: print("动态数组 vs 链表性能测试 - 时间复杂度修正版") print("注意:本测试使用普通单链表(无尾指针),链表尾部插入为O(n)") else: print("Array vs LinkedList Performance Test - Time Complexity Fixed Version") print("Note: This test uses standard singly linked list (no tail pointer), LinkedList tail insertion is O(n)") print("=" * 80) # 获取用户选择的数据规模 sizes = get_user_sizes() if chinese_supported: print(f"\n使用数据规模: {sizes}") else: print(f"\nUsing Data Sizes: {sizes}") start_time = time.time() # 运行测试并收集结果 insert_results = test_insert_operations(sizes) delete_results = test_delete_operations(sizes) random_results = test_random_access(sizes) # 绘制性能图表 plot_performance_results(insert_results, delete_results, random_results) end_time = time.time() if chinese_supported: print(f"\n所有测试完成!总耗时: {end_time - start_time:.2f} 秒") else: print(f"\nAll tests completed! Total time: {end_time - start_time:.2f} seconds") if __name__ == "__main__": main()
10-24
import timeit import random import time import matplotlib.pyplot as plt import matplotlib from matplotlib import font_manager import numpy as np # 设置中文字体 - 更稳健的方法 def setup_chinese_font(): """设置中文字体支持""" try: # 方法1: 直接设置支持中文的字体 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun', 'Arial Unicode MS'] plt.rcParams['axes.unicode_minus'] = False # 测试是否成功 test_fig, test_ax = plt.subplots(figsize=(1, 1)) test_ax.text(0.5, 0.5, '测试', fontsize=12) plt.close(test_fig) print("中文字体设置成功") return True except: print("中文字体设置失败,使用英文显示") plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Arial'] return False # 在文件开头调用字体设置 chinese_supported = setup_chinese_font() class ListNode: """链表节点类""" def __init__(self, val=0, next=None): self.val = val self.next = next class LinkedList: """链表实现 - 无尾指针优化""" def __init__(self): self.head = None self.size = 0 def insert_head(self, val): """头部插入 O(1)""" new_node = ListNode(val) new_node.next = self.head self.head = new_node self.size += 1 def insert_tail(self, val): """尾部插入 O(n) - 需要遍历找到尾部""" new_node = ListNode(val) if self.head is None: self.head = new_node else: current = self.head while current.next is not None: current = current.next current.next = new_node self.size += 1 def insert_mid(self, val, index): """中间插入 O(n)""" if index <= 0: self.insert_head(val) return if index >= self.size: self.insert_tail(val) return new_node = ListNode(val) current = self.head for _ in range(index - 1): current = current.next new_node.next = current.next current.next = new_node self.size += 1 def delete_head(self): """头部删除 O(1)""" if not self.head: return None val = self.head.val self.head = self.head.next self.size -= 1 return val def delete_tail(self): """尾部删除 O(n) - 需要遍历找到尾部前一个节点""" if not self.head: return None if self.head.next is None: return self.delete_head() current = self.head while current.next.next is not None: current = current.next val = current.next.val current.next = None self.size -= 1 return val def delete_mid(self, index): """中间删除 O(n)""" if index <= 0: return self.delete_head() if index >= self.size - 1: return self.delete_tail() current = self.head for _ in range(index - 1): current = current.next val = current.next.val current.next = current.next.next self.size -= 1 return val def random_access(self, index): """随机访问 O(n)""" if index < 0 or index >= self.size: return None current = self.head for _ in range(index): current = current.next return current.val def __len__(self): return self.size class OptimizedLinkedList: """优化的链表实现 - 使用尾指针优化尾部插入""" def __init__(self): self.head = None self.tail = None self.size = 0 def insert_head(self, val): """头部插入 O(1)""" new_node = ListNode(val) new_node.next = self.head self.head = new_node if self.tail is None: self.tail = new_node self.size += 1 def insert_tail(self, val): """尾部插入 O(1) - 使用尾指针优化""" new_node = ListNode(val) if self.tail is None: self.head = self.tail = new_node else: self.tail.next = new_node self.tail = new_node self.size += 1 def insert_mid(self, val, index): """中间插入 O(n)""" if index <= 0: self.insert_head(val) return if index >= self.size: self.insert_tail(val) return new_node = ListNode(val) current = self.head for _ in range(index - 1): current = current.next new_node.next = current.next current.next = new_node self.size += 1 def delete_head(self): """头部删除 O(1)""" if not self.head: return None val = self.head.val self.head = self.head.next if self.head is None: self.tail = None self.size -= 1 return val def delete_tail(self): """尾部删除 O(n) - 即使有尾指针,单链表也无法O(1)删除尾部""" if not self.head: return None if self.head == self.tail: return self.delete_head() current = self.head while current.next != self.tail: current = current.next val = self.tail.val current.next = None self.tail = current self.size -= 1 return val def delete_mid(self, index): """中间删除 O(n)""" if index <= 0: return self.delete_head() if index >= self.size - 1: return self.delete_tail() current = self.head for _ in range(index - 1): current = current.next val = current.next.val current.next = current.next.next self.size -= 1 return val def random_access(self, index): """随机访问 O(n)""" if index < 0 or index >= self.size: return None current = self.head for _ in range(index): current = current.next return current.val def __len__(self): return self.size def create_linked_list(size): """创建普通链表测试数据""" ll = LinkedList() for i in range(size): ll.insert_tail(i) return ll def create_optimized_linked_list(size): """创建优化链表测试数据""" ll = OptimizedLinkedList() for i in range(size): ll.insert_tail(i) return ll def get_user_sizes(): """获取用户选择的数据规模""" print("\n选择测试数据规模:") print("1. 小规模测试 (100, 500, 1000)") print("2. 中规模测试 (500, 1000, 2000)") print("3. 自定义规模") choice = input("请选择 (1-3): ").strip() if choice == '1': return [100, 500, 1000, 5000, 10000] # 修改为包含10000的规模 elif choice == '2': return [500, 1000, 2000, 5000, 10000] # 修改为包含10000的规模 elif choice == '3': try: sizes_input = input("请输入数据规模 (用逗号分隔,如: 100,500,1000,5000,10000): ") sizes = [int(x.strip()) for x in sizes_input.split(',')] return [min(size, 10000) for size in sizes] # 提高最大规模限制到10000 except ValueError: print("输入格式错误,使用默认的小规模测试") return [100, 500, 1000, 5000, 10000] # 修改为包含10000的规模 else: print("无效选择,使用默认的小规模测试") return [100, 500, 1000, 5000, 10000] # 修改为包含10000的规模 def plot_performance_results(insert_results, delete_results, random_results): """绘制性能测试结果图表""" print("\n正在生成性能图表...") sizes = insert_results['sizes'] # 根据字体支持情况选择标签语言 if chinese_supported: titles = { 'main': '动态数组 vs 链表性能对比', 'insert_head': '头部插入性能\nList: O(n) vs LinkedList: O(1)', 'insert_mid': '中间插入性能\nList: O(n) vs LinkedList: O(n)', 'insert_tail': '尾部插入性能\nList: O(1) vs LinkedList: O(n)', 'delete_head': '头部删除性能\nList: O(n) vs LinkedList: O(1)', 'delete_mid': '中间删除性能\nList: O(n) vs LinkedList: O(n)', 'delete_tail': '尾部删除性能\nList: O(1) vs LinkedList: O(n)', 'random_batch': '批量随机访问 (50次)\nList: O(1) vs LinkedList: O(n)', 'random_single': '单次随机访问\nList: O(1) vs LinkedList: O(n)', 'xlabel': '数据规模', 'ylabel': '平均操作时间 ()' } else: titles = { 'main': 'Array vs LinkedList Performance Comparison', 'insert_head': 'Head Insert Performance\nList: O(n) vs LinkedList: O(1)', 'insert_mid': 'Middle Insert Performance\nList: O(n) vs LinkedList: O(n)', 'insert_tail': 'Tail Insert Performance\nList: O(1) vs LinkedList: O(n)', 'delete_head': 'Head Delete Performance\nList: O(n) vs LinkedList: O(1)', 'delete_mid': 'Middle Delete Performance\nList: O(n) vs LinkedList: O(n)', 'delete_tail': 'Tail Delete Performance\nList: O(1) vs LinkedList: O(n)', 'random_batch': 'Batch Random Access (50 times)\nList: O(1) vs LinkedList: O(n)', 'random_single': 'Single Random Access\nList: O(1) vs LinkedList: O(n)', 'xlabel': 'Data Size', 'ylabel': 'Average Operation Time (s)' } # 创建子图 - 调整布局 fig, axes = plt.subplots(2, 3, figsize=(20, 12)) if chinese_supported: fig.suptitle('动态数组 vs 链表性能对比', fontsize=16, fontweight='bold') else: fig.suptitle('Array vs LinkedList Performance Comparison', fontsize=16, fontweight='bold') # 插入操作对比 axes[0, 0].plot(sizes, insert_results['head_list'], 'o-', label='List', linewidth=2, markersize=6) axes[0, 0].plot(sizes, insert_results['head_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[0, 0].set_title(titles['insert_head'], fontsize=12) axes[0, 0].set_xlabel(titles['xlabel'], fontsize=10) axes[0, 0].set_ylabel(titles['ylabel'], fontsize=10) axes[0, 0].legend(fontsize=9) axes[0, 0].grid(True, alpha=0.3) axes[0, 1].plot(sizes, insert_results['mid_list'], 'o-', label='List', linewidth=2, markersize=6) axes[0, 1].plot(sizes, insert_results['mid_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[0, 1].set_title(titles['insert_mid'], fontsize=12) axes[0, 1].set_xlabel(titles['xlabel'], fontsize=10) axes[0, 1].set_ylabel(titles['ylabel'], fontsize=10) axes[0, 1].legend(fontsize=9) axes[0, 1].grid(True, alpha=0.3) axes[0, 2].plot(sizes, insert_results['tail_list'], 'o-', label='List', linewidth=2, markersize=6) axes[0, 2].plot(sizes, insert_results['tail_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[0, 2].set_title(titles['insert_tail'], fontsize=12) axes[0, 2].set_xlabel(titles['xlabel'], fontsize=10) axes[0, 2].set_ylabel(titles['ylabel'], fontsize=10) axes[0, 2].legend(fontsize=9) axes[0, 2].grid(True, alpha=0.3) # 删除操作对比 axes[1, 0].plot(sizes, delete_results['head_list'], 'o-', label='List', linewidth=2, markersize=6) axes[1, 0].plot(sizes, delete_results['head_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[1, 0].set_title(titles['delete_head'], fontsize=12) axes[1, 0].set_xlabel(titles['xlabel'], fontsize=10) axes[1, 0].set_ylabel(titles['ylabel'], fontsize=10) axes[1, 0].legend(fontsize=9) axes[1, 0].grid(True, alpha=0.3) axes[1, 1].plot(sizes, delete_results['mid_list'], 'o-', label='List', linewidth=2, markersize=6) axes[1, 1].plot(sizes, delete_results['mid_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[1, 1].set_title(titles['delete_mid'], fontsize=12) axes[1, 1].set_xlabel(titles['xlabel'], fontsize=10) axes[1, 1].set_ylabel(titles['ylabel'], fontsize=10) axes[1, 1].legend(fontsize=9) axes[1, 1].grid(True, alpha=0.3) axes[1, 2].plot(sizes, delete_results['tail_list'], 'o-', label='List', linewidth=2, markersize=6) axes[1, 2].plot(sizes, delete_results['tail_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) axes[1, 2].set_title(titles['delete_tail'], fontsize=12) axes[1, 2].set_xlabel(titles['xlabel'], fontsize=10) axes[1, 2].set_ylabel(titles['ylabel'], fontsize=10) axes[1, 2].legend(fontsize=9) axes[1, 2].grid(True, alpha=0.3) plt.tight_layout() plt.show() # 随机访问性能单独绘制 fig2, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6)) if chinese_supported: fig2.suptitle('随机访问性能对比', fontsize=16, fontweight='bold') else: fig2.suptitle('Random Access Performance Comparison', fontsize=16, fontweight='bold') ax1.plot(sizes, random_results['batch_list'], 'o-', label='List', linewidth=2, markersize=6) ax1.plot(sizes, random_results['batch_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) ax1.set_title(titles['random_batch'], fontsize=12) ax1.set_xlabel(titles['xlabel'], fontsize=10) ax1.set_ylabel(titles['ylabel'], fontsize=10) ax1.legend(fontsize=9) ax1.grid(True, alpha=0.3) ax2.plot(sizes, random_results['single_list'], 'o-', label='List', linewidth=2, markersize=6) ax2.plot(sizes, random_results['single_linked'], 's-', label='LinkedList', linewidth=2, markersize=6) ax2.set_title(titles['random_single'], fontsize=12) ax2.set_xlabel(titles['xlabel'], fontsize=10) ax2.set_ylabel(titles['ylabel'], fontsize=10) ax2.legend(fontsize=9) ax2.grid(True, alpha=0.3) plt.tight_layout() plt.show() print("性能图表生成完成!") def test_insert_operations(sizes): """使用timeit测试插入操作性能 - 修正版""" if chinese_supported: print("插入操作性能测试") print("时间复杂度说明:") print(" - 头部插入: List O(n) vs LinkedList O(1)") print(" - 中间插入: List O(n) vs LinkedList O(n)") print(" - 尾部插入: List O(1) vs LinkedList O(n)") else: print("Insert Operation Performance Test") print("Time Complexity:") print(" - Head Insert: List O(n) vs LinkedList O(1)") print(" - Middle Insert: List O(n) vs LinkedList O(n)") print(" - Tail Insert: List O(1) vs LinkedList O(n)") print("=" * 80) # 存储测试结果用于绘图 insert_results = { 'sizes': sizes, 'head_list': [], 'head_linked': [], 'mid_list': [], 'mid_linked': [], 'tail_list': [], 'tail_linked': [] } for size in sizes: if chinese_supported: print(f"\n数据规模: {size}") else: print(f"\nData Size: {size}") print("-" * 50) # 动态调整测试次数 - 对于大尺寸减少操作次数 operations = min(500, max(50, 10000 // size * 100)) if size > 1000 else min(1000, max(100, size // 10)) # 头部插入测试 list_time = min(timeit.repeat( "data.insert(0, -1)", setup=f"data = list(range({size}))", number=operations, repeat=3 )) / operations linked_time = min(timeit.repeat( "ll.insert_head(-1)", setup=f""" from __main__ import create_linked_list ll = create_linked_list({size}) """, number=operations, repeat=3 )) / operations insert_results['head_list'].append(list_time) insert_results['head_linked'].append(linked_time) if chinese_supported: print(f"头部插入 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Head Insert - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") # 中间插入测试 mid_index = max(1, size // 2) list_time = min(timeit.repeat( f"data.insert({mid_index}, -1)", setup=f"data = list(range({size}))", number=operations, repeat=3 )) / operations linked_time = min(timeit.repeat( f"ll.insert_mid(-1, {mid_index})", setup=f""" from __main__ import create_linked_list ll = create_linked_list({size}) """, number=operations, repeat=3 )) / operations insert_results['mid_list'].append(list_time) insert_results['mid_linked'].append(linked_time) if chinese_supported: print(f"中间插入 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Middle Insert - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") # 尾部插入测试 list_time = min(timeit.repeat( "data.append(-1)", setup=f"data = list(range({size}))", number=operations, repeat=3 )) / operations linked_time = min(timeit.repeat( "ll.insert_tail(-1)", setup=f""" from __main__ import create_linked_list ll = create_linked_list({size}) """, number=operations, repeat=3 )) / operations insert_results['tail_list'].append(list_time) insert_results['tail_linked'].append(linked_time) if chinese_supported: print(f"尾部插入 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Tail Insert - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") return insert_results def test_delete_operations(sizes): """删除操作测试 - 修正版:统一操作次数""" if chinese_supported: print("\n\n删除操作性能测试") print("时间复杂度说明:") print(" - 头部删除: List O(n) vs LinkedList O(1)") print(" - 中间删除: List O(n) vs LinkedList O(n)") print(" - 尾部删除: List O(1) vs LinkedList O(n)") else: print("\n\nDelete Operation Performance Test") print("Time Complexity:") print(" - Head Delete: List O(n) vs LinkedList O(1)") print(" - Middle Delete: List O(n) vs LinkedList O(n)") print(" - Tail Delete: List O(1) vs LinkedList O(n)") print("=" * 80) delete_results = { 'sizes': sizes, 'head_list': [], 'head_linked': [], 'mid_list': [], 'mid_linked': [], 'tail_list': [], 'tail_linked': [] } for size in sizes: if chinese_supported: print(f"\n数据规模: {size}") else: print(f"\nData Size: {size}") print("-" * 50) # 统一操作次数 - 根据数据规模动态调整,对于大尺寸减少操作次数 operations = min(200, max(20, 10000 // size * 50)) if size > 1000 else min(500, max(50, size // 20)) # 头部删除测试 list_head_time = min(timeit.repeat( "if data: del data[0]", setup="data = list(range(size))", globals={'size': size}, number=operations, repeat=3 )) / operations linked_head_time = min(timeit.repeat( "if ll.head: ll.delete_head()", setup=""" from __main__ import LinkedList ll = LinkedList() for i in range(size): ll.insert_tail(i) """, globals={'size': size}, number=operations, repeat=3 )) / operations delete_results['head_list'].append(list_head_time) delete_results['head_linked'].append(linked_head_time) if chinese_supported: print(f"头部删除 - List: {list_head_time:.8f}s, LinkedList: {linked_head_time:.8f}s") else: print(f"Head Delete - List: {list_head_time:.8f}s, LinkedList: {linked_head_time:.8f}s") # 中间删除测试 mid_index = size // 2 if size > 0 else 0 list_mid_time = min(timeit.repeat( f"if len(data) > {mid_index}: del data[{mid_index}]", setup="data = list(range(size))", globals={'size': size}, number=operations, repeat=3 )) / operations linked_mid_time = min(timeit.repeat( f"if ll.size > {mid_index}: ll.delete_mid({mid_index})", setup=""" from __main__ import LinkedList ll = LinkedList() for i in range(size): ll.insert_tail(i) """, globals={'size': size}, number=operations, repeat=3 )) / operations delete_results['mid_list'].append(list_mid_time) delete_results['mid_linked'].append(linked_mid_time) if chinese_supported: print(f"中间删除 - List: {list_mid_time:.8f}s, LinkedList: {linked_mid_time:.8f}s") else: print(f"Middle Delete - List: {list_mid_time:.8f}s, LinkedList: {linked_mid_time:.8f}s") # 尾部删除测试 list_tail_time = min(timeit.repeat( "if data: data.pop()", setup="data = list(range(size))", globals={'size': size}, number=operations, repeat=3 )) / operations linked_tail_time = min(timeit.repeat( "if ll.head: ll.delete_tail()", setup=""" from __main__ import LinkedList ll = LinkedList() for i in range(size): ll.insert_tail(i) """, globals={'size': size}, number=operations, repeat=3 )) / operations delete_results['tail_list'].append(list_tail_time) delete_results['tail_linked'].append(linked_tail_time) if chinese_supported: print(f"尾部删除 - List: {list_tail_time:.8f}s, LinkedList: {linked_tail_time:.8f}s") else: print(f"Tail Delete - List: {list_tail_time:.8f}s, LinkedList: {linked_tail_time:.8f}s") return delete_results def test_random_access(sizes): """随机访问性能测试 - 修正版""" if chinese_supported: print("\n\n随机访问性能测试") print("时间复杂度说明:") print(" - 随机访问: List O(1) vs LinkedList O(n)") else: print("\n\nRandom Access Performance Test") print("Time Complexity:") print(" - Random Access: List O(1) vs LinkedList O(n)") print("=" * 80) random_results = { 'sizes': sizes, 'batch_list': [], 'batch_linked': [], 'single_list': [], 'single_linked': [] } for size in sizes: if chinese_supported: print(f"\n数据规模: {size}") else: print(f"\nData Size: {size}") print("-" * 50) # 预创建测试数据 list_data = list(range(size)) linked_list = create_linked_list(size) # 生成随机索引 random_indices = [random.randint(0, size-1) for _ in range(min(50, size))] # 测试列表随机访问 list_time = min(timeit.repeat( lambda: [list_data[i] for i in random_indices], number=100, repeat=3 )) / 100 # 测试链表随机访问 linked_time = min(timeit.repeat( lambda: [linked_list.random_access(i) for i in random_indices], number=100, repeat=3 )) / 100 random_results['batch_list'].append(list_time) random_results['batch_linked'].append(linked_time) if chinese_supported: print(f"批量随机访问 {len(random_indices)} 次 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Batch Random Access {len(random_indices)} times - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") # 单次访问测试 test_index = max(0, min(size-1, size // 2)) # 列表单次访问 list_time = min(timeit.repeat( lambda: list_data[test_index], number=1000, repeat=3 )) / 1000 # 链表单次访问 linked_time = min(timeit.repeat( lambda: linked_list.random_access(test_index), number=1000, repeat=3 )) / 1000 random_results['single_list'].append(list_time) random_results['single_linked'].append(linked_time) if chinese_supported: print(f"单次访问测试 - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") else: print(f"Single Access Test - List: {list_time:.8f}s, LinkedList: {linked_time:.8f}s") return random_results def main(): """主函数""" if chinese_supported: print("动态数组 vs 链表性能测试 - 时间复杂度修正版") print("注意:本测试使用普通单链表(无尾指针),链表尾部插入为O(n)") else: print("Array vs LinkedList Performance Test - Time Complexity Fixed Version") print("Note: This test uses standard singly linked list (no tail pointer), LinkedList tail insertion is O(n)") print("=" * 80) # 获取用户选择的数据规模 sizes = get_user_sizes() if chinese_supported: print(f"\n使用数据规模: {sizes}") else: print(f"\nUsing Data Sizes: {sizes}") start_time = time.time() # 运行测试并收集结果 insert_results = test_insert_operations(sizes) delete_results = test_delete_operations(sizes) random_results = test_random_access(sizes) # 绘制性能图表 plot_performance_results(insert_results, delete_results, random_results) end_time = time.time() if chinese_supported: print(f"\n所有测试完成!总耗时: {end_time - start_time:.2f} 秒") else: print(f"\nAll tests completed! Total time: {end_time - start_time:.2f} seconds") if __name__ == "__main__": main()分析上述代码中timeit模块的使用并举出使用相关的代码片段
10-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值