c++八大排序算法详解

八大排序算法详解

1. 插入排序

(1) 直接插入排序

列:1 3 4 2,2比3,4都小,先存下q[3]的值即2,将q[2]=4挪到q[3]的位置再判断4的前一个数q[1]是否比2大,如果是则将q[1]的值也往后挪一个位置至q[2],在判断q[0]是否比2小,是则直接将2插入到q[1]的位置,j代表当前插入2的下标,如果满足直接插入q[j]的位置,不满足则将j-1再判断满不满足,依次迭代直到满足为止

a. 时间复杂度
	(1) 最好情况:O(n)
	(2) 平均情况:O(n^2)
	(3) 最坏情况:O(n^2)
b. 辅助空间复杂度
	O(1)
c.稳定(因为只移动比需要排序的元素要大的元素,相等的是不移动的所以是稳定的)
void insert_sort() //直接插入排序
{
    for(int i =1 ;i<n;i++)//因为第一个数永远都是有序的,所以从第二个数开始判断是否有序
    {
        int t = q[i], j=i;//t存当前需要插入排序的值,j存此值的下标
        while(j!=0&&q[j-1]>t)//如果当前需要排序的数前存在其他数并且,前一个数大于当前数
        {
            q[j]=q[j-1];//将前一位大于当前数的位置往后挪一位,再判断这个数前一个数是否也大于当前数
            j--;//下标减一这样才能j-1依次比较前面的数
        }
        q[j] = t;//如果前面的下标j-1的数比当前数小将当前数插入j下标对应的位置
    }
}

(2)折半插入排序
列:1467235, 排序插入2时,前面的序列已经有序,第一次二分区间元素为1467,二分到4,4>2,所以第二次二分区间元素为14,二分到1,1<2,所以2插入到1的右边,右边区间再二分到4,应该插入到4的左边,所以将467统一向后挪一位先挪7再挪6再挪4变为1_46735,然后再插入排序元素即可。
二分插入元素之前的区间[l,r],如果二分元素小于插入排序元素则,需要在二分元素右边插入l=mid+1,如果二分得到的元素大于所要插入排序的元素则插在左边区间r=mid,然后再次二分,直至找到第一个比排序插入元素大的元素,将比此元素大的所有元素向后挪一位,然后将其插入到mid位置。
【注】注意这里只能从后往前挪,因为后面挪的第一个挪完才会有空位置给前一个元素往后挪,如果从前往后挪,后面的元素还没挪就已经被前面的元素给覆盖掉了

	a. 时间复杂度
		(1) 最好情况:O(n)
		(2) 平均情况:O(n^2)
		(3) 最坏情况:O(n^2)
	b. 辅助空间复杂度
		O(1)
	c. 稳定

void binary_search_insert_sort() //折半插入排序
{
    for(int i = 1;i<n;i++)
    {
        if(q[i-1]<=q[i]) continue;//如果要排序的当前元素之前的元素序列都小于等于当前元素,则不用移动位置
        int t =q[i];//存下当前需要排序的元素
        int l =0 ,r = i-1; // 首次二分的区间
        while(l<r)//while循环是一直二分到大于比需要排序的当前元素第一个数
        {
           int  mid = (l + r ) /2;//每次二分得到的元素
           if(q[mid] > t) r = mid;//如果每次二分得到的元素大于当前元素,则排序元素需要插在这次二分元素的左边
           else
           l = mid+1;//如果二分结果小于当前元素则需要插在二分元素的右边
        }
        for(int j = i-1; j >=r;j-- )//将所有大于排序元素的元素向后挪一个位置
        //注意这里只能从后往前挪,因为后面挪的第一个挪完才会有空位置给前一个元素往后挪
        //如果从前往后挪,后面的元素还没挪就已经被前面的元素给覆盖掉了
            q[j+1] = q[j];
        q[r] = t ; //插入当前排序元素
    }
}

3. 冒泡排序(bubble sort)

列:5 4 2 1 3,
第一次排序:->5 4 1 2 3 -> 5 1 4 2 3 -> 1 5 4 2 3 ; 这之后冒泡排序序列为5 4 2 3
第二次排序:->5 2 4 3 -> 2 5 4 3 ; 之后的冒泡排序序列为5 4 3
第三次排序:->5 3 4 -> 3 5 4 ; 之后的冒泡排序序列为 5 4
第四次排序: -> 4 5
排序完成 1 2 3 4 5,n个元素只需要n-1次排序
冒泡排序从后往前冒,只要前一个数比后一个数大就交换这俩个数,如果有序就不用交换继而判断前一个数和其之前的元素是否有序,当遇到当前冒泡序列的最小值时,会一直交换,直到最小值位于此序列之首。每次只要确定一个序列的最小数之后,之后的冒泡排序序列将不再包括此数。长度为n的序列只需要循环n-1次即可排序完毕,循环n-1次即已确定前n-1个最小数,最后一个必然是最大数。

