实验八 内部排序
1.(必做题)在完善“12.11.4 参考源程序”的基础上,进行典型内部排序算法的比较。
(1) 随机产生整数样本,进行8种排序,并比较各种排序算法的执行时间,如执行时间均为0,可考虑增大样本,如加大至5000或10000。
(2) 设计方案,修改“12.11.4 参考源程序”,对8种排序算法的数据元素比较次数和移动次数进行比较。
(3) 修改“12.11.4 参考源程序”,输出8种排序算法每一趟排序的输出结果。
学习一下
第一篇1
第二篇2
抄来的参考代码如下:原链接
堆排序
堆的概念
堆:本质是一种数组对象。特别重要的一点性质:任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆,大顶堆要求节点的元素都要大于其孩子,小顶堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求。
利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。下面,我们通过大顶堆来实现。
基本思想:
堆排序可以按照以下步骤来完成:
1.首先将序列构建称为大顶堆;
(这样满足了大顶堆那条性质:位于根节点的元素一定是当前序列的最大值)
2.构建大顶堆
3.取出当前大顶堆的根节点,将其与序列末尾元素进行交换;
(此时:序列末尾的元素为已排序的最大值;由于交换了元素,当前位于根节点的堆并不一定满足大顶堆的性质)
对交换后的n-1个序列元素进行调整,使其满足大顶堆的性质;
重复2.3步骤,直至堆中只有1个元素为止
代码实现:
#-------------------------堆排序--------------------------------
#**********获取左右叶子节点**********
def LEFT(i):
return 2*i + 1
def RIGHT(i):
return 2*i + 2
#********** 调整大顶堆 **********
#L:待调整序列 length: 序列长度 i:需要调整的结点
def adjust_max_heap(L,length,i):
#定义一个int值保存当前序列最大值的下标
largest = i
#执行循环操作:两个任务:1 寻找最大值的下标;2.最大值与父节点交换
while (1):
#获得序列左右叶子节点的下标
left,right = LEFT(i),RIGHT(i)
#当左叶子节点的下标小于序列长度 并且 左叶子节点的值大于父节点时,将左叶子节点的下标赋值给largest
if (left < length) and (L[left] > L[i]):
largest = left
print('左叶子节点')
else:
largest = i
#当右叶子节点的下标小于序列长度 并且 右叶子节点的值大于父节点时,将右叶子节点的下标值赋值给largest
if (right < length) and (L[right] > L[largest]):
largest = right
print('右叶子节点')
#如果largest不等于i 说明当前的父节点不是最大值,需要交换值
if (largest != i):
temp = L[i]
L[i] = L[largest]
L[largest] = temp
i = largest
print(largest)
continue
else:
break
#********** 建立大顶堆 **********
def build_max_heap(L):
length = len(L)
for x in range((int)((length-1)/2),-1,-1):
adjust_max_heap(L,length,x)
#********** 堆排序 **********
def heap_sort(L):
#先建立大顶堆,保证最大值位于根节点;并且父节点的值大于叶子结点
build_max_heap(L)
#i:当前堆中序列的长度.初始化为序列的长度
i = len(L)
#执行循环:1. 每次取出堆顶元素置于序列的最后(len-1,len-2,len-3...)
2. 调整堆,使其继续满足大顶堆的性质,注意实时修改堆中序列的长度
while (i > 0):
temp = L[i-1]
L[i-1] = L[0]
L[0] = temp
#堆中序列长度减1
i = i-1
#调整大顶堆
adjust_max_heap(L,i,0)
归并排序
算法思想:
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个典型的应用。它的基本操作是:将已有的子序列合并,达到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
归并排序其实要做两件事:
分解----将序列每次折半拆分
合并----将划分后的序列段两两排序合并
因此,归并排序实际上就是两个操作,拆分+合并
如何合并?
L[first…mid]为第一段,L[mid+1…last]为第二段,并且两端已经有序,现在我们要将两端合成达到L[first…last]并且也有序。
首先依次从第一段与第二段中取出元素比较,将较小的元素赋值给temp[]
重复执行上一步,当某一段赋值结束,则将另一段剩下的元素赋值给temp[]
此时将temp[]中的元素复制给L[],则得到的L[first…last]有序
如何分解?
在这里,我们采用递归的方法,首先将待排序列分成A,B两组;然后重复对A、B序列
分组;直到分组后组内只有一个元素,此时我们认为组内所有元素有序,则分组结束。
代码实现
# 归并排序
#这是合并的函数
# 将序列L[first...mid]与序列L[mid+1...last]进行合并
def mergearray(L,first,mid,last,temp):
#对i,j,k分别进行赋值
i,j,k = first,mid+1,0
#当左右两边都有数时进行比较,取较小的数
while (i <= mid) and (j <= last):
if L[i] <= L[j]:
temp[k] = L[i]
i = i+1
k = k+1
else:
temp[k] = L[j]
j = j+1
k = k+1
#如果左边序列还有数
while (i <= mid):
temp[k] = L[i]
i = i+1
k = k+1
#如果右边序列还有数
while (j <= last):
temp[k] = L[j]
j = j+1
k = k+1
#将temp当中该段有序元素赋值给L待排序列使之部分有序
for x in range(0,k):
L[first+x] = temp[x]
# 这是分组的函数
def merge_sort(L,first,last,temp):
if first < last:
mid = (int)((first + last) / 2)
#使左边序列有序
merge_sort(L,first,mid,temp)
#使右边序列有序
merge_sort(L,mid+1,last,temp)
#将两个有序序列合并
mergearray(L,first,mid,last,temp)
# 归并排序的函数
def merge_sort_array(L):
#声明一个长度为len(L)的空列表
temp = len(L)*[None]
#调用归并排序
merge_sort(L,0,len(L)-1,temp)
用了很多功夫抄了别人的代码过来,一定要好好学习,天天向上!!!
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 10002
typedef int Status;
typedef int ElemType;
char s[12][60],f[12][30];
typedef struct {
ElemType *r;
int length;
int cmpcount,excount;
} SqList;
Status printSqList(SqList *L);//遍历输出表
Status ListCreate(SqList *&L) {
int i;
int value;
printf("---<表的创建>---\n");
L->cmpcount=L->excount=0;
do {
printf("请输入表的元素数:");
scanf("%d",&value);
L->r = (ElemType *)malloc((value+1)*sizeof(ElemType));
srand(time(NULL));
if(value>0&&value<MAXSIZE) {
printf("\n");
for(i=1; i<=value; i++,L->length++) {
L->r[i]=rand()%value;
}
} else {
printf("\n");
printf("输入的数量不合法或超出!\n");
printf("请重新输入:");
}
} while(value<0&&value>MAXSIZE);
return OK;
}
void swap(SqList *L,int i,int j) {
int temp=L->r[i];
L->r[i]=L->r[j];
L->r[j]=temp;
}
//简单选择排序
void SelectSort(SqList *L) {
L->cmpcount=L->excount=0;
int i,j,min;
printf("\n");
printf("简单选择排序:\n");
for(i=1; i<L->length; i++) {
min=i;
for(j=i+1; j<=L->length; j++) {
L->cmpcount++;
if(L->r[min]>L->r[j]) {
min=j;
}
}
if(i!=min) {
swap(L,i,min);
L->excount++;
printSqList(L);
}
}
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[6],"简单选择排序\t\t%-10d\t%d\t",L->cmpcount,L->excount);
}
//简单选择排序
//直接插入排序
void InsertSort(SqList *L) {
L->cmpcount=L->excount=0;
int i,j;
printf("\n");
printf("直接插入排序:\n");
for(i=2; i<=L->length; i++) {
L->cmpcount++;
if(L->r[i]<L->r[i-1]) {
L->r[0]=L->r[i];
for(j=i-1; L->r[j]>L->r[0]; j--) {
L->cmpcount++;
L->r[j+1]=L->r[j];
}
L->r[j+1]=L->r[0];
L->excount++;
printSqList(L);
}
}
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[1],"直接插入排序\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//直接插入排序
//冒泡排序改进算法
void BubbleSort(SqList *L) {
L->cmpcount=L->excount=0;
int i,j;
ElemType Flag=TRUE;
printf("\n");
printf("冒泡算法排序:\n");
for(i=1; i<L->length&&Flag; i++) {
Flag=FALSE;
for(j=L->length-1; j>=i; j--) {
L->cmpcount++;
if(L->r[j]>L->r[j+1]) {
swap(L,j,j+1);
L->excount++;
printSqList(L);
Flag=TRUE;
}
}
}
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[4],"冒泡排序算法\t\t%-10d\t%d\t",L->cmpcount,L->excount);
}
//冒泡排序改进算法
//希尔排序
void ShellSort(SqList *L) {
L->cmpcount=L->excount=0;
int i,j;
printf("\n");
printf("希尔算法排序:\n");
int increment=L->length;
do {
increment=(int)increment/2;
for(i=increment+1; i<=L->length; i++) {
L->cmpcount++;
if(L->r[i]<L->r[i-increment]) {
L->r[0]=L->r[i];
for(j=i-increment; j>0&&L->r[0]<L->r[j]; j-=increment) {
L->r[j+increment]=L->r[j];
}
L->r[j+increment]=L->r[0];
L->excount++;
printSqList(L);
}
}
} while(increment>1);
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[3],"希尔排序算法\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//希尔排序
//折半插入排序
void BInsertSort(SqList *L) {
L->cmpcount=L->excount=0;
int low,high,m;
printf("\n");
printf("折半插入排序:\n");
for(int i=2; i<=L->length; i++) {
L->r[0]=L->r[i];
low=1;
high=i-1;
while(low<=high) {
m=(low+high)/2;
L->cmpcount++;
if(L->r[0]<L->r[m]) {
high=m-1;
} else {
low=m+1;
}
}
for(int j=i-1; j>=high+1; --j) {
L->r[j+1]=L->r[j];
}
L->r[high+1]=L->r[0];
L->excount++;
printSqList(L);
}
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[2],"折半排序算法\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//折半插入排序
//快速排序算法
int partition(SqList *L, int low, int high) {
int key = L->r[low];
while( low < high ) {
while(low < high && L->r[high] >= key) {
L->cmpcount++;
high--;
}
L->r[low] = L->r[high];
while(low < high && L->r[low] <= key) {
L->cmpcount++;
low++;
}
L->r[high] = L->r[low];
}
L->r[low] = key;
return low;
}
void quicksort(SqList *L, int low, int high) {
if(low >= high) return;
int keypos = partition(L, low, high);
L->excount++;
printSqList(L);
quicksort(L, low, keypos-1);
quicksort(L, keypos+1, high);
}
void QuickSort(SqList *L) {
L->cmpcount=L->excount=0;
printf("\n");
printf("快速排序算法:\n");
quicksort(L,1,L->length);
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[5],"快速排序算法\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//快速排序算法
//堆排序
void HeapAdjust(SqList *L,int s,int m) {
int temp,j;
temp=L->r[s];
for(j=2*s; j<=m; j*=2) {
L->cmpcount++;
if(j<m&&L->r[j]<L->r[j+1]) {
++j;
}
L->cmpcount++;
if(temp>=L->r[j]) {
break;
}
L->r[s]=L->r[j];
s=j;
}
L->r[s]=temp;
}
void HeapSort(SqList *L) {
L->cmpcount=L->excount=0;
int i;
printf("\n");
printf("堆排序:\n");
for(i=L->length/2; i>0; i--) {
HeapAdjust(L,i,L->length);
}
for(i=L->length; i>1; i--) {
swap(L,1,i);
L->excount++;
printSqList(L);
HeapAdjust(L,1,i-1);
}
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[7],"堆排序算法\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//堆排序
//归并排序算法
void Merge(int SR[],int TR[],int i,int m,int n,SqList *L) {
int j,k,l;
for(j=m+1,k=i; i<=m&&j<=n; k++) {
L->cmpcount++;
if(SR[i]<SR[j]) {
TR[k]=SR[i++];
} else {
TR[k]=SR[j++];
}
}
L->cmpcount++;
if(i<=m) {
for(l=0; l<=m-i; l++) {
TR[k+l]=SR[i+l];
}
}
L->cmpcount++;
if(j<=n) {
for(l=0; l<=n-j; l++) {
TR[k+l]=SR[j+l];
}
}
L->excount++;
printSqList(L);
}
void MSort(int SR[],int TR1[],int first,int last,SqList *L) {
int mid;
int TR2[MAXSIZE+1];
L->cmpcount++;
if(first==last) {
TR1[first]=SR[first];
} else {
mid=(last+first)/2;
MSort(SR,TR2,first,mid,L);
MSort(SR,TR2,mid+1,last,L);
Merge(TR2,TR1,first,mid,last,L);
}
}
void MergeSort(SqList *L) {
L->cmpcount=L->excount=0;
printf("\n");
printf("归并算法排序(递归):\n");
MSort(L->r,L->r,1,L->length,L);
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[1],"归并排序算法算法\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//归并排序算法
//非递归归并算法
void MergePass(int SR[],int TR[],int s,int n,SqList *L) {
int i=1;
int j;
while(i<=n-2*s+1) {
L->cmpcount++;
Merge(SR,TR,i,i+s-1,i+2*s-1,L);
i=i+2*s;
}
L->cmpcount++;
if(i<n-s+1) {
Merge(SR,TR,i,i+s-1,n,L);
} else {
for(j=i; j<=n; j++) {
TR[j]=SR[j];
}
L->excount++;
printSqList(L);
}
}
void MergeSort2(SqList *L) {
L->cmpcount=L->excount=0;
int *TEMP=(int *)malloc(L->length*sizeof(int));
int k=1;
printf("\n");
printf("归并算法排序(非递归):\n");
while(k<L->length) {
MergePass(L->r,TEMP,k,L->length,L);
k=2*k;
MergePass(TEMP,L->r,k,L->length,L);
k=2*k;
}
printf("比较次数是:%d\t交换次数是:%d\n",L->cmpcount,L->excount);
sprintf(s[8],"归并排序算法\t\t%d\t\t%d\t",L->cmpcount,L->excount);
}
//非递归归并算法
Status printSqList(SqList *L) {
int i,flag;
if(L->excount==0||flag==L->excount) {
return ERROR;
} else {
// return 0;
printf("第%d次交换后",L->excount);
}
printf("遍历表结果:\n\t");
for(i=1; i<=L->length; i++) {
printf("%d\t",L->r[i]);
}
printf("\n");
return OK;
}
Status DataSave(SqList *L,int *a) {
int i;
for(i=1; i<=L->length; i++) {
a[i]=L->r[i];
}
return OK;
}
Status SqListMenu() {
// printf("\n");
// printf(" _______>>>排序算法<<<______\n");
// printf("| |\n");
// printf("| 1.直接插入排序 |\n");
// printf("| 2.折半插入排序 |\n");
// printf("| 3.希尔算法排序 |\n");
// printf("| 4.冒泡算法排序 |\n");
// printf("| 5.快速算法排序 |\n");
// printf("| 6.简单选择排序 |\n");
// printf("| 7.堆排序 |\n");
// printf("| 8.归并算法排序 |\n");
// printf("| 0.退出 |\n");
// printf("|___________________________|\n");
int value;
printf("请选择你要执行的排序操作:");
do {
scanf("%d",&value);
if(value>0&&value<12) {
return value;
} else {
printf("你输入的操作有误,请重新输入:");
}
} while(value>0&&value<12);
}
int main() {
SqList *L;
int i;
int value;
int array[MAXSIZE];
srand(GetTickCount());
ListCreate(L);
DataSave(L,array);
do {
printf("\n");
for(i=1; i<=L->length; i++) {
L->r[i]=array[i];
}
value=SqListMenu();
if(value==1) {
clock_t start = clock();
printSqList(L);
InsertSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 1.直接插入排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==2) {
clock_t start = clock();
// printSqList(L);
BInsertSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 2.折半插入排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==3) {
clock_t start = clock();
// printSqList(L);
ShellSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 3.希尔算法排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==4) {
clock_t start = clock();
// printSqList(L);
BubbleSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 4.冒泡算法排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==5) {
clock_t start = clock();
// printSqList(L);
QuickSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 5.快速算法排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==6) {
clock_t start = clock();
// printSqList(L);
SelectSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 6.简单选择排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==7) {
clock_t start = clock();
// printSqList(L);
HeapSort(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 7.堆排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==8) {
clock_t start = clock();
// printSqList(L);
MergeSort2(L);
printSqList(L);
double end = (double)(clock() - start);
printf("| 8.归并算法排序 |\n");
printf("用时%.0fms\n",(double)end);
sprintf(f[value],"\t%.0fms\n",(double)end);
} else if(value==9) {
printf("样本数为%d\n八大排序算法的结果:\t总的比较次数\t交换次数\t时间\n",L->length);
for(i=1; i<=8; i++) {
printf("%s%s\n",s[i],f[i]);
}
// printf("退出!\n");
} else {
printf("\n");
printf("错误输入!重新输入!\n");
}
} while(value!=0);
return 0;
}
/*测试样例1
50
1
2
3
4
5
6
7
8
9
*/