问题:
/*
* Copyright (c)2016,烟台大学计算机与控制工程学院
* All rights reserved.
* 文件名称:项目1-3.cbp
* 作 者:秦绪龙
* 完成日期:2016年12月15日
* 版 本 号:v1.0
* 问题描述:验证冒泡排序
* 输入描述:无
* 程序输出:测试数据
*/
1.直接插入排序
#include <stdio.h>
#define MaxSize 20
typedef int KeyType; //定义关键字类型
typedef char InfoType[10];
typedef struct //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据项,类型为InfoType
} RecType; //排序的记录类型定义
void InsertSort(RecType R[],int n) //对R[0..n-1]按递增有序进行直接插入排序
{
int i,j;
RecType tmp;
for (i=1; i<n; i++)
{
tmp=R[i];
j=i-1; //从右向左在有序区R[0..i-1]中找R[i]的插入位置
while (j>=0 && tmp.key<R[j].key)
{
R[j+1]=R[j]; //将关键字大于R[i].key的记录后移
j--;
}
R[j+1]=tmp; //在j+1处插入R[i]
}
}
int main()
{
int i,n=10;
RecType R[MaxSize];
KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7};
for (i=0; i<n; i++)
R[i].key=a[i];
printf("排序前:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
InsertSort(R,n);
printf("排序后:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
return 0;
}
运行结果:
2..折半插入排序
代码:
#include <stdio.h>
#define MaxSize 20
typedef int KeyType; //定义关键字类型
typedef char InfoType[10];
typedef struct //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据项,类型为InfoType
} RecType; //排序的记录类型定义
void InsertSort1(RecType R[],int n) //对R[0..n-1]按递增有序进行直接插入排序
{
int i,j,low,high,mid;
RecType tmp;
for (i=1; i<n; i++)
{
tmp=R[i];
low=0;
high=i-1;
while (low<=high)
{
mid=(low+high)/2;
if (tmp.key<R[mid].key)
high=mid-1;
else
low=mid+1;
}
for (j=i-1; j>=high+1; j--)
R[j+1]=R[j];
R[high+1]=tmp;
}
}
int main()
{
int i,n=10;
RecType R[MaxSize];
KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7};
for (i=0; i<n; i++)
R[i].key=a[i];
printf("排序前:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
InsertSort1(R,n);
printf("排序后:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
return 0;
}
运行结果:
3.希尔排序
代码:
#include <stdio.h>
#define MaxSize 20
typedef int KeyType; //定义关键字类型
typedef char InfoType[10];
typedef struct //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据项,类型为InfoType
} RecType; //排序的记录类型定义
void ShellSort(RecType R[],int n) //希尔排序算法
{
int i,j,gap;
RecType tmp;
gap=n/2; //增量置初值
while (gap>0)
{
for (i=gap; i<n; i++) //对所有相隔gap位置的所有元素组进行排序
{
tmp=R[i];
j=i-gap;
while (j>=0 && tmp.key<R[j].key)//对相隔gap位置的元素组进行排序
{
R[j+gap]=R[j];
j=j-gap;
}
R[j+gap]=tmp;
j=j-gap;
}
gap=gap/2; //减小增量
}
}
int main()
{
int i,n=11;
RecType R[MaxSize];
KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7};
for (i=0; i<n; i++)
R[i].key=a[i];
printf("排序前:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
ShellSort(R,n);
printf("排序后:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
return 0;
}
运行结果:
4.冒泡排序
代码:
#include <stdio.h>
#define MaxSize 20
typedef int KeyType; //定义关键字类型
typedef char InfoType[10];
typedef struct //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据项,类型为InfoType
} RecType; //排序的记录类型定义
void BubbleSort1(RecType R[],int n)
{
int i,j,k,exchange;
RecType tmp;
for (i=0; i<n-1; i++)
{
exchange=0;
for (j=n-1; j>i; j--) //比较,找出最小关键字的记录
if (R[j].key<R[j-1].key)
{
tmp=R[j]; //R[j]与R[j-1]进行交换,将最小关键字记录前移
R[j]=R[j-1];
R[j-1]=tmp;
exchange=1;
}
printf("i=%d: ",i);
for (k=0; k<n; k++)
printf("%d ",R[k].key);
printf("\n");
if (exchange==0) //中途结束算法
return;
}
}
int main()
{
int i,n=10;
RecType R[MaxSize];
KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7};
for (i=0; i<n; i++)
R[i].key=a[i];
printf("排序前:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
BubbleSort1(R,n);
printf("排序后:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
return 0;
}
运行结果:
5.快速排序
代码:
以第一个元素为基准
#include <stdio.h>
#define MaxSize 20
typedef int KeyType; //定义关键字类型
typedef char InfoType[10];
typedef struct //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据项,类型为InfoType
} RecType; //排序的记录类型定义
void QuickSort(RecType R[],int s,int t) //对R[s]至R[t]的元素进行快速排序
{
int i=s,j=t;
RecType tmp;
if (s<t) //区间内至少存在两个元素的情况
{
tmp=R[s]; //用区间的第1个记录作为基准
while (i!=j) //从区间两端交替向中间扫描,直至i=j为止
{
while (j>i && R[j].key>=tmp.key)
j--; //从右向左扫描,找第1个小于tmp.key的R[j]
R[i]=R[j]; //找到这样的R[j],R[i]"R[j]交换
while (i<j && R[i].key<=tmp.key)
i++; //从左向右扫描,找第1个大于tmp.key的记录R[i]
R[j]=R[i]; //找到这样的R[i],R[i]"R[j]交换
}
R[i]=tmp;
QuickSort(R,s,i-1); //对左区间递归排序
QuickSort(R,i+1,t); //对右区间递归排序
}
}
int main()
{
int i,n=10;
RecType R[MaxSize];
KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7};
for (i=0; i<n; i++)
R[i].key=a[i];
printf("排序前:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
QuickSort(R,0,n-1);
printf("排序后:");
for (i=0; i<n; i++)
printf("%d ",R[i].key);
printf("\n");
return 0;
}
运行结果:
2.以中间位置的元素作为基准
代码:
#include <stdio.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType; //排序的记录类型定义 void QuickSort1(RecType R[],int s,int t) //对R[s]至R[t]的元素进行快速排序 { int i=s,j=t; KeyType pivot; RecType tmp; pivot = R[(s+t)/2].key; //用区间的中间位置的元素作为关键字 if (s<t) //区间内至少存在两个元素的情况 { while (i!=j) //从区间两端交替向中间扫描,直至i=j为止 { while (j>i && R[j].key>pivot) j--; //从右向左扫描,找第1个小于基准的R[j] while (i<j && R[i].key<pivot) i++; //从左向右扫描,找第1个大于基准记录R[i] if(i<j) //将前后的两个失序元素进行交换 { tmp=R[i]; R[i]=R[j]; R[j]=tmp; } } QuickSort1(R,s,i-1); //对左区间递归排序 QuickSort1(R,j+1,t); //对右区间递归排序 } } int main() { int i,n=10; RecType R[MaxSize]; KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7}; for (i=0; i<n; i++) R[i].key=a[i]; printf("排序前:"); for (i=0; i<n; i++) printf("%d ",R[i].key); printf("\n"); QuickSort1(R,0,n-1); printf("排序后:"); for (i=0; i<n; i++) printf("%d ",R[i].key); printf("\n"); return 0; }
运行结果:
6.堆排序
代码:
#include <stdio.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType; //排序的记录类型定义 //调整堆 void sift(RecType R[],int low,int high) { int i=low,j=2*i; //R[j]是R[i]的左孩子 RecType temp=R[i]; while (j<=high) { if (j<high && R[j].key<R[j+1].key) //若右孩子较大,把j指向右孩子 j++; //变为2i+1 if (temp.key<R[j].key) { R[i]=R[j]; //将R[j]调整到双亲结点位置上 i=j; //修改i和j值,以便继续向下筛选 j=2*i; } else break; //筛选结束 } R[i]=temp; //被筛选结点的值放入最终位置 } //堆排序 void HeapSort(RecType R[],int n) { int i; RecType temp; for (i=n/2; i>=1; i--) //循环建立初始堆 sift(R,i,n); for (i=n; i>=2; i--) //进行n-1次循环,完成推排序 { temp=R[1]; //将第一个元素同当前区间内R[1]对换 R[1]=R[i]; R[i]=temp; sift(R,1,i-1); //筛选R[1]结点,得到i-1个结点的堆 } } int main() { int i,n=10; RecType R[MaxSize]; KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7};//a[0]空闲,不作为关键字 for (i=1; i<=n; i++) R[i].key=a[i]; printf("排序前:"); for (i=1; i<=n; i++) printf("%d ",R[i].key); printf("\n"); HeapSort(R,n); printf("排序后:"); for (i=1; i<=n; i++) printf("%d ",R[i].key); printf("\n"); return 0; }
运行结果:
7.归并排序
代码:
#include <stdio.h> #include <malloc.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType; //排序的记录类型定义 void Merge(RecType R[],int low,int mid,int high) { RecType *R1; int i=low,j=mid+1,k=0; //k是R1的下标,i、j分别为第1、2段的下标 R1=(RecType *)malloc((high-low+1)*sizeof(RecType)); //动态分配空间 while (i<=mid && j<=high) //在第1段和第2段均未扫描完时循环 if (R[i].key<=R[j].key) //将第1段中的记录放入R1中 { R1[k]=R[i]; i++; k++; } else //将第2段中的记录放入R1中 { R1[k]=R[j]; j++; k++; } while (i<=mid) //将第1段余下部分复制到R1 { R1[k]=R[i]; i++; k++; } while (j<=high) //将第2段余下部分复制到R1 { R1[k]=R[j]; j++; k++; } for (k=0,i=low; i<=high; k++,i++) //将R1复制回R中 R[i]=R1[k]; } void MergePass(RecType R[],int length,int n) //对整个数序进行一趟归并 { int i; for (i=0; i+2*length-1<n; i=i+2*length) //归并length长的两相邻子表 Merge(R,i,i+length-1,i+2*length-1); if (i+length-1<n) //余下两个子表,后者长度小于length Merge(R,i,i+length-1,n-1); //归并这两个子表 } void MergeSort(RecType R[],int n) //自底向上的二路归并算法 { int length; for (length=1; length<n; length=2*length) //进行log2n趟归并 MergePass(R,length,n); } int main() { int i,n=10; RecType R[MaxSize]; KeyType a[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7}; for (i=0; i<n; i++) R[i].key=a[i]; printf("排序前:"); for (i=0; i<n; i++) printf("%d ",R[i].key); printf("\n"); MergeSort(R,n); printf("排序后:"); for (i=0; i<n; i++) printf("%d ",R[i].key); printf("\n"); return 0; }
运行结果:
8.基数排序
代码:
#include <stdio.h> #include <malloc.h> #include <string.h> #define MAXE 20 //线性表中最多元素个数 #define MAXR 10 //基数的最大取值 #define MAXD 8 //关键字位数的最大取值 typedef struct node { char data[MAXD]; //记录的关键字定义的字符串 struct node *next; } RecType; void CreaLink(RecType *&p,char *a[],int n); void DispLink(RecType *p); void RadixSort(RecType *&p,int r,int d) //实现基数排序:*p为待排序序列链表指针,r为基数,d为关键字位数 { RecType *head[MAXR],*tail[MAXR],*t; //定义各链队的首尾指针 int i,j,k; for (i=0; i<=d-1; i++) //从低位到高位循环 { for (j=0; j<r; j++) //初始化各链队首、尾指针 head[j]=tail[j]=NULL; while (p!=NULL) //对于原链表中每个结点循环 { k=p->data[i]-'0'; //找第k个链队 if (head[k]==NULL) //进行分配 { head[k]=p; tail[k]=p; } else { tail[k]->next=p; tail[k]=p; } p=p->next; //取下一个待排序的元素 } p=NULL; //重新用p来收集所有结点 for (j=0; j<r; j++) //对于每一个链队循环 if (head[j]!=NULL) //进行收集 { if (p==NULL) { p=head[j]; t=tail[j]; } else { t->next=head[j]; t=tail[j]; } } t->next=NULL; //最后一个结点的next域置NULL //以下的显示并非必要 printf(" 按%d位排序\t",i); DispLink(p); } } void CreateLink(RecType *&p,char a[MAXE][MAXD],int n) //采用后插法产生链表 { int i; RecType *s,*t; for (i=0; i<n; i++) { s=(RecType *)malloc(sizeof(RecType)); strcpy(s->data,a[i]); if (i==0) { p=s; t=s; } else { t->next=s; t=s; } } t->next=NULL; } void DispLink(RecType *p) //输出链表 { while (p!=NULL) { printf("%c%c ",p->data[1],p->data[0]); p=p->next; } printf("\n"); } int main() { int n=10,r=10,d=2; int i,j,k; RecType *p; char a[MAXE][MAXD]; int b[]= {57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7}; for (i=0; i<n; i++) //将b[i]转换成字符串 { k=b[i]; for (j=0; j<d; j++) //例如b[0]=75,转换后a[0][0]='7',a[0][1]='5' { a[i][j]=k%10+'0'; k=k/10; } a[i][j]='\0'; } CreateLink(p,a,n); printf("\n"); printf(" 初始关键字\t"); //输出初始关键字序列 DispLink(p); RadixSort(p,10,2); printf(" 最终结果\t"); //输出最终结果 DispLink(p); printf("\n"); return 0; }
运行结果: