实验六 排序实现
实验内容:
1、 编程实现几种典型的排序算法,如插入排序,选择排序、交换排序、归并排序。
2、 冒泡排序、快速排序的实现与比较。
/* 源程序的头文件 sort.h */
产生随机数的算法:
voidgetrandat(Data ary[],int count) /* 产生一批随机数,准备排序 */
{ int a;
int i;
srand(time(NULL));
for(i=0;i<count;i++){ a=rand()%100+1;
ary[i].key=a;
}
} /*getrandat */
voidprdata(Data ary[],int count) /* 输出数据的函数 */
{ inti; char ch;
printf(“\n”);
for(i=0;i<count;i++)printf(“%6d”,ary[i].key);
printf(“\n”);
printf(“\n\n 打回车键,结束显示。“); ch=getch();
} /*prdata */
[两种排序方法的比较源程序]
/* sortcmp.c */
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /* 数组最大界限 */
typedef int ElemType; /* 关键字的类型 */
typedef struct
{ ElemType key;
int shu; /* 其它属性域 */
}Data; /* 一个纪录的结构体类型 */
Data ar[MAX],br[MAX];
Typedefstruct
{ int lo,hi;
}Selem; /* 栈的元素结构体类型*/
typedefstruct
{ Selem elem[MAX]; /* 一维数组子域 */
int top; /* 栈顶指针子域 */
}SqStack; /* 栈的顺序结构体类型*/
Stack s1;
/* 函数声明 */
void bubble(Data ary[],int n)
void qksort(Data ary[],int n)
void hoare(Data ary[],int l,int h)
void init_s(SqStack *s);
void push(SqStack *s,Selem e) /* 进栈一个元素 */
Selem pop(SqStack *s)
int empty(SqStack s)
/* 主函数 */
main()
{ int k,n,j; j; char ch;
do { printf("\n\n\n");
printf("\n\n 1. 产生一批随机数准备排序 ");
printf("\n\n 2. 一般情况的起泡排序");
printf("\n\n 3. 有序情况的起泡排序");
printf("\n\n 4. 一般情况的快速排序");
printf("\n\n 5. 有序情况的快速排序");
printf("\n\n 6. 结束程序运行");
printf("\n======================================");
printf("\n 请输入您的选择 (1,2,3,4,5,6)");
scanf("%d",&k);
switch(k)
{ case 1:{ printf(“the number of datas:”); /* 输入数据个数 */
scanf(“%d”,&n);
getrandat(ar,n); /*产生n个随机数 */
for(j=0;j<n;j++)br[j]=ar[j]; /* 保留复原始数据 */
prdata(ar,n);
} break;
case 2:{ for(j=0;j<n;j++) ar[j]=br[j]; /* 恢复原始数据 */
bubble(ar,n); /* 对n个数据起泡排序 */
prdata(ar,n); /* 排序后输出 */
} break;
case 3: { bubble( ar,n); /* 有序情况的起泡排序 */
prdata(ar,n);
} break;
case 4:{ for(j=0;j<n;j++) ar[j]=br[j]; /* 恢复原始数据 */
qksort(ar,n); /* 对n个数据快速排序 */
prdata(ar,n); /* 排序后输出 */
} break;
case 5:{ qksort(ar,n); /* 有序情况的快速排序 */
prdata(ar,n);
} break;
case 6: exit(0);
} /* switch */
printf("\n ----------------");
}while(k>=1 && k<6);
printf("\n 再见!")
printf(“\n 打回车键,返回。“);ch=getch();
} /* main */
/* 起泡排序 */
void bubble(Data ary[],int n)
{ int i,j,tag; Dtata x;
i=0;
do{ tag=0;
for(j=0;j<n-1;j--)
if (ary[j].key>ary[j+1].key)
{ x=ary[j]; ary[j]=ary[j+1];
ary[j+1]=x; tag=1;
}
i++;
}while( i<n-1 &&tag==1);
} /* bubble */
/* 快速排序非递归算法 */
void qksort(Data ary[],int n)
{ int low,high,i,tag; Selem x,y;
init_s( &s1); /* 初始化一个空栈 */
low=0; high=n-1; tag=1;
do{ while(low<high)
{i=hoare(ary,low,high); /* 调用一趟快速排序 */
x.lo= i+1; x.hi=high;
push(&s1,x);
high=i-1;
}
if(empty()==0) tag=0;
else { y=pop(s1);
low==y.lo; high=y.hi;
}
}while(tag==1);
} /*qksort */
/* 一趟快速排序 */
voidhoare(int ary[],int l,int h)
{ int i,j; Data x;
i=l; j=h; x=ary[l];
do{ while((i<j)&& ary[j]>=x)j--;
if (i<j) { ary[i]=ary[j]; i++;}
while((i<j)&&ary[i]<=x)i++;
if(i<j) { ary[j]=ary[i]; j--;}
}while(i<j);
ary[i]=x; /* 枢轴记录定位 */
return(i); /* 返回左、右区分界处 */
} /* hoar */
/* 关于栈的操作 */
void init_s(SqStack *s) /* 初始化一个空栈 */
{s->top=0;
} /* init_s */;
/* 进栈一个元素 */
void push(SqStack *s,Selem e)
{ if(s->top==MAX-1)printf(“\nstack Overflow!\n”);
else { s->top++;
s->elem[s->top]=e;
}
}/* push */
/* 出栈一个元素 */
Selem pop(SqStack *s) init_s(&s1);
{ Selem e;
if(s->top==0){ printf(“\n satck Empty!\n”);
e.lo=-1; e.hi=-1;
}
else { e=s->elem[s->top];
s->top--;
}
return(e);
}/* pop */
本程序中,qksort用非递归实现快速排序,在这个函数里,调用了hoare函数,函数,hoare对ary[l…h]进行一趟快速排序,执行该函数后,将ary[]从下标i处分成左右两个分区,其中左分区中的数据均小于等于ary[i].key,而右分区中的数据均大于等于ary[i].key(l≤i≤h)。将右区尾指针(记录下标)保存入栈,对左区再调用hoare进行快速排序。另外,此处用到的栈与以前的栈结构稍有不同,(因为栈中同时要放进两个值),故操作也稍有不同。例:入栈时,要两个参数即右区首、尾指针组成的结构体变量入栈。
快速排序的最坏情况亦即各元素已有序时,再进行快速排序,这种情况下其实并不快,这种情况下的冒泡排序反而很快。可见算法的优劣并不是绝对的。快速排序适合于记录关键字无序的情况。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef int KeyType;
typedef char OtherType ;
typedef struct
{
KeyType key;
OtherType other_data;
}RecordType;
void getrandat(RecordTypeary[],int count) /* 产生一批随机数,准备排序 */
{
int a;
int i;
srand(time(NULL));
for(i=0;i<count;i++)
{ a=rand()%100+1;
ary[i].key=a;
}
}
int QKPass(RecordType r[],int low,int high)
{
RecordType x;
x=r[low];
while(low<high)
{
while(low<high&&r[high].key)
high--;
if(low<high)
{r[low]=r[high];low++;}
while(low<high&&r[low].key<x.key)
low++;
if(low<high)
{r[high]=r[low];high--;}
}
r[low]=x;
return low;
}
void prdata(RecordType ary[],int count) /* 输出数据的函数 */
{ int i;
printf("\n");
for(i=0;i<count;i++) printf("%6d",ary[i].key);
printf("\n");
printf("\n\n 打回车键,结束显示。");
}
void QKSort(RecordType r[],int low,int high)
{
if(low<high)
{
int pos;
pos=QKPass( r, low, high);
QKSort( r, low,pos-1);
QKSort( r, pos+1,high);
}
}
void main()
{
RecordType ar[31],br[31];
int j,n;
printf("the number of datas:"); /* 输入数据个数 */
scanf("%d",&n);
getrandat(ar,n); /*产生n个随机数 */
for(j=0;j<n;j++)br[j]=ar[j];
prdata(ar,n);
QKSort(ar ,1,n ); /*对n个数据快速排序 */
prdata(ar,n);
}
2、统计成绩
[问题描述]给出n个学生的考试成绩表,每条信息由姓名和分数组成,试设计一个算法:
(1)按分数高低次序,打印出每个学生在考试中获得的名次,分数相同的为同一名次;
(2)按名次列出每个学生的姓名与分数。
[基本要求]学生的考试成绩表必须通过键盘输入数据而建立,同时要对输出进行格式控制。
[算法实现]下面给出的是用直接选择排序算法实现的C语言程序。
//给出n个学生的考试成绩表,每条信息由姓名和分数组成,试设计一个算法:
//1、按分数高低次序,打印出每个学生在考试中获得的名次,分数相同的为同一名次;
//2、按名次列出每个学生的姓名与分数。
#define n 10 //假设本班共10名同学
#include"stdio.h"
typedef struct student
{ charname[8];
int score;
}STUDENT;
STUDENT stu[n],temp;
void main( )
{ int num, i, j, max;
printf("\n请输入学生成绩: \n");
for (i=0; i<n; i++)
{ printf("姓名:");
scanf ("%s", &stu[i].name);
scanf ("%4d", &stu[i].score);
}
num=1;
for(i=0; i<n; i++)
{ max=i;
for(j=i+1; j<n; j++)
if(stu[j].score>stu[max].score)
max=j;
if (max!=i)
{ temp =stu[max];
stu[max]=stu[i];
stu[i]= temp;
}
if((i>0)&&(stu[i].score<stu[i-1].score))
num=num+1;
printf("%4d%s%4d", num,stu[i].name, stu[i].score);
}
}