Python篇——数据结构与算法(第三部分:归并排序;快速、归并、堆排序小结;深拷贝和浅拷贝区别)

news/2025/1/13 9:25:45/

 

1、归并排序——归并

  •  假设现在的列表分为两段有序,如何将其合成为一个有序列表
  • 这种操作称为一次归并

 归并过程描述:(前提是两段列表分别有序)

        两段有序列表进行对比,1和2进行对比选出最小的数,1出列,然后指针向后移,2和3在进行对比,2出列,指针向后移,指向5,以此类推......

# 归并排序
def merge(li, low, mid, high):''':param li:列表[AB]:param low:A列表的第一个位置:param mid:A列表的最后一个位置,mid+1为B列表的第一个位置:param high:B列表的最后一个位置:return:'''i = lowj = mid + 1ltmp = []  # 临时列表while i <= mid and j <= high:  # 只要左右两边都有数if li[i] < li[j]:ltmp.append(li[i])i = i + 1else:ltmp.append(li[j])j = j + 1# 第一部分跳出之后,肯定一部分没数了while i <= mid:ltmp.append(li[i])i += 1while j <= high:ltmp.append(li[j])j += 1li[low:high + 1] = ltmpli = [2, 4, 7, 8, 3, 6, 9, 10]
print(li)
merge(li, 0, 3, 7)
print(li)

2、归并排序——使用归并

  • 之前介绍的归并条件是两个列表分别有序,但是在实际中不会遇到这样的特殊情况,因此我们需要进行以下操作
  • 分解:将列表越分越小,直至分成一个元素
  • 终止条件:一个元素是有序的
  • 合并:将两个有序列表归并,列表越来越大
  • 过程如下图所示:

 

# 归并排序
def merge(li, low, mid, high):''':param li:列表[AB]:param low:A列表的第一个位置:param mid:A列表的最后一个位置,mid+1为B列表的第一个位置:param high:B列表的最后一个位置:return:'''i = lowj = mid + 1ltmp = []  # 临时列表while i <= mid and j <= high:  # 只要左右两边都有数if li[i] < li[j]:ltmp.append(li[i])i = i + 1else:ltmp.append(li[j])j = j + 1# 第一部分跳出之后,肯定一部分没数了while i <= mid:ltmp.append(li[i])i += 1while j <= high:ltmp.append(li[j])j += 1li[low:high + 1] = ltmpdef merge_sort(li, low, high):'''归并排序'''if low < high:  # 至少有两个元素# 使用递归分解mid = (low + high) // 2merge_sort(li, low, mid)merge_sort(li, mid + 1, high)# 使用merge合并merge(li, low, mid, high)# li = [2, 4, 7, 8, 3, 6, 9, 10]
# print(li)
# merge(li, 0, 3, 7)
# print(li)li = list(range(100))
import randomrandom.shuffle(li)
print(li)
merge_sort(li, 0, len(li) - 1)
print(li)

3、归并排序算法的时间复杂度和空间复杂度

  • 时间复杂度O(nlogn)
  • 空间复杂度O(n)(递归)

4、基于前两部分的三种排序算法小结

  •  三种排序算法的时间复杂度都是O(nlogn)
  • 一般情况下,就运行时间而言
    • 快速排序<归并排序<堆排序
  • 三种排序算法的缺点:
    • 快速排序:极端情况下排序效率低
    • 归并排序:需要额外的内存开销
    • 堆排序:在快的排序算法中相对较慢

 

 5、深拷贝和浅拷贝的区别

  • 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存(分支)
  • 深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象,是“值”而不是“引用”(不是分支)

http://www.ppmy.cn/news/80476.html

相关文章

《花雕学AI》34:用13种Prompt玩转AI聊天机器人—揭秘ChatGPT模型

引言&#xff1a; 聊天机器人是一种能够通过自然语言进行交流的智能系统&#xff0c;它可以模仿人类的对话方式&#xff0c;提供各种信息、服务或娱乐。随着人工智能技术的发展&#xff0c;聊天机器人的应用越来越广泛&#xff0c;从电商、教育、医疗、旅游等领域&#xff0c;到…

Mysql数据库分库分表

为什么使用分库分表&#xff1f; 传统的将数据集中存储至单一数据节点的解决方案&#xff0c;在性能、可用性和运维成本这三方面已经难于满足互联网的海量数据场景。 1&#xff09;性能 从性能方面来说&#xff0c;由于关系型数据库大多采用 B 树类型的索引&#xff0c;在数…

11 多线程

多线程 程序在快速切换(时间片)完成多线程的操作 并行:同一时间点执行多个任务,多核操作 并发:同一个时间段执行多个任务,单核快速切换 说说进程和线程的区别 一个进程可以运行多个线程,多个进程的数据很难进行共享,多个进程可以同时运行 一个线程就是进程的一个执行单元…

深入理解Java ThreadLocal及其内存泄漏防范

文章目录 一、ThreadLocal简介二、ThreadLocal的内存泄漏问题三、防止ThreadLocal导致的内存泄漏四、总结 一、ThreadLocal简介 在Java中&#xff0c;ThreadLocal是一种线程封闭的机制&#xff0c;其主要目的是为每个线程都创建一个单独的变量副本。这意味着&#xff0c;每个线…

springboot使用线程池的实际应用(一)

好的&#xff0c;这里是一个多线程应用于大量数据处理并且返回数据库的例子。 假设我们需要从数据库中查询所有用户的信息&#xff0c;然后对这些用户数据进行批量处理&#xff0c;并将结果写回数据库中。在处理大量数据时&#xff0c;单个线程可能会花费很长时间来完成任务&a…

【英语文学导读】课程论文《哈姆雷特》读后感

蓦然回首&#xff0c;尘埃落定 ——读《哈姆雷特》有感 一、戏剧故事梗概 一部作品是否伟大&#xff0c;一部分取决于作者笔下的作品本身&#xff0c;还有一个至关重要的部分便是它的受众&#xff0c;即读者的文本解读&#xff0c;想必“一千个读者心中有一千个哈姆雷特”就是…

Emacs之打开交互log(九十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

解决:在单项目组件里面引入 base.scss/ base.less 等的外部文件不成功的问题

1、问题展示&#xff1a; 其一、问题描述&#xff1a; 在单文件组件里面使用封装在 base.scss 或 base.less 里面的样式用法一直不成功&#xff1b; 其二、代码&#xff1a; // 虽然已经标明了用的是 scss 的语法&#xff0c;但是页面调用 .scss 里的 style 样式还是不成功&a…