①:直接插入排序(直插法):将一个记录插入到一个已经排序好的有序表
设表尾最后那个是“要插入表的元素”
#define MaxSize 10// 最大长度
#define ok 0
typedef int KeyType;//整形
typedef int InfoType;
typedef struct{
KeyType key;
InfoType otherinfo;
}RedType;
typedef struct{
RedType r[MaxSize+1];//r[0]闲置或用做哨兵单元
int length;//顺序表长度
}SqList,*SqListLink;
typedef SqList HeapType;
//--------------比较函数-----------------//
int LT(KeyType key1,KeyType key2){
if (key1<key2) return 1;//1
else return 0;//0
}
//---------------排序------------------//
void InsertSort(SqList *L){
int i=1,j=0;
for(;i<=(*L).length;++i)
if(LT((*L).r[i].key,(*L).r[i-1].key)){
//靠近表头的比靠近表尾的大
(*L).r[0]=(*L).r[i];//将小(相对靠近表尾)的入哨兵
(*L).r[i]=(*L).r[i-1];//将大(相对靠近表头)的向后
for(j=i-2;LT((*L).r[0].key,(*L).r[j].key);--j)
(*L).r[j+1]=(*L).r[j];//与哨兵做比较,比哨兵大 移位
(*L).r[j+1]=(*L).r[0];///哨兵
}
printf("排序好后数据:");
for(i=1;i<=(*L).length;i++){
printf("% 2d",(*L).r[i].key);
}
return ok;
}
void Init_SqList(SqList *L){//初始化顺序表,下面还要用,只在这里写
printf("有个数据不符合规律 哨兵设置为0,共多少个数据:");
int length;
scanf("%d",&length);
int i=0;
printf("哨兵:");
scanf("%d",&(L->r[0].key));
for(i=1;i<=length;i++){//L.r[0]为哨兵位置
scanf("%d",&(L->r[i].key));
}
L->length=length;
printf("初始化数据\n");
for(i=0;i<=L->length;++i){
printf("% 2d",L->r[i].key);
}
return ok;
}
void SqListTest(){//相当于main 下同
SqList L;
Init_SqList(&L);
InsertSort(&L);
}
原来的key: 38,49,65,97,76(要进行排序的那个)关键字比较次数:(n²)/4,时间复杂度:O(n²)
②:折半插入排序(半插法):
void BInsertSort(SqList *L){
int i,j,m,low,high;
for(i=2;i<=L->length;++i){
L->r[0]=L->r[i];//从“表尾”进一个排一个;表尾从2~3~.....最后一个
low=1,high=i-1;
while(low<=high){
m=(low+high)/2;
if(LT(L->r[0].key,L->r[m].key)) high=m-1;
else low=m+1;
}//while
for(j=i-1;j>=high+1;--j) L->r[j+1]=L->r[j];
L->r[high+1]=L->r[0];
}//for
}
void SqListTest(){
SqList L;
Init_SqList(&L);
BInsertSort(&L);
}
void ShellInsert(SqList *L,int dk){
int i,j;
for(i=dk+1;i<=L->length;++i){
if(LT(L->r[i].key,L->r[i-dk].key)){//后面的比前面的小
L->r[0]=L->r[i];//小的入哨兵
for(j=i-dk;j>0&<(L->r[0].key,L-r[j].key);j-=dk)
L->r[j+dk]=L->r[j];//换位
L->r[j+dk]=L->r[0];
}//if
}//for i
printf("排序ing--:\n");
for(j=1;j<=L->length;++j)
printf("% d",L->r[j].key);
}
void ShellSort(SqList *L,int dlta[],int t){
int k;
for(k=0;k<t;++k) ShellInsert(L,dlta[k]);
printf("排序后:");
for(k=1;k<=L->length;++k) printf("% 2d",L->r[k].key);
}
void SqListTest(){
SqList L;int sum,i;
printf("共有dlta值几个:");
scanf("%d",&sum);
int dlta[sum];
Init_SqList(&L);
printf("输入dlta值:\n");
for(i=0;i<sum;++i)
scanf("%d",&dlta[i]);
ShellSort(&L,dlta,sum);
}
①:快速选择排序(快排):
选择一个枢轴
int Partition(SqList *L,int low,int high){//一次快排
int pivotkey;//枢轴
L-r[0]=L->r[low];
pivotkey=L->r[low].key;
while(low<high){
while(low<high&&L->r[high].key>=pivotkey) --high;//大于枢轴,high就一直往‘左’移动位置
L->r[low]=L->r[high];
while(low<high&&L->r[low].key>=pivotkey) ++low;//大于枢轴,low就一直往‘右’移动位置
L->r[high]=L->r[low];
}//while
L->r[low]=L->r[0];
return low;
}
void Qsort(SqList *L,int low,int high){
int pivotloc;
if(low<high){
pivotloc=Partition(L,low,high);//一次快排定位后已经分为两个“比较”有序的俩半
Qsort(L,low,pivotloc-1);
Qsort(L,pivotloc+1,high);
}
}
void SqListTest(){
SqList L;
Init_SqList(&L);
Qsort(&L,1,8);
}
时间复杂度:平均:**O(nlog2n),最坏:O(n²)**进来的是有序的
①堆排序:
分为大顶堆和小顶堆,一次堆排序只输出一个堆顶值
成为堆的条件:1小顶堆 Ki<=K₂i && Ki<=K(₂i+1) 2大顶堆 Ki>=K₂i && Ki>=K(₂i+1)
大顶堆多次堆排序的演绎:每排一次得到最大值就放在堆尾
void HeapOnceAdjust(HeapType *H,int s,int m){//s为顶点下标 m表示表长
RedType rc=H->r[s];//堆顶先赋值给RC
int j;
for(j=2*s;j<m;j*=2){
if(j<m&<(H->r[j].key,H->r[j+1].key)) ++j;//j为Key较大值得下标
if(!LT(rc.key,H->r[j].key)) break;
H->r[s]=H->r[j];s=j;
}
H->r[s]=rc;//H->r[s] 原来的消息已经移走上去了
}
void HeapSort(HeapType *H){
int i=0;
for(i=(H->length)/2;i>0;--i){
HeapOnceAdjust(H,i,H->length);
}//将数据变成大顶堆
for(i=H->length;i>1;--i){
H->r[0]=H->r[1];
H->r[1]=H->r[i];
H->r[i]=H->r[0];
HeapOnceAdjust(H,1,i-1);
}
printf("排序后:\n");
for(i=1;i<=H->length;i++){
printf("% 2d",H->r[i].key);
}
}
void SqListTest(){
SqList L;
Init_SqList(&L);
HeapSort(&L);
}
时间复杂度:O(nlog2n) 其中m,n是两个有序表的表长
相当于:有序表+有序表=有序表
表中,二二做比较,大的排后,小的排前,多次归并即可。
2-路归并的思想:将一维数组中 前后相邻的两个有序序列归并为一个有序序列
,m是归并的路数,n是关键字次数。
时间复杂度:O(nlog2n)
1:如果输入序列是有序的:直插算法最快结束,快排最慢结束
2:不稳定的算法有:快排,希尔,选排,堆排(快 些 选 堆 美女)