a. 时间复杂度
	(1). 最好情况:O(n) //初始就为有序序列
	(2). 平均情况:O(n^2)
	(3). 最坏情况:O(n^2)  //初始序列为逆序序列
b. 空间复杂度
	O(1)
c. 稳定  // 相等元素不交换位置
void bubble_sort()//冒泡排序
{
    for(int i=0;i<n-1;i++)//n个数排序只要循环n-1次,将前n-1个最小数排序,最后一个自然最大即n个数有序
    {
        bool has_swap = false;//定义bool变量,如果第一次循环都没有交换过数即这个序列本身就是有序的,直接返回
        for(int j = n-1;j>i;j--)
        //for循环第一次判断最后一个元素和其前一个元素的大小,如果有序,则j--判断倒数第二个元素和其前一个元素的大小
        //冒泡排序是从后往前冒,冒到最小的数时,最小的数会一直交换到最前面
        //每次确定完最小的数,后面冒泡的序列是这个最小数后面的序列即不再包括这个最小数及最小数前面的序列
            if(q[j-1]>q[j])//如果前一个数大于后一个数
            {
                swap(q[j],q[j-1]);//交换这俩个数
                has_swap = true;//标记一下,即这个序列一开始不是有序的
            }
        if(has_swap ==false)
        break;
    }
}

4. 简单选择排序

简单选择排序即给出一个序列,从第一个数从前往后排序,每排一个数都将此数与其后面整个序列进行比较,每找到一个比它小的数,都跟这个位置的数进行交换,直至找到后面的序列的最小数。同样只需要排n-1次,最后一个数一定为最大数。
列如 3 2 1 4; 第一个排序的数为3,跟后面的序列2 1 4 依次比较,找到比第一个位置小的数就与其交换 : 结果为 2 3 1 4-> 1 3 2 4;
再排第二个数3,也是依次比较3后面的整个序列找到其中最小数,结果为:1 2 3 4;

(1) 时间复杂度
	a. 最好情况:O(n^2)
	b. 平均情况:O(n^2)
	c. 最坏情况:O(n^2)
(2) 空间复杂度
	O(1)
(3) 不稳定
void select_sort()//简单选择排序
{
    for(int i = 0 ; i<n-1 ;i++)//同样的,对n个数排序只需要排前n-1个数,最后一个数一定最大
    {
        int  k = i;//记住当前需要排序元素的下标
        for(int j = i + 1;j< n;j++)//从此元素后面的序列判断哪个数最小,将最小数与当前排序的数进行交换
        if(q[i]>q[j])
        swap(q[i],q[j]);
    }
    //简单选择排序每次循环都会遍历一遍当前数后面的序列找到最小值,然后交换,所以平均,最好,最坏的复杂度都是O(n²)
}

5. 希尔排序(shell sort)

希尔排序,每次按相同增量将原序列分为若干个组,每个组内元素下标都是一个等差数列,增量即这个等差数列的公差,再在组内进行简单插入排序,之后缩小增量,再将获得的序列重新按增量分组,再在组内进行简单插入排序,最后结果就是增量为1时,所有元素都在同一个组里,将所有元素按简单插入排序排好。

下标 :0 1 2 3 4 5 6 7
列如 :1 4 6 7 3 5 2 8 此序列按照增量为n/2来分,获得序列有四个
分别为 [1,3] ,[4,5] ,[6,2] , [7,8]。
每个组内每个元素的下标都相差n/2=4; 在每个组内进行简单(直接)插入排序,结果为[13],[4,5],[2,6],[7,8]
获得新序列为 1 4 2 7 3 5 6 8。然后缩小增量为2(原本增量为4),再次分组且组内进行插入排序。
二次分组分别为:[ 1,2,3,6], [4,7,5,8],组内元素下标相差2,即增量为2。然后再组内进行插入排序获得新序列为:1 4 2 5 3 7 6 8。再缩小使增量为1(上一次为2),
第三次分组获得分组[1,4,2,5,3,7,6,8],此次可以看到所有元素再同一个组里,对组内所有元素进行插入排序获得最终结果[1,2,3,4,5,6,7,8]

