排序算法
1、排序算法的稳定性:
①稳定的:关键字相同的元素在排序后相对位置不变
②不稳定的:关键字相同的元素在排序后相对位置改变
2、排序算法分类:内部排序,外部排序。
插入排序
1、算法思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。
2、①直接插入排序②带哨兵的直接插入排序(不用temp,将首位置设为空,将需要排序的关键码复制为哨兵)优点:不需要每轮循环判断j>=0
3、空间复杂度:O(1) 。时间复杂度:最好O(n)、最坏O(n²)、平均O(n²)
4、直接插入排序示例(不含哨兵):
#include<stdio.h>
# define N 5
void Input();
void InsertSort();
void Output();
int A[N],i;
void Input()
{printf("请输入需插入排序数字:\n");
for(i=0;i<N;i++)
scanf("%d",&A[i]);
}
void InsertSort(){
int j,temp;
for(i=1;i<N;i++)
if(A[i]<A[i-1]){
temp=A[i];
for(j=i-1;j>=0&&A[j]>temp;--j)
A[j+1]=A[j];
A[j+1]=temp;
}
}
void Output()
{printf("直接插入排序后为:\n");
for(i=0;i<N;i++)
printf("%d\t",A[i]);
}
int main(){
Input();
InsertSort();
Output();
return 0;
}
优化——折半插入排序(顺序表)
1、思路:先用折半查找找到应该插入的位置,再移动元素。(最终将当前元素插入到low即high+1的位置)为保障算法稳定性,折半查找至相等时将不会停止,应继续在mid右边继续寻找插入位置。
2、折半查找:对比需移动的元素与mid的大小,通过比较不断缩小确定插入位置,相等或low>high时将停止查找。
3、时间复杂度:O(n²)
4、含哨兵的折半插入排序示例:
void InsertSort(){
int i,j,low,high,mid;
for(i=2;i<=N;i++){
A[0]=A[i];
low=1,high=i-1;
while(low<=high){
mid=(low+high)/2;
if(A[mid]>A[0])
high=mid-1;
else low=mid+1;
}
for(j=i-1;j>=high+1;--j)
A[j+1]=A[j];
A[high+1]=A[0];
}
}
优化——希尔排序(顺序表)
1、思想:先追求表中元素部分有序,再逐渐逼近全局有序。
2、实现过程:增量d值为元素个数除2(可能会已知各种增量),将相差相同d的分为不同子表后对子表进行直接排序,每次将d减半,直至d=1后最终对整体进行一次直接插入排序。如:d=4,则1、5为子表1, 2、6为子表2,分别对子表1、2中元素进行直接排序。
3、空间复杂度:O(1) 。时间复杂度:最坏O(n²)即直接插入排序。
4、稳定性:不稳定
5、示例:
#include<stdio.h>
#define N 5
int A[N],i,temp;
void ShellSort(){
int d,i,j;
for(d=N/2;d>=1;d=d/2){
for(i=d+1;i<=N;++i){
for(j=i-d;j>=0;j=j-d){
if(A[j]>A[j+d]){
temp = A[j];
A[j] = A[j+d];
A[j+d] = temp;
}
}}}}
void Input()
{
printf("请输入5个需插入排序数字:\n");
for(i=0;i<N;i++){
scanf("%d",&A[i]);}
}
void Output()
{
printf("插入排序后为:\n");
for(i=0;i<N;i++){
printf("%d\t",A[i]);
}
}
int main(){
Input();
ShellSort();
Output();
return 0;
}