题目要求:
内部排序算法比较
[问题描述]
各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间。试通过随机的数据比较各算法的关键字比较次数和关键字移动次数,以取得直观感受。
[基本要求]
(1) 对以下8种常用的内部排序算法任意选择8种进行比较:直接插入排序;希尔排序;冒泡排序;快速排序;简单选择排序;堆排序;归并排序;基数排序。
(2) 待排序表的表长不小于100;其中的数据要用伪随机数产生程序产生;至少要用5组不同的输入数据作比较;比较的指标为有关键字参加的比较次数和关键字移动次数(关键字交换计为3次移动)。
[测试数据]
由随机产生器决定。
[实现提示]
主要工作是设法在程序中适当的地方插入计数操作。程序还可以包括计算几组数据得出结果波动大小的解释。注意分块调试的方法。
代码:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#define SIZE 2000
typedef struct Radix
{
int nValue;
struct Radix *pNext;
}Radix;
void MIN(double *average_move,double *average_compare);
void Insert_sort(int *number,int n,int &move,int &compare,int &sing);
void Shell_sort(int *number,int n,int &move,int &compare,int &sing);
void Bubble_sort(int *number,int n,int &move,int &compare,int &sing);
int partition(int *number, int s, int t);
void Quick_sort(int *number,int s,int t,int &move,int &compare,int &sing);
void Selection_sort(int *number,int n,int &move,int &compare,int &sing);
void Down(int a[], int i, int n);
void Build_Heap(int a[], int size);
void Heap_sort(int *number,int n,int &move,int &compare,int &sing);
void Merge(int *number,int left,int right,int mid,int &move,int &compare);
void Merge_sort(int *number,int left,int right,int &move,int &compare,int &sing);
void Radix_sort(int *number,int n,int &move,int &compare,int &sing);
void print(double *move,double *compare);
void Genert_random_numbers(int *number,int n);
double average(int *shu);
void Error(int sing);
void PRINT(double *move,double *compare);
int main () {
int x,i=0;
double average_move[8],average_compare[8];
do{
printf ("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n*\n");
printf ("* 1: 输入1生成数据表格 *\n*\n");
printf ("* 2: 输入-1退出程序 *\n*\n");
printf ("* 3: 输入0得出结论 *\n*\n");
printf ("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n") ;
printf ("* 请输入:");
scanf ("%d",&x);
if (x==1){
printf ("case %d:\n",i++);
MIN(average_move,average_compare);
printf ("\n");
printf ("是否输出最小结果:1(输出) 2(不输出)\n请输入1或2:");
int c;
scanf ("%d",&c);
if (c==1){
print(average_move,average_compare);
}
}else if (x==0){
print(average_move,average_compare);
}else if (x==-1){
printf ("退出程序");
break;
}
}while(1);
return 0;
}
void MIN(double *average_move,double *average_compare){
int n=SIZE,j,i,k;
int Insert_move[6]= {0},Insert_compare[6]= {0};
int Shell_move[6]= {0},Shell_compare[6]= {0};
int Bubble_move[6]= {0},Bubble_compare[6]= {0};
int Quick_move[6]= {0},Quick_compare[6]= {0};
int Simple_selection_move[6]= {0},Simple_selection_compare[6]= {0};
int Heap_move[6]= {0},Heap_compare[6]= {0};
int Merge_move[6]= {0},Merge_compare[6]= {0};
int Radix_move[6]= {0},Radix_compare[6]= {0};
int number[SIZE];
int left=0,right=n-1,s=0,t=n-1;
for (k=0; k<8; k++) {
for (j=0; j<6; j++) {
Genert_random_numbers(number,n);
int sing=-1;
switch(k) {
case 0:
Insert_sort(number,n,Insert_move[j],Insert_compare[j],sing);
break;
case 1:
Shell_sort(number,n,Shell_move[j],Shell_compare[j],sing);
break;
case 2:
Bubble_sort(number,n,Bubble_move[j],Bubble_compare[j],sing);
break;
case 3:
Quick_sort(number,s,t,Quick_move[j],Quick_compare[j],sing);
break;
case 4:
Selection_sort(number,n,Simple_selection_move[j],Simple_selection_compare[j],sing);
break;
case 5:
Heap_sort(number,n,Heap_move[j],Heap_compare[j],sing);
break;
case 6:
Merge_sort(number,left,right,Merge_move[j],Merge_compare[j],sing);
break;
case 7:
Radix_sort(number,n,Radix_move[j],Radix_compare[j],sing);
break;
}
if (sing!=-1)Error(sing);
}
}
for (k=0; k<8; k++) {
switch(k) {
case 0:
average_move[k]=average(Insert_move);
average_compare[k]=average(Insert_compare);
break;
case 1:
average_move[k]=average(Shell_move);
average_compare[k]=average(Shell_compare);
break;
case 2:
average_move[k]=average(Bubble_move);
average_compare[k]=average(Bubble_compare);
break;
case 3:
average_move[k]=average(Quick_move);
average_compare[k]=average(Quick_compare);
break;
case 4:
average_move[k]=average(Simple_selection_move);
average_compare[k]=average(Simple_selection_compare);
break;
case 5:
average_move[k]=average(Heap_move);
average_compare[k]=average(Heap_compare);
break;
case 6:
average_move[k]=average(Merge_move);
average_compare[k]=average(Merge_compare);
break;
case 7:
average_move[k]=average(Radix_move);
average_compare[k]=average(Radix_compare);
break;
}
}
PRINT(average_move,average_compare);
}
void print(double *move,double *compare){
int move_min=0,compare_min=0;
for (int i=0;i<8;i++){
if (move[i]<move[move_min]){
move_min=i;
}
if (compare[i]<compare[compare_min]){
compare_min=i;
}
}
switch(move_min){
case 0:
printf ("插入排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 1:
printf ("希尔排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 2:
printf ("冒泡排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 3:
printf ("快速排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 4:
printf ("简单选择排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 5:
printf ("堆排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 6:
printf ("归并排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
case 7:
printf ("基数排序次数移动最少:移动次数平均数为%f\n\n",move[move_min]);
break;
}
switch(compare_min){
case 0:
printf ("插入排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 1:
printf ("希尔排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 2:
printf ("冒泡排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 3:
printf ("快速排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 4:
printf ("简单选择排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 5:
printf ("堆排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 6:
printf ("归并排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
case 7:
printf ("基数排序次数比较最少:比较次数平均数为%f\n\n",compare[compare_min]);
break;
}
}
void Genert_random_numbers(int *number,int n) {
int i=0;
srand((unsigned int)time(NULL));
for (i=0; i<n; i++) {
number[i]=rand()%(1000-10+1)+10;
}
}
void Error(int sing) {
switch(sing) {
case 0:
printf ("Insert_sort han shu fan hui cuo wu\n");
break;
case 1:
printf ("Shell_sort han shu fan hui cuo wu\n");
break;
case 2:
printf ("Bubble_sort han shu fan hui cuo wu\n");
break;
case 3:
printf ("Quick_sort han shu fan hui cuo wu\n");
break;
case 4:
printf ("Selection_sort han shu fan hui cuo wu\n");
break;
case 5:
printf ("Heap_sort han shu fan hui cuo wu\n");
break;
case 6:
printf ("Merge_sort han shu fan hui cuo wu\n");
break;
case 7:
printf ("Radix_sort han shu fan hui cuo wu\n");
break;
}
}
void PRINT(double *move,double *compare) {
for (int i=0;i<50;i++){
printf("_");
}
printf ("\n");
int len=10,i,j;
printf ("| Sort_name | Average_move Average_compare |\n");
printf ("| |");
printf ("\n");
for (i=0; i<8; i++) {
switch(i) {
case 0:
printf ("| Insert_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| | ");
break;
case 1:
printf ("| Shell_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| |");
break;
case 2:
printf ("| Bubble_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| |");
break;
case 3:
printf ("| Quick_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| |");
break;
case 4:
printf ("| Selection_sort| %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| |");
break;
case 5:
printf ("| Heap_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| |");
break;
case 6:
printf ("| Merge_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
printf ("| |");
break;
case 7:
printf ("| Radix_sort | %-8.2f %-8.2f |\n",move[i],compare[i]);
break;
}
if (i!=7){
printf ("\n");
}
}
for (j=0; j<50; j++) {
printf ("-");
}
}
double average(int *shu) {
int sum=0,i;
for (i=0; i<6; i++) {
sum+=shu[i];
}
return sum/6;
}
void print(int *newnumber) {
for (int i=0; i<SIZE; i++) {
printf ("%-5d",newnumber[i]);
}
printf ("\n");
}
/*
插入排序
*/
void Insert_sort(int *number,int n,int &move,int &compare,int &sing) {
int i,j,temp;
move=0,compare=0;
for (i=1; i<n; i++) {
if (number[i]<number[i-1]){
temp=number[i];
for (j=i-1; j>=0&&number[j]>temp; j--) {
number[j+1]=number[j];
compare++;
move++;
}
number[j+1]=temp;
move++;
}
}
}
/*
希尔排序
*/
void Shell_sort(int *number,int n,int &move,int &compare,int &sing) {
int i,temp,j,dk=n/2;
move=0,compare=0;
while(dk>0) {
for(i=dk; i<n; i+=dk)
for(j=i; j>0; j-=dk)
if(number[j]<number[j-dk]) {
temp=number[j];
number[j]=number[j-dk];
number[j-dk]=temp;
compare++;
move++;
}
dk=dk/2;
}
}
/*
冒泡排序
*/
void Bubble_sort(int *number, int n,int &move,int &compare,int &sing) {
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = n - 1; j > i; j--) {
if (number[j] < number[j - 1]) {
compare++;
move += 3;
int tmp = number[j - 1];
number[j - 1] = number[j];
number[j] = tmp;
}
}
}
}
/*
快速排序
*/
int partition(int *number, int s, int t,int &move,int &compare) { //一趟划分
int i = s, j = t;
int tmp = number[i]; //以a[i]为基准
while (i < j) {
//从两端交替向中间扫描,直至i=j为止
while (j > i && number[j] >= tmp) {
j--; //从右向左扫描,找一个小于tmp的a[j]
compare++; //进行比较
}
number[i] = number[j]; //找到这样的a[j],放入a[i]处
move++; //移动+1
while (i < j && number[i] <= tmp) {
i++; //从左向右扫描,找一个大于tmp的a[i]
compare++; //比较加一
}
number[j] = number[i]; //找到这样的number[i],放入a[j]处
move++; //移动加一
}
number[i] = tmp;
move += 2; //temp的交换
return i;
}
void Quick_sort(int *number, int s, int t,int &move,int &compare,int &sing) {
int i;
if (s < t) {
i = partition(number, s, t,move,compare);
Quick_sort(number, s, i - 1,move,compare,sing);//对左递归排序
Quick_sort(number, i + 1, t,move,compare,sing);//对右递归排序
}
}
/*
选择排序
*/
void Selection_sort(int *number,int n,int &move,int &compare,int &sing) {
int min;
int i,j;
for (i = 0; i<n; i++) {
min = i;
for (j = i+1; j<n; j++) {
compare++;
if (number[j]<number[min]) {
min = j;
}
}
if(min != i) {
int tmp = number[i];
number[i] = number[min];
number[min] = tmp;
move += 3;
}
}
}
/*
堆排序
*/
// 大顶堆
void Down(int a[], int i, int n,int &move,int &compare) {
int parent = i; // 父亲
int child = 2 * i + 1; // 孩子
while (child < n) {
if (child + 1 < n) {
compare++;
// 判断子节点那个大,大的与父节点比较 比较次数+1
if(a[child] < a[child + 1])
child++;
}
compare++;
if (a[parent] < a[child]) {
int key = a[parent];
a[parent] = a[child];
a[child] = key;
move +=3; //交换+3
parent = child; // 子节点给父节点
}
child = child * 2 + 1;
}
}
//初始化
void Build_Heap(int a[], int size,int &move,int &compare) {
int i;
for (i = size / 2 - 1; i >= 0; i--) {
Down(a, i, size,move,compare);
}
}
void Heap_sort(int *number, int n,int &move,int &compare,int &sing) {
Build_Heap(number, n,move,compare);//初始化
int i;
for (i = n - 1; i > 0; i--) {
// 交换数据
int key = number[0];
number[0] = number[i];
number[i] = key;
move +=3; //交换 + 3
Down(number, 0, i,move,compare); // 重新建立堆
}
}
/*
归并排序
*/
void Merge(int *number,int left,int right,int mid,int &move,int &compare) {
int s[SIZE];//一个新数组用来存储排序好的数组
int i = left, j = mid + 1;
int sor = left;
while (i <= mid && j <= right) {
compare++;
if (number[i] < number[j]) {
s[sor++] = number[i++];
move++;
} else {
s[sor++] = number[j++];
move++;
}
}
while (i <= mid) {
s[sor++] = number[i++];
move++;
}
while (j <= right) {
s[sor++] = number[j++];
move++;
}
sor = left;
while (sor <= right) {
number[sor] = s[sor];
move++;
sor++;
}
}
void Merge_sort(int *number,int left,int right,int &move,int &compare,int &sing){
if(left<right){
int mid = (left + right) / 2;
Merge_sort(number,left, mid,move,compare,sing);
Merge_sort(number, mid + 1, right,move,compare,sing);
Merge(number, left, right, mid,move,compare);
}
}
void Radix_sort(int *number,int n,int &move,int &compare,int &sing)
{
int i,j,nLen=n;
if(number == NULL || nLen <= 0)return;
int nBit = 1;
int nMax = number[0];
//找出最大数
for(i = 1;i < nLen;i++)
{
if(nMax < number[i]){
nMax = number[i];
}
}
//计算位数
while(nMax /= 10){
nBit++;
}
int x = 1;
//定义一个指针数组来存数据,并开辟10个Radix空间
Radix **pRadix = (Radix **)malloc(sizeof(Radix *)*10);
Radix *pTemp = NULL;
Radix *pMark = NULL;
int nCount;
Radix *pDel = NULL;
//初始化为空
for(i = 0;i < 10;i++){
pRadix[i] = NULL;
}
for(i = 0;i < nBit;i++)
{
//按位排序
for(j = 0;j < nLen;j++){
pTemp = (Radix*)malloc(sizeof(Radix));
move++;
pTemp->nValue = number[j];
pTemp->pNext = NULL;
if(pRadix[number[j]/n%10] == NULL){
pRadix[number[j]/n%10] = pTemp;
}else{
pMark = pRadix[number[j]/n%10];
while(pMark->pNext != NULL){
pMark = pMark->pNext;
}
pMark->pNext = pTemp;
}
}
nCount = 0;
//将数据重新放回原数组
for(j = 0;j < 10;j++){
while(pRadix[j] != NULL){
number[nCount++] = pRadix[j]->nValue;
pDel = pRadix[j];
pRadix[j] = pRadix[j]->pNext;
free(pDel);
pDel = NULL;
move++;
}
}
x *= 10;
}
}