三种排序比较前言:如果内容不全,说明还没复习到,复习时会陆续更新。
堆排序,快速排序,归并排序平均复杂度都是O(nlogn)。其中归并排序时间最稳定(最好最差的时间复杂度差距不大)。快速排序平均时间最快,虽然最差情况时O(n^2),但此情况发生概率极小。堆排序主要使用优先队列,可以在线插入新数据。
堆排序补充:C++ sort(快排)链接
C++ STL优先队列 链接
建议初学者先去看这两篇文章,写的很好,保姆级别教学。此篇只是加入了些个人理解以及代码模板供自己复习使用,具体细节太多了,本人时间和水平有限,就不在此写具体实现过程了。有的地方可能说的不对,欢迎指正。
文章链接:
堆排序——深入浅出(图解)
堆排序
前置知识
1.堆:堆是一种数据结构,一种叫做完全二叉树的数据结构。
2.堆的性质:这里我们用到两种堆,其实也算是一种。
大顶堆:每个节点的值都大于或者等于它的左右子节点的值。
小顶堆:每个节点的值都小于或者等于它的左右子节点的值。
3.完全二叉树
(1)父节点编号 = (该节点编号 - 1)/2
(2)左儿子编号 = 2i+1(根编号为0的情况)
(3)右儿子编号 = 2i+2(根编号为0的情况),如果根编号为1,左二子 = 2i,右儿子 = 2i+1
(4)完全二叉树最后一个非叶子节点的编号 = n(节点个数)/2
排序过程
分为两个部分,构造初始堆和重建堆。时间复杂度也不同,构造初始堆的时间复杂度为O(n),重建堆的时间复杂度为O(nlogn),空间复杂度O(n)。
先附上一张搬运的经典过程图像
代码实现构造初始堆,即将无序的完全二叉树构建成一个大(小)根堆。
重建堆,即每次取出堆顶元素后将最后一个叶子节点转移到堆顶,再将其下推的过程。
因为是完全二叉树,所以直接用数组来存,这里方便起见,使用1作为根。实现过程直接看代码。
#include#include #include #include #include #include #include #include using namespace std; typedef long long int ll; const int MAX_N = 1e5+10; int tree[MAX_N];//堆(完全二叉树) //向下调整 inline void siftdown(int now,int n) { //当节点有儿子时 while((now<<1)<=n){ int temp = now; //先判断左儿子(因为没法保证有右儿子) if(tree[now] > tree[now<<1]) temp = now<<1; //接着判断右儿子,首先得保证有右儿子 if((now<<1|1) <= n) if(tree[temp] > tree[now<<1|1]) temp = now<<1|1; if(temp != now){ swap(tree[now],tree[temp]); //如果进行了交换,跟新now,便于下一步继续下推 now = temp; }else{ //如果没有进行交换,说明已经不用下推 break; } } } //建立初始堆 void creat(int n) { //从第一个非叶子节点到第一个节点依次向上调整 for(int i = n/2;i>=1;i--){ siftdown(i,n); } } //拿出堆顶元素 int getTop(int &n) { int temp; temp = tree[1];//记录堆顶元素 tree[1] = tree[n];//将最后一个节点移到堆顶 n--;//堆中元素个数-1 siftdown(1,n);//下推 return temp; } int main() { int n; cin>>n; for(int i = 1;i<=n;i++){ cin>>tree[i]; } creat(n); int all = n;//因为堆里元素个数在不断变化,用另一个变量保存初始堆元素个数 for(int i = 1;i<=n;i++){ cout<
快速排序基本思想初学者直接转链接,包懂:
视频链接:快速排序算法哔哩哔哩bilibili
文章链接:快速排序法(详解)小白的博客-CSDN博客快速排序
快速排序其实是冒泡排序的一种改进,随机选取待排序的一个数字P作为中心轴,使用双指针从两头开始寻找,比P小的放左指针,比P大的放右指针,双指针向中心靠拢。当双指针重合时,将数字P放于该位置。然后再次重置中心轴,循环以上过程。(看不懂的先去看链接,看完就懂了)
时间复杂度最坏情况:O(n^2),枢纽始终是最小元素。
最好情况:O(nlogn),枢纽恰好位于序列的中间。
平均情况: O(nlogn)。
代码实现#include#include #include #include #include #include #include #include using namespace std; typedef long long int ll; const int MAX_N = 1e5+10; int num[MAX_N]; int N; //从小到大排序 void mysort(int begin,int end) { if(begin>end) return ; int temp = num[begin];//中继枢纽 int l = begin; int r = end; while(l != r){ while(num[r] >= temp&&r>l) r--; //必须先找右边 while(num[l] <= temp&&l l){ swap(num[l],num[r]); } } //交换枢纽和r与l重合的点 swap(num[l],num[begin]); //左半部分进行 mysort(begin,l-1); //右半部分进行 mysort(r+1,end); } int main() { int n; cin>>n; N = n; for(int i = 1;i<=n;i++){ cin>>num[i]; } //快排 mysort(1,n); //检测 cout<<"从小到大排序"<
另外一个排序待更新。



