八大排序总结,10大排序
int index=getmid(a,left,right);
swap( a[left],a[index]);//默认键的位置是左边的第一个键
int begin=left
int end=right
int pivot=beginpit代表维修站位置
int key=a[begin];
While (begin end)//在一次行程中排序
While (a[end]=key begin end)//找到右边小的放在左边。
end-;
a[支点]=a[端];//把小的放在左边的坑里,自己形成一个新的坑。
枢轴=末端;
While (a[begin]=key begin end)//找到左边大的放在右边。
开始;
一个[支点]=一个[开始];//把大的放在右边的坑里,自己形成一个新的坑。
枢轴=开始;
枢轴=开始;//当begin==end时,循环结束,关键字赋给begin所在的位置。
一个[枢纽]=键;//按坑位分为两部分[left pivot-1]pivot[pivot 1 right]
If (pivot-1-left 10) //单元格间优化
快速排序(a,左,pivot-1);
其他
insertsort(a left,pivot-1-left 1);//随着递归的变化,左边的区间可能不是从0开始,右边的区间如果下标变化就会变成1。
如果(向右-(枢轴1) 10度)
快速排序(a,pivot 1,右);
其他
insertsort(a pivot 1,right-(pivot 1)1);
}
4.快速排序的时间复杂度
理想情况下,左右区间每次都被坑支点等分,也就是满二叉树。
每一层将遍历所有的数,所有层的时间复杂度为O(N)
根据二叉树的性质共遍历了度:2 h-1=n h=log n。
*快速排序的整体时间复杂度为O(NlogN)**
5.拿这三个数字来说。
最坏的情况是什么时候?
时间排序最差
按顺序,一次只能选择一个数,时间复杂度为O (n 2)。
所以为了防止这种情况发生,用三个数取中间。
6.单元之间的优化。
单元间优化用于减少函数调用的数量。
当我们递归的时候,会发现最后几层的函数调用占了绝大多数。
我们假设当一个区间内的差小于10时,就会被淘汰。
淘汰部分采用直接插入排序。
这里是直接插入排序:八种排序(第1部分)
2.左右指针法
简单来说,就是先从右侧寻找比关键字小的东西,再从左侧寻找比关键字大的东西。两者互换。
当left==right时,用关键字交换值。
2.代码实现
void swap(int* pa,int* pb)
int tmp=0;
tmp=* pa
* pa=* pb
* pb=tmp
Intpartsort (int * a,int left,int right)//左右指针方法
if(左=右)
返回;
int begin=left
int end=right
int key=left
while(开始结束)
while (a[end]=a[key] begin end)
end-;
while (a[begin]=a[key] begin end)
开始;
swap( a[begin],a[end]);//当左边找到小的,右边找到大的,两个值会互换。
swap(一个[键],一个[开始]);
返回开始;//[左,开始-1]开始[开始1,右]
Get mid (int * a,int left,int right)//为了防止排序,时间复杂度为O (n 2)
int mid=(左右)/2;
if(a[左]a[中])
如果(右)左)
向左返回;
else if (a[mid] a[right])
返回mid
其他
向右返回;
else//a[左]a[中]
如果(右)左)
向左返回;
else if (a[mid] a[right])
返回mid
其他
向右返回;
void快速排序(int* a,int left,int right)
int keyindex=partsort(a,left,right);
if (keyindex - 1 - left 10)
quicksort(a,左,keyindex-1);
其他
insertsort(a left,keyindex-1-left 1);//随着递归的变化,左边区间可能不是从0开始,右边区间是下标变化到1。
if(右- (keyindex 1) 10)
quicksort(a,keyindex 1,右);
其他
insertsort(a keyindex 1,right-(key index 1)1);
}
3.前后指针法
1.当cur的值大于key,cur
2.当cur的值小于key,prev时,交换两者的值。
3.当cur遍历数组时,它会将prev位置的值与key位置的值进行交换。
2.代码实现
void swap(int* pa,int* pb)
int tmp=0;
tmp=* pa
* pa=* pb
* pb=tmp
Get mid (int * a,int left,int right)//为了防止排序,时间复杂度为O (n 2)
int mid=(左右)/2;
if(a[左]a[中])
如果(右)左)
向左返回;
else if (a[mid] a[right])
返回mid
其他
向右返回;
else//a[左]a[中]
如果(右)左)
向左返回;
else if (a[mid] a[right])
返回中间的
其他
向右返回;
int partsort(int* a,int left,int right)//前后指针法
如果(左=右)
返回0;
int key=left
int prev=left
int cur=left 1;
while (cur=right)
if (a[cur] a[key] prev!=cur)//如果坏蛋位置值比键位置值小,上一页并交换两者值
{ //如果上一个向后移后的值与键位置值相等就不进入循环没有交换的必要
上一个
swap( a[prev],a[cur]);
坏蛋
swap( a[prev],a[key]);//当坏蛋出了正确范围,将上一个位置值与键位置值交换
返回上一个
空的快速排序(int* a,int left,int right)
int keyindex=partsort(a,left,right);
if (keyindex - 1 - left 10)
快速排序(a,左,key index-1);
其他
insertsort(a left,keyindex-1-left 1);//随着递归的变化,左区间有可能不从0开始,右区间是下标变化要一
如果(右-(关键索引1) 10)
快速排序(a,keyindex 1,右);
其他
insertsort(a keyindex 1,right-(key index 1)1);
}
4.非递归
非递归借助了数据结构栈的模拟:栈和队列的实现
栈有先进后出的原则,所以我们先判断下是否符合区间值一的条件,如果符合,则先将右边的右入栈,再入右边的左,其次入左边的右,再入,做左边的左
呈现出来则为,左边的左,右,右边的左,右
2.代码实现
int partsort(int* a,int left,int right)
如果(左=右)
返回0;
int begin=左
int end=right
int pivot=开始
int key=a[begin];
而(开始结束)
while (a[end]=键开始结束)
end-;
a[支点]=a[端];
枢轴=末端;
while (a[begin]=键开始结束)
开始;
一个[支点]=一个[开始];//把大的放在右边的坑位中,自己形成新的坑位
枢轴=开始;
枢轴=开始;//当begin==end时,循环结束,将关键字赋值给开始所在位置
一个[枢纽]=键;//通过坑位分成两部分[向左旋转-1]旋转[向右旋转1]
返回枢轴;
}
void快速排序(int * a,int n)
{
意法半导体
堆栈初始化(ST);
stackpush( st,n-1);//先将右输入再将左输入
stackpush( st,0);//输出时,则为左先输出,右再输出
而(!stackempty( st))
{
int left=栈顶(ST);
堆栈弹出(ST);
int right=栈顶(ST);
堆栈弹出(ST);
int keyindex=partsort(a,left,right);//[左关键索引-1]关键索引[右关键索引1]
if (keyindex 1 right)//栈符合先进后出的原则
{
堆栈推进(st,右);//先入右区间的右再入右区间的左
stackpush( st,关键指标1);//输出右区间的左再输出右
}
if (left keyindex - 1)//再入左区间的右左区间的左
{
stackpush( st,key index-1);//输出左区间的左,再输出右
堆栈推进(左一);
}
}
堆栈销毁(ST);
}
# 二、归并排序
## 1.递归
### 1.过程
![在这里插入图片描述](https://s 2.51 CTO。com/images/blog/202209/26064932 _ 6330 dafc 9 b 64413167。png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type _ zm fuz 3 poz w5 nagvpdgk=/resize,m_fixed,w_750)
通过递归的方式使左半区间与右半区间有序,最后使整体区间有序
### 2.代码实现
void mergesort(int* a,int left,int right,int* tmp)//
if (left=right)//当区间不存在或者只有一个时返回
返回;
int mid=(左右)/2;
mergesort(a,left,mid,tmp);//左半区间
mergesort(a,mid 1,right,tmp);//右半区间
int begin1=左
int end1=mid
int begin 2=mid 1;
int end2=右
int index=左
while(开始1=结束1开始2=结束2)//将小的的依次放入新的临时数组中
如果开始,开始
tmp[索引]=a[begin 1];
指数;
开始1;
其他
tmp[索引]=a[begin 2];
指数;
开始2
while (begin1=end1)//如果此时的左区间未完全排完则进入循环
tmp[索引]=a[begin 1];
指数;
开始1;
while (begin2=end2)//如果此时的右区间未完全排完则进入循环
tmp[索引]=a[begin 2];
指数;
开始2
int I=0;
for(I=0;我=对;i )//将此时排好的临时数组传回原数组中
a[I]=tmp[I];
Void sort(int* a,int n)//合并排序递归
int left=0;
int right=n-1;
int * tmp=(int *)malloc(sizeof(int)* n);
mergesort(a,left,right,tmp);
免费(tmp);
3.合并和排序的时间复杂度。
每次都被分成两半。
可以看作是一棵完整的二叉树。
2^h-1=n h=对数n
向上递归排序时,每层的区间排序会遍历到所有的数n。
时间复杂度为O(N)
即*合并和排序的总时间复杂度为O(Nlog N)**
4.递归的缺陷
如果堆栈深度太深,堆栈空间不够,可能会造成溢出。
2.非递归的
采用一个周期,从前一个底部开始,有序结束。
假设数组中有8个数字。
通过*[i,i gap-1] [i gap,i 2gap-1],每次分为两个区间* *
当gap为1时,左间隔号为1,右间隔号为1。
当gap为2时,左区间数为2,右区间数为2。
当gap为4时,左区间数为4,右区间数为4。
2.代码实现
void mergesortNonR(int* a,int n)
int * tmp=(int *)malloc(sizeof(int)* n);
int gap=1;
int I=0;
while(间隙n)
for(I=0;I=2 * gap)//以间隙间隔分为1 ^ 2 ^ 4。
int begin 1=I;//[i i gap-1] [i gap i 2*gap-1]
int end 1=I gap-1;
int begin2=i gap
int end 2=I ^ 2 * gap-1;
int index=I;
If (begin2=n)//右区间可能不存在
打破;
如果(end2=n)//右边区间太多,请改正。
end 2=n-1;
while(begin 1=end 1 begin 2=end 2)//排序
如果(a[begin1] a[begin2])
tmp[index]=a[begin 1];
指数;
开始1;
其他
tmp[索引]=a[begin 2];
指数;
begin2
while (begin1=end1)
tmp[index]=a[begin 1];
指数;
开始1;
while (begin2=end2)
tmp[索引]=a[begin 2];
指数;
begin2
int j=0;
for(j=I;j=end2j)
a[j]=tmp[j];
gap *=2;
免费(tmp);
}
3.预防措施
当左区间存在而右区间不存在时,左区间不需要合并。
当左音程的四个数字与右音程合并时
发现右区间只有三个数,第四个数不存在,于是将第三个数修正为end2。
当左区间的个数不足以除以gap,且右区间不存在时,如果复制回左区间,就会出现随机值。
所以合并的就复制回来,不复制的就不用复制了,所以返回过程就放成了一个循环。
三。计数排序
1.统计,对应其下标的大小,观察每个下标对应的数字,直接按顺序输出,就是绝对映射位置。
2.如果数量太大,前面的空间就浪费了,所以要避免这种情况的发生,就要进行相对位置的映射。
2.代码实现
时间复杂度为O(N)
void countsort(int* a,int n)
int I=0;
int j=0;
int max=a[0];
int min=a[0];
for(I=0;我我)
if (max a[i])
max=a[I];
如果(阿敏[我])
min=a[I];
int range=max-min 1;//从0开始,所以多了一个数
int * count=(int *)malloc(sizeof(int)* range);
memset(count,0,sizeof(int)* range);//将所有计数初始化为0
for(I=0;I)//计算次数
count[a[I]-min];//a[i]-min是相对映射位置。
for(I=0;I范围;I )//遍历下标范围
while(count[I]-)//判断每个下标中的次数
a[j]=I min;
j;
免费(计数);
}
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。