(数据结构排序的实验四)快速,冒泡,简单选择,直接插入排序的c语言实现!!

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">#include<stdio.h>
/****四种(冒泡,选择,快速,插入)排序(递增)下标都是从0开始的******/
int dig[1000];
    int n;
/*****1 (交换类) 冒泡排序***时间复杂度:O(n^2)***/
/**思想:一趟排序中(从起始位置开始)是将最大的关键字沉到数组的底部。
n个数字排序,需要n-1趟,(假设就两个数字,那么只要一趟排序将最大的数值沉到数组底部,此序列就是有序的啦)
    若序列本身就是有序的,那么只要一趟即可,(为什么还需要一趟呢?此趟是验证序列都没有发生交换,那么此序列就是有序的)
**/</span>
void bubblingSort(int msort[],int num){
    int tmp;
    int flag;
    for(int i = 0;i < num-1;i++){
        flag = 0;
        for(int j = 0;j < num-i-1;j++){
            if(msort[j]>msort[j+1]){
                flag = 1;
                tmp = msort[j];
                msort[j] = msort[j+1];
                msort[j+1] = tmp;
            }
        }
        if(!flag) break;
    }
    for(int i = 0;i < num;i++){
        printf("%d ",msort[i]);
    }
    printf("\n");
}
/****2 (插入类) 直接插入排序***O(n^2)**/
/**
    思想:假设  2,5,7,10 已经排好了, 而接下来 数字式 6 ,一看就知道把 6 插入到5 和 7 之间。
怎么插入呢?:边插边将数组后移。6 比10 小, 那么10 后移;6比7小,7后移;6比5大,那么就把6插到5的后边(5的后边是个空的,因为前面已经把数组后移啦!!)
**/
void insertSort(int msort[],int num){
    int tmp,j;
    for(int i = 1;i < num;i++){
        tmp = msort[i];
        for( j = i-1;j >= 0;j--){
            if(tmp<msort[j]){
                msort[j+1] = msort[j];
            }
            else{
                break;
            }
        }
        msort[j+1] = tmp;
    }
    for(int i = 0;i <num;i++){
        printf("%d ",msort[i]);
    }
    printf("\n");
}
 /****3 (选择类) 简单选择排序****O(n^2)*/
 /**
    思想:第i 趟排序是指从n-i-1个记录中,找出一个最小的记录与第i个记录交换。那么第i个记录就是较小的。
    列如:第一趟排序:从n个记录中(从dig[1]...dig[n])找到最小的与第一个记录交换,那么第一个就是最小的。
            第二趟排序:从数组后面的n-1个记录中(从dig[2].....dig[n]),找出一个次小的,与第2个记录交换。
    由此看来也是需要n-1趟排序
 **/
 void selectSort(int msort[],int num){
     int minn,pos;
    for(int i = 0;i < num-1;i++){
        minn = 1111111;
        for(int j = i;j < num;j++){
            if(msort[j]<minn){
                minn = msort[j];
                pos = j;
            }
        }
        if(i!=pos){
        int tmp;
        tmp = msort[pos];
        msort[pos] = msort[i];
        msort[i] = tmp;
        }
    }
    for(int i = 0;i <num;i++){
        printf("%d ",msort[i]);
    }
    printf("\n");
 }
/****4 (交换类) 快速排序***O(nlogn)**/
/**
    思想:待排的序列:dig[start].....dig[end],首先任意选取一个记录(通常以第一个记录作为枢轴(啥是枢轴?其实枢轴也没啥概念(不用理解他)))
然后按照下述原则重新排列其余记录。将所有关键字(就是数组里的值)小于它的记录放在它的位置之前,将所有关键字大于它的记录放在它的位置之后。
由此以该“枢轴”记录最后所落的位置i作为分界线,将序列dig[start]....dig[end],分割成两个两个子序列dig[start]...dig[i-1](此序列的值都是无序的但是他们的值都小于枢轴的值)
和dig[i+1]....dig[end]((此序列的值也是无序的但是他们的值都大于枢轴的值)。这个过程为一次划分。!!!
    划分过程的具体实现:附设两个指针(此处的指针并不是指向内存地址的指针,而是指向数组的位置)low,high。low的初值=start,high = end;
设枢轴记录的关键字为pivotkey,则首先从high所指向位置向前搜索找到第一个关键字小于pivotkey的记录和枢轴的记录交换,然后从low所指向的位置向后搜索找到第一个关键字大于pivotkey的记录和枢轴的记录交换。
重复这两步,直至low==high为止。(为什么要附设两个指针从两边开始呢?枢轴右边的都是大于它的,那么只要从右边找到第一个小于枢轴的
和枢轴交换一下,那么小于枢轴的记录就到了枢轴的左边。枢轴的左边也是同样道理)
    快排的实现用到递归。
**/
// 划分 划分操作的时间复杂度是O(n)
int mpartition(int msort[],int low,int high){
int pivotkey = msort[low];
int  tmp;
while(low < high){
    while(low < high&&msort[high]>=pivotkey) --high;
    tmp = msort[low];
    msort[low] = msort[high];
    msort[high] = tmp;
    while(low < high&&msort[low]<=pivotkey) ++low;
    tmp = msort[low];
    msort[low] = msort[high];
    msort[high] = tmp;
    }
    return low;
}
/*****上述划分每一次交换需要进行3次记录移动(赋值)的操作。而实际上,对枢轴记录的赋值操作是多余的,因为只有到了low==high时
此位置才是枢轴记录的最后位置,因此只要在此位置给枢轴赋值即可。******/
int improve_mpartition(int msort[],int low,int high){
int pivotkey = msort[low];
int  tmp;
while(low < high){
    while(low < high&&msort[high]>=pivotkey) --high;
    msort[low] = msort[high];
    while(low < high&&msort[low]<=pivotkey) ++low;
    msort[high] = msort[low];
    }
    msort[low] = pivotkey;
    return low;
}
// 递归操作的时间复杂度是o(log n)
 void quickSort(int msort[],int low,int high){
    int pivotloc;
    /***递归的终止条件是待排序的子序列是一个序列(也就是(序列的左边界)low<high(序列的右边界))***/
    if(low < high){
        pivotloc = improve_mpartition(msort,low,high);
        quickSort(msort,low,pivotloc-1);
        quickSort(msort,pivotloc+1,high);
    }
 }


int main(){
    /**
    输入n个数
    **/
    scanf("%d",&n);
    for(int i = 0; i < n;i++){
        scanf("%d",&dig[i]);
    }
    /****
    因为数组作为参数无法实现值传递, 所以用循环将数组实现复制
    ****/
    int m1sort[100],m2sort[100],m3sort[100],m4sort[100];
    for(int i = 0;i < n;i++){
    m1sort[i] = dig[i];m2sort[i] = dig[i];
    m3sort[i] = dig[i];m4sort[i] = dig[i];
   // m5sort[i] = dig[i];
    }
    /****1 (交换类) 冒泡排序*****/
    printf("冒泡排序\n");
   bubblingSort(m1sort,n);




    /****2 (插入类) 直接插入排序*****/
     printf("直接插入排序\n");
    insertSort(m2sort,n);


    /****3 (选择类) 简单选择排序*****/
    printf("简单选择排序\n");
    selectSort(m3sort,n);


    /****4 (交换类) 快速排序*****/
    printf("快速排序\n");
    quickSort(m4sort,0,n-1);
     for(int i = 0;i < n;i++){
        printf("%d ",m4sort[i]);
    }


}</span></span></span>

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值