(1) 时间复杂度
	O(n^(3/2))
(2) 空间复杂度
	O(1)
(3) 不稳定
void shell_sort()//希尔排序
{
    for(int d = n/2;d!=0;d=d/2)//第一重循环表示每种不同分组法,每有不同增量进行分组时,都要在分出的组中进行插入排序
    {
        for(int start=0;start<d;start++)//二重循环是需要枚举每一个分组,只需要表示出起点就可以,后面增量相同就可以将所有元素都分在这几个分组当中
        //如果当d=4时,各个分组的起点一定分别为0,1,2,3
        //因为增量为4,每一组的元素下标必定相差4,下标列如[0,4],[1,5],[2,6],[3,7],[4,8]
        {
            for(int i = start+d;i<n;i= i+d)//因为插入排序都是从每个组第二个数开始插入排序,第一个元素插入必定有序,所以从start+d开始
            {
                int t = q[i],j=i;//t存下当前需要插入排序的数,j存此数的下标
                while(j>start&&q[j-d]>t)//当j不是第一个数时(即排好序的最小数)并且需要插入排序的数的前一个数比当前数大
                {
                    q[j] = q[j-d];//将前一个数位置向后挪动一位,初始时因为已经记下t=q[i]了所以不用担心q[i]被覆盖
                    j=j-d;//再判断组内更前面一个数是否比需要插入排序的数大,如果不满足会直到前面没有数,即插入排序的数放第一个
                }
                q[j] = t;//将需要插入排序的值放入下标为j的位置
            }
        }
    }
}

6. 快速排序

(1) 时间复杂度
	a. 最好情况:O(nlogn)
	b. 平均情况:O(nlogn)
	c. 最坏情况:O(n^2)
(2) 空间复杂度
	O(logn)
(3) 不稳定
void qucik_sort(int l,int r)//每次快排的区间(按下标看)
{
    if(l==r) return ;//如果区间长度为1就不用排了直接返回
    int i = l -1, j = r +1, x = q[(r+l)/2]; //i=l-1,j=r+1,是为了保证do i++后为第一个数,do j--为最后一个数,否则就首位俩个数就会被跳过判断不了。
    while(i<j)//当俩个指针相遇时停止循环
    {
        do i++ ;while(q[i]<x);//小于x的原因是如若出现>=x的数一定会被交换到右边
        do j-- ;while(q[j]>x);//大于x是出现<=x的数会被交换到左边
//不能用while do,如果q[i]=q[j]=x,用while do会死循环,交换之后i,j的值也不会变。
        if(i<j) swap(q[i],q[j]);
        //在i<j条件下当do while循环停止时即判定到q[i]>=x,q[j]<=x,交换这俩个数,i,j继续往下判断是否有出现这种情况,如果有再交换这俩个数。
        //最终while循环结束时结果时分界点的左边一定小于等于x,右边一定大于等于x
    }

    qucik_sort(l,j);//依次递归划分的左区间,直至区间长度为1为止
//不能传i即quick_sort(l,i),因为q[i]在划分区间后一定大于等于x不能将q[i]放左边
//即当i++之后i=j且q[i]>=x这时就停止上面的while循环并且也不会交换q[i],q[j].
    qucik_sort(j+1,r);//递归划分的右区间
}

7. 堆排序

堆排序可以按大根堆来排,将完全二叉树按照数组的顺序结构来存储,大根堆即树内每个父节点的值都大于其左右儿子,根节点即为最大数,然后将根节点即q[1]与数组内最后一个数q[sz]交换,即将最大数排序到最后,再将数组长度sz减一,再将整个sz-1长度的数组按照大根堆排序,然后将根节点即最大的数与末尾的数交换,然后再将sz减一,依次这样交换n-1次即完成整个序列的排序。
堆排序的down操作:
down(x)操作是一个递归操作,其原理是判断以x为父节点的树是否父节点的值大于左右儿子,如果是则为大根堆的一部分,如果不是则要将父节点x的值与左右儿子种较大的数进行交换,交换后因为子节点的值发生改变所有又要down操作一遍交换的子节点是否也满足大根堆,依次这样递归直至所有子树都满足大根堆。
a.时间复杂度
(1)最好情况:O(nlogn)
(2)平均情况:O(nlogn)
(3)最坏情况:O(nlogn)
b.空间复杂度
O(logn)
c.不稳定

