数据结构几种常见的排序算法比较

数据结构中,常见的排序算法有起泡法,直接插入法,简单选择法,快速排序法,希尔排序,堆排序法,其中每种算法对数据的比较次数和平均移动次数不同,在此,运用C++仿真将每种算法的优略性进行对比。

1.起泡法

每趟不断将记录两两比较,并按“前小后大” 规则交换

a)代码

#include<stdio.h>
#include<stdlib.h>


void getdata(int key[],int j)
{int i;
srand(j);
for(i=0;i<100;i++)
{key[i]=rand()%150; /*生成150以内的随机数*/
}
}

void maopao(int key[],float *compare,float *mov)
{int i,j;
int t;
for(j=99;j>1;j--)
{for(i=0;i+1<=j;i++)
{(*compare)++;
 if(key[i]>key[i+1])
 {t=key[i];
 key[i]=key[i+1];
 key[i+1]=t;
 (*mov)++;

 }
}}
}





void main()
{int key[100];
float compare[5]={0};
float mov[5]={0};
int i;
float avec,avem;
for(i=0;i<5;i++)
{getdata(key,i);
maopao(key,&compare[i],&mov[i]);
}
avec=(compare[0]+compare[1]+compare[2]+compare[3]+compare[4])/5;
avem=(mov[0]+mov[1]+mov[2]+mov[3]+mov[4])/5;
printf("冒泡法的平均比较次数为%f\n    平均移动次数为%f\n",avec,avem*3);
}

b)运行结果

 2.直接插入法

先将序列中第1个记录看成是一个有序子序列,然后从第2个记录开始,逐个进行插入,直至整个序列有序

a)代码

 #include<stdio.h>
#include<stdlib.h>


void getdata(int key[],int j)
{int i;
srand(j);
for(i=0;i<100;i++)
{key[i]=rand()%150; /*生成150以内的随机数*/
}
}

void din(int key[],float *compare,float *mov)
{int t,i,j;
for(i=1;i<100;i++)
{t=key[i];(*mov)++;
for(j=i-1;j>=0;j--)
{(*compare)++;
	if(t<key[j])
	{key[j+1]=key[j];}
	else {key[j+1]=t;(*mov)++;}
}}}



void main()
{int key[100];
float compare[5]={0};
float mov[5]={0};
int i;
float avec,avem;
for(i=0;i<5;i++)
{getdata(key,i);
din(key,&compare[i],&mov[i]);
}
avec=(compare[0]+compare[1]+compare[2]+compare[3]+compare[4])/5;
avem=(mov[0]+mov[1]+mov[2]+mov[3]+mov[4])/5;
printf("直接插入排序的平均比较次数为%f\n    平均移动次数为%f\n",avec,avem);

b)结果

 3.简单选择

直接选择排序是一种简单的排序方法 基本步骤:
在一组对象 V[ i ] V[ n -1] 中选择具有最小排序码的对象;
若它不是这组对象中的第一个对象 , 则将它与这组对象中的第一个对象对调;
在这组对象中剔除这个具有最小排序码的对象。在剩下的对象 V[i+1] V[n-1] 中重复执行第①、②步 , 直到剩余对象只有一个为止。

 a)代码

 #include<stdio.h>
#include<stdlib.h>


void getdata(int key[],int j)
{int i;
srand(j);
for(i=0;i<100;i++)
{key[i]=rand()%150; /*生成150以内的随机数*/
}
}

void easych(int key[],float *compare,float *mov)
{int i,j,t;
int min;
for(i=0;i<100;i++)
{min=i;
for(j=i+1;j<100;j++)
{(*compare)++;
if(key[j]<key[min]) min=j;}
if(min!=i) 
{t=key[i];
key[i]=key[min];
key[min]=t;
(*mov)=(*mov)+3;}}}



void main()
{int key[100];
float compare[5]={0};
float mov[5]={0};
int i;
float avec,avem;
for(i=0;i<5;i++)
{getdata(key,i);
easych(key,&compare[i],&mov[i]);
}
avec=(compare[0]+compare[1]+compare[2]+compare[3]+compare[4])/5;
avem=(mov[0]+mov[1]+mov[2]+mov[3]+mov[4])/5;
printf("简单选择排序的平均比较次数为%f\n    平均移动次数为%f\n",avec,avem);
}

b)结果

 4.快速排序法

①任取一个元素 ( 如第一个 ) 为中心(基准,枢轴变量)
②所有比它 的元素一律前放,比它 的元素一律后放,形成 左右两个子表
③对各子表重新选择 中心 元素并依此规则调整,直到每个子表的元素 只剩一个

 a)代码

 #include<stdio.h>
#include<stdlib.h>


void getdata(int key[],int j)
{int i;
srand(j);
for(i=0;i<100;i++)
{key[i]=rand()%150; /*生成150以内的随机数*/
}
}


