四种排序算法

▼魔方 西西 提交于 2020-04-06 03:57:24

前言:经过昨天做的排序算法题,发现自己这么简单的题都忘记怎么做了,感觉很难受,今天复习整理了一遍,写成一个文章,以便日后复习,其中冒泡、选择、插入三种算法的思路和图片来自于B站up主"正月点灯笼",感谢你的讲解,我觉得你讲的非常好!

冒泡排序

例如 3、7、4、2、6、1这一个数组,我们对它进行升序的一个排序

1、首先从左往右两两进行比较,若左>右,则交换位置,进行第一趟排序

对于这第一趟的排序,并不能保证从左往右一定都是正确的升序排序,但是一定能保证最大的数已经排在了最右边

由此,我们可以得到一个思路,在第一趟排序后,我们只需要对这个长度为6的数组左边5个数字再进行一次冒泡排序,然后再对左边4个数字再进行一次冒泡排序,以此类推.....

#include <stdio.h>
/*
冒泡排序算法
*/


 /***
 * @Description:交换函数,交换括号内的参数 
 * [@Param](https://my.oschina.net/u/2303379): &a,&b
 * [@return](https://my.oschina.net/u/556800): 
 * [@Author](https://my.oschina.net/arthor): JaneRoad
 * [@Date](https://my.oschina.net/u/2504391): 2020/4/1
 */
void swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}



/***
* @Description:一次冒泡函数,将数组中最大的数移到最右边
* @Param: arr[],n(数组,数组长度)
* @return: 
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void bubble(int arr[],int n){
    int i;
    for(i=0;i<n-1;i++){
        if(arr[i]>arr[i+1]){
            swap(arr[i],arr[i+1]);
        }
    }
}



/***
* @Description:冒泡排序函数,实现升序排序 
* @Param: arr[],n(数组,数组长度)
* @return: 
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void bubbleSort(int arr[],int n){
    int i;
    for(i=n;i>=1;i--){
        bubble(arr,i);
    }
}



int main()
{
    int arr[] = {12,13,15,20,0,-1,-10,100,9};
    bubbleSort(arr,9);
    for(int i=0;i<9;i++){
        printf("%d\n",arr[i]);
    }
    return 0;
}

最终结果:

选择排序

例如 3、7、4、2、6、1这一个数组,我们对它进行升序的一个排序

首先找出[3、7、4、2、6、1]中最大的数字,将其与数组末位数字进行交换,然后再对前五个数字,即

[3、1、4、2、6] 中找出最大数字,再与末位数字进行交换,这样以此类推,就可以将这个数组进行升序排列

#include <stdio.h>
/*
选择排序算法学习
*/


/***
* @Description:交换函数,交换括号内的参数
* @Param: &a,&b
* @return:
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}


/**
* @Description: 遍历寻找当前数组中最大的数的数组位置
* @Param: arr[],n(数组,数组长度)
* @return: pos
* @Author: JaneRoad
* @Date: 2020/4/1
*/
int findMaxPos(int arr[],int n){
    int max=arr[0];
    int pos=0;
    for (int i = 0; i <n ; i++) {
        if(arr[i]>max){
            max=arr[i];
            pos=i;
        }
    }
    return pos;
}



/**
* @Description: 选择排序函数
* @Param: arr[],n(数组,数组长度)
* @return: 
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void selectionSort(int arr[],int n){
    while(n>1){
        int pos=findMaxPos(arr,n);
        swap(arr[pos],arr[n-1]);
        n--;
    }
}


int main()
{
    int arr[] = {12,13,15,20,0,-1,-10,100,9};
    selectionSort(arr,9);
    for(int i=0;i<9;i++){
        printf("%d\n",arr[i]);
    }
    return 0;
}

插入排序

例如 3、7、4、2、6、1这一个数组,我们对它进行升序的一个排序

插入排序的思想就是,把一段数字分成两段,一段时间排好顺序的,一段时间未排好的。

例如:

图中[3、6、7] 就是一段排好顺序的,[4、2、1、5]就是未排好的,我们要想办法把4、2、1、5依次插到前面一段已经排好顺序的段落中正确的位置,这样就是插入排序。

我们知道了原理如何转化为代码思路呢?

我们以3、6、7、4为例

1、数组中的3、6、7已经是正确顺序,我们要想办法把4插入到它应该去的地方,我们设置一个值为key,key=4

然后我们再设置一个i,指向4所在的数组位置,即i=3 ,4和它的前一位数字7进行比较,7比4大所以我们使arr[3]=arr[2],也就是把4覆盖成7

2、完成上一步后,我们让i--,也就是i指向前一位数组位置,再次比较6和4(key),6比4大,所以再次arr[2]=arr[1],也就是把原本的7覆盖成6,

3、完成上一步后,i--,i来到了arr[1],3与4进行比较发现3比4小,那么条件不成立,4应该在此时i指向的数组位置,即arr[1]=key

但是这个方法要注意一点

如上图,2是最小的数字,他应该在最左边,但是在程序中,当它移动到arr[0]的位置时,他并不知道自己在数组最左端,它再找前一位数字进行比较时,就会报错,所以当i=0时,必须要停止。

在实际代码中,我们通常把第一个数字当成一个整体,它本身就是一个已经排好序的一段数字,尽管它只是单个数字,然后从后往前插入排序

#include <stdio.h>
/*
插入排序算法学习
*/