void down(int u)//堆排序的down操作
{
    int t =u; //t记下当前需要down的数的下标
    //下面的操作是判断父节点是否大于左右儿子,如果不是则选左右儿子较大的数作为父节点
    if(u*2 <=sz && q[u*2]>q[t]) t = u*2; //先判断左儿子的数是否大于父节点如果是则下一个if即判断右儿子是否大于左儿子
    //如果此数的左儿子未越界数组且大于当前数,令t=左儿子的下标
    if(u*2+1 <=sz && q[u*2+1]>q[t]) t=u*2+1;
    //如果此数的右儿子未越界数组且大于当前数,令t=右儿子的下标
    if(u!=t)//如果t!=u即原父节并不比左右儿子大
    {
        swap(q[u],q[t]);//交换父节点与左右儿子俩数之间的较大值的位置,因为是用数组储存,所以交换后父节点的下标位置并不改变
        down(t);//子节点的值变了,为了确保子节点的整棵树也是属于大根堆就得重新递归down一遍,以保证所有数据都满足大根堆
    }
}
void heap_sort()//堆排序下标一定要从1开始,输出输出下标都从1开始
{
    sz = n;//sz为维护的数组边界
    for(int i = n/2;i>0;i--) down(i);//因为大根堆最低层的n/2个元素没有左右儿子所以都不需要down,所有需要down的只有另外n/2个元素
    for(int i = 0;i<n-1;i++)
    {
        swap(q[1],q[sz]);//最终大根堆的根节点一定是最大的数,所以将其跟最后一个数交换,即排序完成最大的数在数组最后
        sz--;//将边界减1就相当于以后递归down操作都不管最后一个数了,即下次排序的最大值为第二大的数,依次操作下去
        down(1);//因为交换了根节点的值得保证整个树为大根堆所以数据又得重新从根节点down操作维护一遍
    }
}

8. 二路归并排序(merge sort)

二路归并的原理也是分治递归,每次都对半划分每一个序列,划分到最后每个区间都只剩一个元素,直接将这个程度区间元素进行归并,之后每个区间都会拥有俩个有序元素的序列,再依次归并,直至最后俩个有序序列进行归并为一个有序序列。
归并,即俩个指针分别指向不同区间,对比这俩个指针指向的数的大小,取小的数放在临时数组w里,同时所属指针向后移动一位,再次对比大小,取较小值依次放入w里,所得到的数组w即为俩个原序列归并得到的一个有序数组。
列子:4 3 2 1
先对半划分为俩个区间[4 3],[2,1],再次对半划分左右区间变为4个区间[4],[3],[2],[1]。
此时每个区间的元素都为1个,此时俩俩归并获得区间[3,4],[1,2].
再次归并俩个有序区间获得有序序列[1,2,3,4]

a.时间复杂度
	(1) 最好情况:O(nlogn)
	(2)平均情况:O(nlogn)
	(3) 最坏情况:O(nlogn)
b.空间复杂度
	O(n)
c.稳定
#include<bits/stdc++.h>

using namespace std;

const int N = 100010;
int q[N];
int n ,sz;//sz是堆排序的维护边界
int w[N];//归并排序的临时数组
void insert_sort() //直接插入排序
{
    for(int i =1 ;i<n;i++)//因为第一个数永远都是有序的,所以从第二个数开始判断是否有序
    {
        int t = q[i], j=i;//t存当前需要插入排序的值,j存此值的下标
        while(j!=0&&q[j-1]>t)//如果当前需要排序的数前存在其他数并且,前一个数大于当前数
        {
            q[j]=q[j-1];//将前一位大于当前数的位置往后挪一位,再判断这个数前一个数是否也大于当前数
            j--;//下标减一这样才能j-1依次比较前面的数
        }
        q[j] = t;//如果前面的下标j-1的数比当前数小将当前数插入j下标对应的位置
    }
}

void binary_search_insert_sort() //折半插入排序
{
    for(int i = 1;i<n;i++)
    {
        if(q[i-1]<=q[i]) continue;//如果要排序的当前元素之前的元素序列都小于等于当前元素,则不用移动位置
        int t =q[i];//存下当前需要排序的元素
        int l =0 ,r = i-1; // 首次二分的区间
        while(l<r)//while循环是一直二分到大于比需要排序的当前元素第一个数
        {
           int  mid = (l + r ) /2;//每次二分得到的元素
           if(q[mid] > t) r = mid;//如果每次二分得到的元素大于当前元素,则排序元素需要插在这次二分元素的左边
           else
           l = mid+1;//如果二分结果小于当前元素则需要插在二分元素的右边
        }
        for(int j = i-1; j >=r;j-- )//将所有大于排序元素的元素向后挪一个位置
        //注意这里只能从后往前挪,因为后面挪的第一个挪完才会有空位置给前一个元素往后挪
        //如果从前往后挪,后面的元素还没挪就已经被前面的元素给覆盖掉了
            q[j+1] = q[j];
        q[r] = t ; //插入当前排序元素
    }
}

