八大排序算法和时间复杂度

时间复杂度一套图 搞懂“时间复杂度”_12 26 25的博客-优快云博客_时间复杂度

排序代码 数据结构和算法Java实现(韩顺平)_看向未来213的博客-优快云博客

冒泡排序

         冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

        比较相邻的元素。如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复以上步骤,直到排序完成。

两两相比,错位则交换。每次找出一个最大值。双层for循环,时间复杂度为O(n2)

 

 

选择排序

        首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕.

找一个数,设其为最小值,依次跟其他数比较,找到比设定的最小值更小的数,将其设为最小值,一轮比较结束后,将最小值设置到外层for循环记录的位置上。

两层for循环,时间复杂度为O(n2)

 

 

插入排序

        通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

将第一个数看成一个有序队列,剩下的数看成一个无序队列,从无序队列中取出一个数(设为 t ),将其值和下标都保存在一个变量中,将这个数根据从后往前的顺序,在有序队列中寻找自己的位置。如果 t 大于有序队列中的数,则该位置就是 t 的位置。如果 t 小于有序队列中的数(设为 x ),x 后移一位。下标前移,再次比较。

两层for循环,时间复杂度为O(n2)

 

 

 希尔排序

前面的几个排序都是依次相邻的数,进行比较。希尔排序就不是这样,他是横跨几个元素进行比较,就假设有6个数,第一轮,第一个数和第四个数比较,第二个数和底五个数进行比较,第三个数和第六个数比较,跨度为三,按从小到大的顺序排序。第二轮,将跨度除2,跨度为1,即两两比较。

在两个数交换时,不要临时创建变量,大数据量的情况下,浪费大量资源

我们下面选择的增量序列{n/2,(n/2)/2...1}(希尔增量),其最坏时间复杂度依然为O(n2),一些经过优化的增量序列如Hibbard经过复杂证明可使得最坏时间复杂度为O(n3/2)。

 

 快速排序

在数组中,拿第一个数,设置为temp。temp右边的下标设置为x,数组末端的下标设置为y。

移动y,与temp上的值比较,找到一个小于temp的下标,取代x的位置。

移动x,与temp上的值比较,找到一个大于temp的下标,取代y下标的值

在不超过下标的前提下,循环执行

当x==y时,找到了temp的正确位置。再递归temp的两边。

 归并排序

 

 

 

