#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define COUNT 100
void InsertSort(int *arr);
void BInsertSort(int * arr);
void ShellInsert(int * arr ,int dk);
void ShellSort(int *arr);
void BubbleSort(int * arr);
void QuickSort(int * arr,int low ,int high);
int FindPos(int *arr,int low ,int high);
void SelectSort(int * arr);
void HeadSort(int *arr);
void HeapAdjust(int *arr,int s,int m);
void CreatHeap(int *arr);
void MSort(int *R ,int * T ,int low, int high);
void Merge(int *R,int *T,int low,int mid ,int high);
int main(){
int arr[COUNT];
int buff[COUNT];
srand(time(NULL));
for(int i =0;i<COUNT;i++){
arr[i] = rand();
}
int 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");
while(scanf("%d",&n)!=EOF){
switch(n){
case 1: InsertSort(arr);break;
case 2: BInsertSort(arr);break;
case 3: ShellSort(arr);break;
case 4: BubbleSort(arr);break;
case 5: QuickSort(arr,0,COUNT-1);break;
case 6: SelectSort(arr);break;
case 7: HeadSort(arr);break;
case 8: MSort(arr,buff,0,COUNT-1);break;
default: printf("输入错误,请重新输入:\n");
}
for(int i =0 ;i<COUNT;i++){
printf("%d\n",arr[i]);
}
for(int i =0;i<COUNT;i++){
arr[i] = rand();
}
}
return 0;
}
//插入排序 之 直接插入排序
/*
* 时间复杂度;O(n^2)
* 空间复杂度:O(1)
* 算法特点:
* 1.稳定排序
* 2.算法简便,且容易实现
* 3.也适用于链式存储结构,知识在单链表上无需移动记录,只需要修改相应的指针
* 4.更适用于初始记录基本有序的情况,当初是记录无序,n较大时,此算法时间复杂度较高,不宜采用。
*/
void InsertSort(int *arr){
for(int i = 1,val=0,j;i<COUNT;i++){
if(i<COUNT&&arr[i]<arr[i-1]){
val = arr[i];
arr[i]=arr[i-1];
for( j =i-2;j>=0&&arr[j]>val;j--){
arr[j+1]=arr[j];
}
arr[j+1] = val;
}
}
}
//插入排序之 折半插入排序
/*
* 时间复杂度;O(n^2)
* 空间复杂度:O(1)
* 算法特点:
* 1.稳定排序
* 2.因为要进行折半查找,所以只能用于顺序结构,不能用于链式结构
* 3.适合初始记录无序,n较大时的情况。
*/
void BInsertSort(int * arr){
for(int i =1 ; i < COUNT;i++){
if(arr[i]<arr[i-1]){
int val = arr[i];
int low = 0;
int high = i-1;
while(low<=high){
int mid = (low+high)/2;
if(arr[mid]<val){
low = mid+1;
}else{
high = mid-1;
}
}
for(int j = i-1;j>=high+1;j--){
arr[j+1]=arr[j];
}
arr[high+1] = val;
}
}
}
//插入排序之 希尔排序
/*
* 时间复杂度;O(n^(3/2))
* 空间复杂度:O(1)
* 算法特点:
* 1.记录跳跃式的移动导致排序方法是不稳定的
* 2.只能用于顺序结构,不能用于链式结构
* 3.增量序列可以使用各种取法,当应该使增量序列中的值没有除1之外的公因子,并且最后的一个增量必须等于1
* 4.记录总的比较次数和移动次数都比直接插入排序要少,n越大时,效果越明显,所以适合记录无序,n较大时的情况
*
*/
void ShellInsert(int * arr ,int dk){
for(int i =dk,j ;i<COUNT;i++){
if(arr[i]<arr[i-dk]){
int val = arr[i];
for( j = i-dk;j>=0&&arr[j]>val;j-=dk){
arr[j+dk]=arr[j];
}
arr[j+dk] = val;
}
}
}
void ShellSort(int * arr){
int dt[10] = {1000,300,200,99,70,44,19,9,4,1};
for(int i =0 ;i<10;i++){
ShellInsert(arr,dt[i]);
}
}
// 交换排序 之 冒泡排序
/*
* 时间复杂度;O(n^2)
* 空间复杂度:O(1)
* 算法特点:
* 1.稳定排序
* 2.可适用链式存储结构。
* 3.移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时,此算法不宜采用。
*/
void BubbleSort(int * arr){
int flag = 1;
for(int i = 1 ;i< COUNT&&flag == 1;i++){
flag = 0;
for(int j =0 ;j< COUNT - i;j++){
if(arr[j]>arr[j+1]){
flag = 1;
arr[j] = arr[j]^arr[j+1];
arr[j+1] = arr[j]^arr[j+1];
arr[j] = arr[j]^arr[j+1];
}
}
}
}
// 交换排序之 快速排序
/*
* 时间复杂度;O(nlog2(n)).
* 空间复杂度;最好的情况是:O(log2(n)),最坏的情况是:O(n).
* 算法特点:
* 1.记录非顺次的移动导致排序方法是不稳定的。
* 2.排序过程中需要定位表的上界和下届,所以适合用于顺序结构,很难用于链式储存结构
* 3.当n较大时,在平均情况下快速排序是在所有内部排序方法中速度最快的一种,所以其适合初始记录无序,n较大时的情况。
*/
int FindPos(int * arr ,int low ,int high){
int val = arr[low];
while(low<high){
while(low<high&&arr[high]>=val){
high--;
}
arr[low] = arr[high];
while(low<high&&arr[low]<=val){
low++;
}
arr[high] = arr[low];
}
arr[low] = val;
return low;
}
void QuickSort(int * arr,int low ,int high){
if(low<high){
int pos = FindPos(arr,low,high);
QuickSort(arr,low,pos-1);
QuickSort(arr,pos+1,high);
}
}
// 选择排序之 简单选择排序
/*
* 时间复杂度;O(n^2)
* 空间复杂度:O(1)
* 算法特点:
* 1.稳定排序
* 2.可用于链式储存结构
* 3.移动记录次数较少。此方法比直接插入排序快。
*/
void SelectSort(int * arr){
for(int i =0;i<COUNT -1;i++){
int k = i;
for(int j = i+1;j<COUNT;j++){
if(arr[k]>arr[j]){
k = j;
}
}
if(k!=i){
arr[i] = arr[i]^arr[k];
arr[k] = arr[i]^arr[k];
arr[i] = arr[i]^arr[k];
}
}
}
// 选择排序之 堆排序
/*
* 实验研究表名:平均性能接近最坏性能
* 堆排序在最坏的情况下,其
* 时间复杂度:O(nlog2(n))
* 空间复杂度:O(1)
* 算法特点:
* 1.是不稳定排序。
* 2.只能用于顺序结构,不能用于链式结构
* 3.初始建对所需的比较次数较多 ,因此记录数较少时不宜采用。
* 堆排序在最坏的情况下时间复杂度为O(nlog2(n)),相对于快速排序最坏情况下的O(n^2)而言是一个优点,当记录较多时较为高效。
*/
/**
堆排序
1.筛选法求大根堆
2.构建堆
3.对堆进行排序
*/
void HeapAdjust(int * arr,int s,int m){
int j = 0;
int val = arr[s];
for(int j= 2*s;j<=m;j*=2){
if(j<m&&arr[j]<arr[j+1]){
j++;
}
if(val>=arr[j])
break;
arr[s] = arr[j];
s=j;
}
arr[s]= val;
}
void CreatHeap(int *arr){
for(int j =COUNT/2;j>=0;j--){
HeapAdjust(arr,j,COUNT-1);
}
}
void HeadSort(int *arr){
CreatHeap(arr);
for(int i = COUNT-1;i>=1;i--){
arr[i] = arr[i]^arr[0];
arr[0] = arr[i]^arr[0];
arr[i] = arr[i]^arr[0];
HeapAdjust(arr,0,i-1);
}
}
//归并排序
/*
* 时间复杂度:O(nlog2(n))
* 空间复杂度:O(n)
* 算法特点:
* 1.是稳定排序
* 2.可用于链式结构,且不需要附加存储空间,但是递归实现仍需要开辟相应的递归工作栈
*/
void Merge(int *R ,int *T,int low ,int mid,int high){
int i = low;
int j = mid+1;
int k = 0;
while(i<=mid&&j<=high){
if(R[i]<R[j]){
T[k++] = R[i++];
}else{
T[k++] = R[j++];
}
}
while(i<=mid){
T[k++] = R[i++];
}
while(j<=high){
T[k++] = R[j++];
}
for(int t = 0;t<k;t++){
R[low+t] = T[t];
}
}
void MSort(int *R ,int * T ,int low, int high){
if(low<high){
int mid =(low+high)/2;
MSort(R,T,low,mid);
MSort(R,T,mid+1,high);
Merge(R,T,low,mid,high);
}
}
八种排序的比较
最新推荐文章于 2023-07-20 15:51:28 发布