void bubble_sort()//冒泡排序
{
    for(int i=0;i<n-1;i++)//n个数排序只要循环n-1次,将前n-1个最小数排序,最后一个自然最大即n个数有序
    {
        bool has_swap = false;//定义bool变量,如果第一次循环都没有交换过数即这个序列本身就是有序的,直接返回
        for(int j = n-1;j>i;j--)
        //for循环第一次判断最后一个元素和其前一个元素的大小,如果有序,则j--判断倒数第二个元素和其前一个元素的大小
        //冒泡排序是从后往前冒,冒到最小的数时,最小的数会一直交换到最前面
        //每次确定完最小的数,后面冒泡的序列是这个最小数后面的序列即不再包括这个最小数及最小数前面的序列
            if(q[j-1]>q[j])//如果前一个数大于后一个数
            {
                swap(q[j],q[j-1]);//交换这俩个数
                has_swap = true;//标记一下,即这个序列一开始不是有序的
            }
        if(has_swap ==false)
        break;
    }
}

void select_sort()//简单选择排序
{
    for(int i = 0 ; i<n-1 ;i++)//同样的,对n个数排序只需要排前n-1个数,最后一个数一定最大
    {
        int  k = i;//记住当前需要排序元素的下标
        for(int j = i + 1;j< n;j++)//从此元素后面的序列判断哪个数最小,将最小数与当前排序的数进行交换
        if(q[i]>q[j])
        swap(q[i],q[j]);
    }
    //简单选择排序每次循环都会遍历一遍当前数后面的序列找到最小值,然后交换,所以平均,最好,最坏的复杂度都是O(n²)
}

void shell_sort()//希尔排序
{
    for(int d = n/2;d!=0;d=d/2)//第一重循环表示每种不同分组法,每有不同增量进行分组时,都要在分出的组中进行插入排序
    {
        for(int start=0;start<d;start++)//二重循环是需要枚举每一个分组,只需要表示出起点就可以,后面增量相同就可以将所有元素都分在这几个分组当中
        //如果当d=4时,各个分组的起点一定分别为0,1,2,3
        //因为增量为4,每一组的元素下标必定相差4,下标列如[0,4],[1,5],[2,6],[3,7],[4,8]
        {
            for(int i = start+d;i<n;i= i+d)//因为插入排序都是从每个组第二个数开始插入排序,第一个元素插入必定有序,所以从start+d开始
            {
                int t = q[i],j=i;//t存下当前需要插入排序的数,j存此数的下标
                while(j>start&&q[j-d]>t)//当j不是第一个数时(即排好序的最小数)并且需要插入排序的数的前一个数比当前数大
                {
                    q[j] = q[j-d];//将前一个数位置向后挪动一位,初始时因为已经记下t=q[i]了所以不用担心q[i]被覆盖
                    j=j-d;//再判断组内更前面一个数是否比需要插入排序的数大,如果不满足会直到前面没有数,即插入排序的数放第一个
                }
                q[j] = t;//将需要插入排序的值放入下标为j的位置
            }
        }
    }
}

void qucik_sort(int l,int r)//每次快排的区间(按下标看)
{
    if(l==r) return ;//如果区间长度为1就不用排了直接返回
    int i = l -1, j = r +1, x = q[(r+l)/2]; //i=l-1,j=r+1,是为了保证do i++后为第一个数,do j--为最后一个数,否则就首位俩个数就会被跳过判断不了。
    while(i<j)//当俩个指针相遇时停止循环
    {
        do i++ ;while(q[i]<x);//小于x的原因是如若出现>=x的数一定会被交换到右边
        do j-- ;while(q[j]>x);//大于x是出现<=x的数会被交换到左边
//不能用while do,如果q[i]=q[j]=x,用while do会死循环,交换之后i,j的值也不会变。
        if(i<j) swap(q[i],q[j]);
        //在i<j条件下当do while循环停止时即判定到q[i]>=x,q[j]<=x,交换这俩个数,i,j继续往下判断是否有出现这种情况,如果有再交换这俩个数。
        //最终while循环结束时结果时分界点的左边一定小于等于x,右边一定大于等于x
    }

    qucik_sort(l,j);//依次递归划分的左区间,直至区间长度为1为止
//不能传i即quick_sort(l,i),因为q[i]在划分区间后一定大于等于x不能将q[i]放左边
//即当i++之后i=j且q[i]>=x这时就停止上面的while循环并且也不会交换q[i],q[j].
    qucik_sort(j+1,r);//递归划分的右区间
}