/***
* @Description:插入函数,数组中从后往前不断插入数字到正确位置
* @Param: arr[],n
* @return:
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void insert(int arr[],int n){
    int key=arr[n];
    int i=n;
    while(arr[i-1]>key){
        arr[i]=arr[i-1];
        i--;
        if(i==0){
            break;
        }
    }
    arr[i]=key;
}

/***
* @Description:插入排序函数,调用插入函数
* @Param: arr[],n
* @return:
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void insertionSort(int arr[],int n){
    int i;
    for (int i = 0; i < n; i++) {
        insert(arr,i);
    }
}


int main()
{
    int arr[] = {12,13,15,20,0,-1,-10,100,9};
    insertionSort(arr,9);
    for(int i=0;i<9;i++){
        printf("%d\n",arr[i]);
    }
    return 0;
}

快速排序

快速排序是我今天早上一早上慢慢想,跟着断点读示范代码领悟的,没有查资料,所以记得很清晰。

例如 3、6、7、4、2、1、5这一个数组,我们对它进行升序的一个排序

1、选取基准数3,设置头指针、尾指针,分别指向数组第一个元素和最后一个元素

2、基准数3与尾指针指向数字5比较,3<5且3在5左边,正确,不交换,尾指针前移一位,指向1

3、基准数3与尾指针指向数字1比较,3>5但3在1左边,做交换,arr[0]=1,arr[5]=3,由于此时尾指针指向了基准数3,故前指针后移一位,指向6。

4、基准数3与头指针指向数字6比较,3<6但3在6右边,做交换,尾指针前移一位,指向2

5、基准数3与尾指针指向数字2比较,3>2但3在2左边,做交换,头指针后移一位,指向7

6、基准数3与头指针指向数字7比较,3<7但3在7右边,做交换,尾指针前移一位,指向4

7、基准数3与尾指针指向数字4比较,3<4且3在4左边,正确,不做交换,尾指针前移,发现尾指针与头指针位置重合,第一趟快速排序完成

此时的数组是 [1、2、3、4、7、6、5]

我们可以发现最中间的4,左边都是比它小的数右边都是比它大的数

此时4左边的数字为一组,右边的数字为一组,分别递归调用快速排序,以此类推,即可完成数组排序

#include <stdio.h>
/*
快速排序算法学习
*/
/***
* @Description:交换函数,交换括号内的参数
* @Param: &a,&b
* @return:
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
/***
* @Description:快速排序算法
* @Param: arr[],start,end(数组,数组头元素位置,数组尾元素位置)
* @return:
* @Author: JaneRoad
* @Date: 2020/4/1
*/
void quickSort(int arr[] ,int start, int end)
{
    int arrBase, arrMiddle;
    //arrBase为基准值,arrMiddle为一趟快速排序下来后,最中间的数字在数组中的位置(是第几个元素)
    int tempStart = start,tempEnd = end;

    //当头指针和尾指针重合时,跳出函数
    if(tempStart >= tempEnd)
        return;

    //拷贝一个基准值作为后面比较的参数
    arrBase = arr[start];
    while(start < end)
    {
        while(start < end && arr[end] > arrBase)
            end--;
        if(start < end)
        {
            swap(arr[start], arr[end]);
            start++;
        }

        while(start < end && arr[start] < arrBase)
            start++;
        if(start < end)
        {
            swap(arr[start], arr[end]);
            end--;
        }
    }
    arr[start] = arrBase;
    arrMiddle = start;

    //左右分别进行递归
    quickSort(arr,tempStart,arrMiddle-1);
    quickSort(arr,arrMiddle+1,tempEnd);
}


int main()
{
    int myArr[] = {12,13,15,20,0,-1,-10,100,9};
    int arrLength = sizeof(myArr)/sizeof(int);//数组长度
    quickSort(myArr,0,arrLength-1);
    for(int i=0;i<arrLength;i++){
        printf("%d\n",myArr[i]);
    }
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!