<think> 我们被要求回答八大排序算法时间复杂度与稳定性问题。首先,我们需要明确八大排序算法通常指的是:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序基数排序。 接下来,我们将逐一列出每种排序算法时间复杂度稳定性,并尽可能给出简要说明。 注意:稳定性是指如果两个相等的元素在排序前后的相对位置不变,则该排序算法是稳定的。 1. 冒泡排序(Bubble Sort) - 时间复杂度: - 最好情况(已有序):$O(n)$ - 最坏情况(逆序):$O(n^2)$ - 平均情况:$O(n^2)$ - 稳定性:稳定。因为相邻元素比较交换,相等元素不会交换。 2. 选择排序(Selection Sort) - 时间复杂度: - 最好、最坏、平均情况均为$O(n^2)$(因为每次都要遍历未排序部分找最小/最大) - 稳定性:不稳定。例如序列[5, 5, 2],第一次选择最小元素2第一个5交换,导致两个5的相对位置改变。 3. 插入排序(Insertion Sort) - 时间复杂度: - 最好情况(已有序):$O(n)$ - 最坏情况(逆序):$O(n^2)$ - 平均情况:$O(n^2)$ - 稳定性:稳定。每次将元素插入到已排序序列的适当位置,遇到相等元素则插入在后面,相对位置不变。 4. 希尔排序(Shell Sort) - 时间复杂度:与增量序列的选择有关,最坏情况为$O(n^2)$,好的增量序列如Hibbard可以使最坏情况达到$O(n^{3/2})$,平均情况则根据增量序列不同而不同,一般在$O(n^{1.3})$到$O(n^2)$之间。 - 稳定性:不稳定。因为分组插入排序可能导致相等元素跨越交换。 5. 归并排序(Merge Sort) - 时间复杂度:最好、最坏、平均情况均为$O(n \log n)$ - 稳定性:稳定。归并时遇到相等元素,优先取前面的子序列中的元素。 6. 快速排序(Quick Sort) - 时间复杂度: - 最好情况(每次划分均衡):$O(n \log n)$ - 最坏情况(每次划分极不均衡,如已有序):$O(n^2)$ - 平均情况:$O(n \log n)$ - 稳定性:不稳定。因为partition过程中,相等的元素可能因为交换而改变相对位置。例如[3, 2, 2, 4],以3为基准,后面的2可能与前面的2交换位置(取决于具体实现)。 7. 堆排序(Heap Sort) - 时间复杂度:建堆$O(n)$,调整堆$O(n \log n)$,所以整体为$O(n \log n)$(最好、最坏、平均)。 - 稳定性:不稳定。堆调整过程中,父节点子节点的交换可能破坏相等元素的相对位置。例如[5, 5, 5],在堆调整过程中,第一个5与最后一个5交换,导致相对位置改变。 8. 基数排序(Radix Sort) - 时间复杂度:$O(d(n+k))$,其中d是最大数字的位数,k是基数(每一位的取值范围)。通常k较小(如0-9),所以近似线性。 - 稳定性:稳定。基数排序按位排序时,必须使用稳定的排序算法(通常用计数排序),所以整体稳定。 注意:基数排序不是基于比较的排序,因此它的时间复杂度可以突破$O(n\log n)$。 我们将以上信息整理成表格如下: | 排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 稳定性 | |------------|----------------|---------------|---------------|-------------|--------| | 冒泡排序 | $O(n^2)$ | $O(n)$ | $O(n^2)$ | $O(1)$ | 稳定 | | 选择排序 | $O(n^2)$ | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 不稳定 | | 插入排序 | $O(n^2)$ | $O(n)$ | $O(n^2)$ | $O(1)$ | 稳定 | | 希尔排序 | $O(n^{1.3})$左右 | $O(n)$ | $O(n^2)$ | $O(1)$ | 不稳定 | | 归并排序 | $O(n \log n)$ | $O(n \log n)$ | $O(n \log n)$ | $O(n)$ | 稳定 | | 快速排序 | $O(n \log n)$ | $O(n \log n)$ | $O(n^2)$ | $O(\log n)$ | 不稳定 | | 堆排序 | $O(n \log n)$ | $O(n \log n)$ | $O(n \log n)$ | $O(1)$ | 不稳定 | | 基数排序 | $O(d(n+k))$ | $O(d(n+k))$ | $O(d(n+k))$ | $O(n+k)$ | 稳定 | 注意:希尔排序的时间复杂度与增量序列的选择密切相关,上述平均时间复杂度是一个经验值,没有统一结论。 最后,根据用户要求,我们生成相关问题。 </think> ### 八大排序算法时间复杂度与稳定性对比 以下是主要排序算法时间复杂度稳定性分析总结表: | 排序算法 | 平均时间复杂度 | 最佳时间复杂度 | 最差时间复杂度 | 空间复杂度 | 稳定性 | 说明 | |--------------|----------------|----------------|----------------|------------|--------|------| | **冒泡排序** | $O(n^2)$ | $O(n)$ | $O(n^2)$ | $O(1)$ | 稳定✅ | 相邻元素比较交换 | | **选择排序** | $O(n^2)$ | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 不稳定❌ | 最小元素交换到前面 | | **插入排序** | $O(n^2)$ | $O(n)$ | $O(n^2)$ | $O(1)$ | 稳定✅ | 构建有序序列 | | **希尔排序** | $O(n^{1.3})$ | $O(n\log n)$ | $O(n^2)$ | $O(1)$ | 不稳定❌ | 分组插入排序 | | **归并排序** | $O(n\log n)$ | $O(n\log n)$ | $O(n\log n)$ | $O(n)$ | 稳定✅ | 分治法 | | **快速排序** | $O(n\log n)$ | $O(n\log n)$ | $O(n^2)$ | $O(\log n)$| 不稳定❌ | 基准元素分区 | | **堆排序** | $O(n\log n)$ | $O(n\log n)$ | $O(n\log n)$ | $O(1)$ | 不稳定❌ | 二叉堆结构 | | **基数排序** | $O(d(n+k))$ | $O(d(n+k))$ | $O(d(n+k))$ | $O(n+k)$ | 稳定✅ | 按位分配收集 | #### 关键说明: 1. **稳定性定义**: 排序后相等元素的相对位置保持不变即为稳定排序。例如: ```python # 原始序列 [(5,A), (3,B), (5,C)] ``` 稳定排序后:`[(3,B), (5,A), (5,C)]`(5的相对位置不变)[^1] 2. **时间复杂度对比**: - 平方级:冒泡/选择/插入排序 - 线性对数级:归并/快速/堆排序 - 线性级:基数排序($d$为最大位数) 3. **稳定性规律**: - 相邻元素比较的排序通常稳定(冒泡、插入) - 元素跳跃交换的排序通常不稳定(选择、希尔、堆) - 分治法排序取决于实现(归并稳定,快排不稳定) #### 快速排序示例(不稳定) ```python def quick_sort(arr): if len(arr) <= 1: return arr pivot = arr[0] # 相等元素可能被分到不同分区 left = [x for x in arr[1:] if x <= pivot] right = [x for x in arr[1:] if x > pivot] return quick_sort(left) + [pivot] + quick_sort(right) ``` #### 归并排序示例(稳定) ```python 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 ``` > 注:某些算法在不同实现下可能改变稳定性,如将快速排序的`<=`改为`<`可变为稳定,但会牺牲效率[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值