void down(int u)//堆排序的down操作
{
    int t =u; //t记下当前需要down的数的下标
    //下面的操作是判断父节点是否大于左右儿子,如果不是则选左右儿子较大的数作为父节点
    if(u*2 <=sz && q[u*2]>q[t]) t = u*2; //先判断左儿子的数是否大于父节点如果是则下一个if即判断右儿子是否大于左儿子
    //如果此数的左儿子未越界数组且大于当前数,令t=左儿子的下标
    if(u*2+1 <=sz && q[u*2+1]>q[t]) t=u*2+1;
    //如果此数的右儿子未越界数组且大于当前数,令t=右儿子的下标
    if(u!=t)//如果t!=u即原父节并不比左右儿子大
    {
        swap(q[u],q[t]);//交换父节点与左右儿子俩数之间的较大值的位置,因为是用数组储存,所以交换后父节点的下标位置并不改变
        down(t);//子节点的值变了,为了确保子节点的整棵树也是属于大根堆就得重新递归down一遍,以保证所有数据都满足大根堆
    }
}
void heap_sort()//堆排序下标一定要从1开始,输出输出下标都从1开始
{
    sz = n;//sz为维护的数组边界
    for(int i = n/2;i>0;i--) down(i);//因为大根堆最低层的n/2个元素没有左右儿子所以都不需要down,所有需要down的只有另外n/2个元素
    for(int i = 0;i<n-1;i++)
    {
        swap(q[1],q[sz]);//最终大根堆的根节点一定是最大的数,所以将其跟最后一个数交换,即排序完成最大的数在数组最后
        sz--;//将边界减1就相当于以后递归down操作都不管最后一个数了,即下次排序的最大值为第二大的数,依次操作下去
        down(1);//因为交换了根节点的值得保证整个树为大根堆所以数据又得重新从根节点down操作维护一遍
    }
}

void merge_sort(int l,int r)
{
    if(l==r) return;//判断边界,当区间长度为1时,就不用在二分区间了
    int mid = (l+r)/2;//每次都将区间二分
    merge_sort(l,mid),merge_sort(mid+1,r);//依次递归划分出来的区间
    int i = l , j = mid+1 , k = 0;//l为左区间的首元素下标,j为右区间首元素下标,k为临时数组的下标
    while(i<=mid&&j<=r)//当左右数组都没走完时
    {
        if(q[i]<=q[j]) w[k] = q[i],k++,i++;//判断i,j指针指向的元素的大小,把小的元素放入临时数组w中
        //同时临时数组下标k和调换元素的所属区间的指针i向后移动一位
        else
        w[k] = q[j],k++,j++;//临时数组下标k和调换元素的所属区间的指针j向后移动一位
    }
    while(i<=mid)//当j指针所属的区间数组已经移动完毕,i所属区间还没有移动完毕直接将i后面所有的元素放入临时数组中
    {
        w[k] = q[i];
        k++,i++;
    }
    while(j<=r)//当i指针所属的区间数组已经移动完毕,j所属区间还没有移动完毕直接将j后面所有的元素放入临时数组中
    {
        w[k] = q[j];
        k++,j++;
    }
    for(int i = l,j=0;j<k;i++,j++) q[i] = w[j];//将临时数组w中的所有值搬回原数组q中
}
int main()
{

    cin>>n;
    for(int  i=0; i<n; i++)
        cin>>q[i];

    //insert_sort(); //直接插入排序
    //binary_search_insert_sort();//折半插入排序
    //bubble_sort();  //冒泡排序
    //select_sort();  //简单选择排序
    //shell_sort();//希尔排序
    //qucik_sort(0,n-1);//快速排序
    //heap_sort();//堆排序(下标一定要从1开始)
    merge_sort(0,n-1);
    
    for(int i = 0;i<n;i++)
    cout<<q[i]<<' ';

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值