各种排序的C语言实现

归并排序

归并排序的思想就是将一个数组分为二组,如果这两组数组是有序的话,那么可以很快将这两组数组进行排序。

那么怎么样才能让这两个数组内的数据都有序呢?

可以通过递归的方法,将两个数组各自再分为两组,以此类推,当每个组都只有一个数据的时候,可以认为有序。

再合并数组。

总结起来:归并排序就是通过递归对数组进行分解,再通过合并,从而完成归并排序。

#include <cstdio>

void mergeArray(int* array, int first, int mid, int last, int* buff)
{
    int i, j, m, n,k;
    i = first;
    j = mid;
    m = mid+1;
    n = last;
    k = 0;
    while (i <=j&&m <=n)
    {
        if (array[i] <=array[m])
            buff[k++] = array[i++];
        else
            buff[k++] = array[m++];
    }
    while (i <= j)//如果其中一个数组已经全部移动到buff中,则把另一个数组剩余的元素按序移动到buff。
    {
        buff[k++] = array[i++];
    }
    while (m <= n)//如果其中一个数组已经全部移动到buff中,则把另一个数组剩余的元素按序移动到buff。
    {
        buff[k++] = array[m++];
    }
    for (int q = 0; q < k; q++)
    {
        array[first + q] = buff[q];//两组数组归并好后替换掉原有的数组
    }

}

void mergeSort(int* array, int first,int last,int* buff)
{
    if (first < last)
    {
        int mid = (first + last) / 2;
        mergeSort(array, first, mid, buff);
        mergeSort(array, mid + 1, last, buff);
        mergeArray(array, first, mid, last, buff);
    }
}

bool MergeSort(int* array, int n)
{
    int* buff = new int[n];//开辟一个临时空间
    if (!buff)
        return false;
    mergeSort(array, 0, n-1, buff);
    delete[] buff;//要记得释放
    return true;
}

希尔排序

希尔排序的基本思想是分组插入排序。

基本步骤就是:将整个数组分为若干个子序列,每个子序列的数据相隔某一增量,分别对每个子序列进行直接插入排序。

完成后,再缩小增量,对整个数组进行子序列的重新划分。再对每个子序列进行直接插入排序,以此类推。

直到每个子序列都只有一个单独的数据,最后进行一次直播插入排序。

void shellSort(int* array, int n)
{
    for (int gap = n / 2; gap >0; gap /= 2)
    {
        for (int i = gap; i < n; i++)
        {
            for (int j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap)
            {
                swap(array[j], array[j + gap]);
            }
        }
    }
}

直接插入排序

void insertSort(int* array,int n)
{
    for (int i=1 ; i < n; i++)
    {
        for (int j = i - 1; j >= 0 && array[j] > array[j+1]; j--)
        {
            swap(array[j], array[j + 1]);
        }
    }
}

快速排序

快速排序的主要思想:
【1】选取一个基准,进行分区。将小于基准的数放在基准的左边,将大于基准的数放在基准的右边。对此序列以基准为基准,左边全部是小于基准的数,右边全部是大于基准的数。
【2】运用递归的思想再分别对左右两个半区进行再快速排序。

快速排序的举例说明:

如取array[]={4,7,8,3,6}进行简单说明

【1】取4为基准,i=0, j=4,i用于向右找比4大的数,j用于向左找比4小的数。
【2】首先,先向左找比基准4小的数,6?不是,3?比4小!!此时把基准挖一个坑,并把3填入4的位置,此时基准的坑被填好了,但却出现了一个新的坑,即原来3所在的位置。将值array[0 ]=array[3]后,j–;
【3】接下来,从左向右找一个比基准4大的数,并填入新的坑。7?比4大。好,那么将7这个数值填入新的坑中。array[3]=array[2] ;i++;
【4】当i=j或者是i>j时,停止寻找。
【5】并将基准填入最后出现的坑中。
【6】经历了以上6个步骤后,数组变为3 4 8 7 6 。发现,基准4的左边全是小于4的数,右边全是大于4的数。即成功地进行分区!!
【7】再接下来,运用递归的思想分别再对左右两边进行同样的操作。

//快速排序函数
void quickSort(int* array, int arrayBegin, int arrayEnd)
{

    if (arrayBegin < arrayEnd)//确保输入的参数有效,同时也是递归终止的关键
    {
        int i = arrayBegin;
        int j = arrayEnd;
        int base = array[arrayBegin];//以目标序列的第一个数为基准

        while (i < j)//i=j或者i>j后都不再进行分区
        {
            while ((i < j) && (array[j] >= base))//从后往前找直到找到比基准小的数
                j--;
            if (i < j)
                array[i++] = array[j];//要注意到是先把array[j]赋给array[i]后,i才自加的。此时把坑array[i]填了后,array[j]变成了坑。

            while ((i<j) && (array[i]< base))//while里条件重复一下i<j是有必要的,因为上面的程序会进行 i,j的运算。以防上面的程序运行完后i=j,或者i>j了!!
                i++;
            if (i < j)
                array[j--] = array[i];//要注意到是先把array[i]赋给array[j]后,j才自加的。此时把坑array[j]填了后,array[i]变成了坑。
        }
        array[i] = base;//到最后留下的坑由基准来填。
        quickSort(array, arrayBegin, i - 1);//递归调用对左半区再进行排序
        quickSort(array, i + 1, arrayEnd);//递归调用对右半区再进行排序
    }
}

冒泡排序

//原理版冒泡排序
void bubbleSort1(int array[],int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - i-1; j++)
        {
            if (array[j] > array[j+1])
            {
                swap(array[j], array[j+1]);
            }
        }
    }
}

//优化版冒泡排序
void bubbleSort4(int array[], int n)
{
    int numCount = n;
    while (numCount>0)
    {
        int k = numCount;
        numCount=0;//如果没有可交换的数,这句的作用就可以使while循环结束。
        for (int j = 0; j < k - 1; j++)//比如数组有5个数,则第遍历一次要4次 
        {
            if (array[j] > array[j + 1])
            {
                swap(array[j], array[j + 1]);
                //记录下此时交换数组的位置
                //优点:比如说100个数,后90个数都是排序好的
                //那么,第一次进行交换的位置j一定在10以内
                //记录后赋给一个标志位,从此标志位之后不用再去遍历,而是遍历前10位
                //通俗来说,因为后90个已经不再须要排序,我们可以把这个数组当成只有前10位
                numCount = j + 1;//为什么+1具体逻辑可能得自己通过特殊取值法来验算
            }
        }
    }
}
//测试主函数
void main()
{
    int a[] = { 8,7,10,1,3,5,4,9 };
    quickSort(a, 0, 7);
    bubbleSort4(a,8);
    for (int i = 0; i < 8; i++)
        printf("%d  ", a[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值