int part(int key[],float *compare,float *mov,int low,int high)
{int t;
t=key[low];
while((low)<(high))
{
	while((low)<(high)&&key[high]>=t) {(high)--;(*compare)++;}
	(*compare)++;
key[low]=key[high];
(*mov)++;

while((low)<(high)&&key[low]<t) {low++;(*compare)++;}
(*compare)++;
key[high]=key[low];(*mov)++;
}
key[low]=t;
return low;}


void quicksort(int key[],float *compare,float *mov,int low,int high)
{
	if((low)<(high))
{int L=part(key,compare,mov,low,high);
	quicksort(key,compare,mov,low,L-1);
	quicksort(key,compare,mov,L+1,high);}}






void main()
{int key[100];
float compare[5]={0};
float mov[5]={0};
int i;
float avec,avem;
for(i=0;i<5;i++)
{getdata(key,i);
quicksort(key,&compare[i],&mov[i],0,99);
}
avec=(compare[0]+compare[1]+compare[2]+compare[3]+compare[4])/5;
avem=(mov[0]+mov[1]+mov[2]+mov[3]+mov[4])/5;
printf("快速排序的平均比较次数为%f\n    平均移动次数为%f\n",avec,avem);
}

b)结果

 5.希尔排序

①先将整个序列按某个增量分割成若干子序列,分别进行直接插入排序

② 减小增量,将序列分割为更大、更有序的子序列,再分别进行直接插入排序

③ 如此重复下去,直到整个序列“基本有序”时,再对全体记录进行一次直接插入排序

a)代码

 #include<stdio.h>
#include<stdlib.h>


void getdata(int key[],int j)
{int i;
srand(j);
for(i=0;i<100;i++)
{key[i]=rand()%150; /*生成150以内的随机数*/
}
}


void shell(int key[],int dk[],float *compare,float *mov)
{int i,j,k;int t;
for(k=0;k<5;k++)
for(i=dk[k]+1;i<100;i++)
	{(*compare)++;
		if(key[i]<key[i-dk[k]])
		{t=key[i];
		for(j=i-dk[k];j>0&&t<key[j];j=j-dk[k])
		{key[j+dk[k]]=key[j];(*mov)++;(*compare)++;}
	(*compare)++;
		key[j+dk[k]]=t;(*mov)++;
		}}}


void main()
{int key[100];
float compare[5]={0};
float mov[5]={0};
int dk[5]={7,5,3,2,1};
int i;
float avec,avem;
for(i=0;i<5;i++)
{getdata(key,i);
shell(key,dk,&compare[i],&mov[i]);
}
avec=(compare[0]+compare[1]+compare[2]+compare[3]+compare[4])/5;
avem=(mov[0]+mov[1]+mov[2]+mov[3]+mov[4])/5;
printf("希尔插入排序的平均比较次数为%f\n    平均移动次数为%f\n",avec,avem);
}

b)结果

 6.堆排序

①将无序序列建成一个堆
②输出堆顶的最小(大)值
③使剩余的n-1个元素又调整成一个堆,则可得到n个元素的次小值
④重复执行,得到一个有序序列
a)代码
#include<stdio.h>
#include<stdlib.h>


void getdata(int key[],int j)
{int i;
srand(j);
for(i=0;i<100;i++)
{key[i]=rand()%150; /*生成150以内的随机数*/
}
}


void ad(int key[],int s,int m,float *compare,float *mov)
{int t,j;
t=key[s];(*mov)++;
for(j=2*s;j<m;j*=2)
{(*compare)++;
if(j<m&&key[j]<key[j+1]) j++;
(*compare)++;
if(t>key[j]) break;
key[s]=key[j];s=j;(*mov)++;
}
key[s]=t;(*mov)++;}

void order(int key[],float *compare,float *mov)
{int i;int t;
for(i=50;i>=0;i--)
	ad(key,i,100,compare,mov);
for(i=99;i>0;i--)
{t=key[1];key[1]=key[i];key[i]=t;(*mov)=(*mov)+3;
ad(key,1,i-1,compare,mov);}}



void main()
{int key[100];
float compare[5]={0};
float mov[5]={0};

int i;
float avec,avem;
for(i=0;i<5;i++)
{getdata(key,i);
order(key,&compare[i],&mov[i]);
}
avec=(compare[0]+compare[1]+compare[2]+compare[3]+compare[4])/5;
avem=(mov[0]+mov[1]+mov[2]+mov[3]+mov[4])/5;
printf("堆排序的平均比较次数为%f\n    平均移动次数为%f\n",avec,avem);
}

b)结果

 

总结:

  1. 比较次数上,起泡、直接插入、简单选择的次数相同,数据之间两两均有一次比较,比较次数较少的是快速排序、希尔排序和堆排序。

        2.关键字移动次数上,冒泡法需要不断的交换来冒泡,因此其交换次数远大于其他方法,而移动次数最少的是简单选择,该方法是在找到插入位置后才进行交换,因此交换次数最少

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值