算法思想之排序问题

简介: 算法思想之排序问题

算法知识点

分治法求解排序问题思想:按某种方式将序列分成两个或多个子序列,分别进行排序,再将已排序的子序列合并成一个有序序列。合并排序和快速排序是两种典型的符合分治策略的排序算法。

合并排序:把两个或多个有序序列合并成一个有序序列。最基本的合并排序算法——两路合并排序。两路合并排序:把两个有序序列合并成一个有序序列。

算法题目来源

排序问题

算法题目描述

各种排序

做题思路

提示:两路合并排序。使用分治法的两路合并排序算法:

将待排序的元素序列一分为二,得到长度基本相等的两个子序列,分别排序。如果子序列较长,还可继续细分,直到子序列的长度不超过1为止。当分解所得的子序列已排列有序时,将两个有序子序列合并成一个有序子序列,得到原问题的解。

合并方法:

比较两序列中的最小值,输出其中较小者,然后重复此过程,直到其中一个队列为空时,如果另一个队列还有元素没有输出,则将剩余元素依次输出。

模板代码

两路合并排序算法

void MergeSort(int left,int right)

{

if (left<right) {//序列长度大于1时,进一步划分

int mid=(left+right)/2;//一分为二

MergeSort(left,mid);//对左子序列元素排序

MergeSort(mid+1,right);//对右子序列元素排序

Merge(left,mid,right);

//将已排好序的左、右子序列合并成一个有序序列

}

做题过程中遇到的bug及解决方案

void Merge (int left,int mid,int right)

{ T* temp=new T[right-left+1];

int k=0; //k为数组temp中当前位置

int i=left,j=mid+1;//i为左子序列当前位置;j为右子序列当前位置

while ((i<=mid) && (j<=right))

if (l[i]<=l[j])temp[k++]=l[i++];

else temp[k++]=l[j++];

while (i<=mid) temp[k++]=l[i++];

while (j<=right) temp[k++]=l[j++];

for (i=0,k=left;k<=right;) l[k++]=temp[i++];

//从temp中重新写回序列l中

}

相关算法题型题目总结

两路合并算法时间复杂度分析

Merge函数将长度之和为n的两个有序子序列合并成一个有序序列,执行过程中最多需进行n-1次关键字值间的比较,其时间复杂度为O(n)。

请写出合并排序递归算法MergeSort的时间复杂度递归函数?

两路合并算法时间复杂度分析

Merge函数将长度之和为n的两个有序子序列合并成一个有序序列,执行过程中最多需进行n-1次关键字值间的比较,其时间复杂度为O(n)。

由此可得到合并排序递归算法MergeSort的时间复杂度递归函数:

由定理5-1,或通过迭代计算,均可得到两路合并排序的时间复杂度为T(n)=O(nlogn)。

两路合并算法空间复杂度分析

两路合并排序一般需要一个与原序列相同长度的辅助数组temp,因此它所需的额外空间为O(n)。

两路合并排序

快速排序

快速排序(又称分划交换排序):在待排序的序列(k0,k1,…,kn-1)中选择一个元素作为分划元素,也称为主元。以主元为轴心,对原序列重新排列,分成左右两个子序列,使主元左侧子序列中所有元素都不大于主元,主元右侧子序列中所有元素都不小于主元,这样的分解过程称为一趟分划。原序列被分成三部分:主元和左、右两个子序列(Kp(0),Kp(1),…Kp(j-1))Kp(j)(Kp(j+1),Kp(j+2),Kp(n-1))

通过分划操作,原序列的排序问题被分解成了两个性质相同、相互独立的子问题,分别对两个子序列进行排序。

快速排序算法

void QuickSort(int left,int right)

{if (left<right){ //当序列长度>1时,用Partition函数分割

int j=Partition(left,right);//对序列进行分划操作

QuickSort(left,j-1);//对左子序列进行快速排序

QuickSort(j+1,right);//对右子序列进行快速排序

}

}

拓展

快速排序算法空间复杂度分析

最坏情况下,程序所需的系统栈调用深度,最大为O(n)。

如果希望减少使用的栈空间,可以每次分划后在栈中保存较大子序列的上、下界,而对较小的子序列先进行排序。这样可使所需的栈空间大小降为O(logn)。

堆排序是利用二叉树的一种排序方法。

堆(Heap)也译为堆或堆垒,是与二叉排序树不同的一种二叉树,它的定义为:一个完全二叉树(完全二叉树:各层都是满的,只是最下面一层从右边起连续缺几个结点),它的每个结点对应于原始数据的一个元素,且规定:如果一个结点有子结点,此结点数据必须大于或等于其子结点的数据。

由此可见,堆是完全二叉树,且规定了父结点和子结点数据之间必须满足的条件。阵排序分为建立堆阵和利用堆阵排序两大步骤。设堆阵有r个满层,元素个数n=2r-1。

最坏的情况假设每个元素都需要从原来位置“筛”到堆阵的最底层,仅原来在最底层的不必筛,这样一来最上层的一个元素要下降r-1层;第二层的两个元素要下降r-2层;……;中间第i层2(i-1)个元素要下降r-i层;……;下面倒数第二层,也即第r-1层的2(r-2)个元素下降一层。

每筛下一层要进行两次比较(先左右两子节点相比,然后此元素与其中较大者比)。


相关文章
|
5月前
|
算法 C++
【洛谷 P1223】排队接水(贪心算法+结构体排序)
该问题要求安排$n$个人的排队顺序以最小化平均等待时间。每个人接水需时$T_i$,解决方案是让接水时间短的人优先。给定$n\leq1000$和$t_i\leq10^6$,代码示例使用C++实现,通过排序使时间从小到大排列,然后计算平均等待时间。样例输入为10个人的时间数组,输出为优化后的排队顺序及平均等待时间(291.90)。
53 0
|
3月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
9天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
50 8
|
9天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
36 7
|
1月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
49 9
|
1月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
23 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
30 0
|
1月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
70 0
|
3月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
39 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
|
3月前
|
算法 搜索推荐 Java
算法实战:手写归并排序,让复杂排序变简单!
归并排序是一种基于“分治法”的经典算法,通过递归分割和合并数组,实现O(n log n)的高效排序。本文将通过Java手写代码,详细讲解归并排序的原理及实现,帮助你快速掌握这一实用算法。
41 0