常见排序算法——交换排序

利用交换元素的位置进行排序的方法称作交换排序
常用的交换排序的方法:冒泡排序和快速排序
【冒泡排序】
冒泡排序最好情况时间复杂度O(n),冒泡排序最坏情况下时间复杂度O(n^2)
冒泡排序空间复杂度O(1)
冒泡排序是一种稳定的排序算法

void BubbleSort(int* array, int size)
{
    int i = 0;
    for (i = 0; i < size; i++)
    {
        int j = 0;
        for (j = 0; j < size - 1 -i; j++)
        {
            if (array[j] > array[j + 1])
                Swap(&array[j], &array[j + 1]);
        }
    }
}

交换函数

void Swap(int* pLeft, int* pRight)
{
    int tmp;
    assert(pLeft);
    assert(pRight);

    tmp = *pLeft;
    *pLeft = *pRight;
    *pRight = tmp;
}

【快速排序】
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基
本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将
待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序
列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元
素都排列在相应位置上为止。

将区间按照基准值划分为左右两半部分的常见方式有:
hoare版本
挖坑法
前后指针

快排的时间复杂度:O(N*log2N)
快排的空间复杂度: O(log2N) (单支为O(N))
快排是不稳定的

快排递归代码

void QuickSort(int* array, int left,int right)
{
    if (right - left > 1)
    {
        int div = Partion3(array, left, right);

        QuickSort(array, left, div);

        QuickSort(array,div+1,right);
    }
}

hoare法

int Partion1(int* array, int left, int right)
{
    int begin = left;
    int end = right - 1;
    int key = array[end];

    while (begin < end)
    {
        //从前往后找比基准值大的元素
        while (begin < end && array[begin] <= key)
            ++begin;

        //从后往前找比基准值小的元素
        while (begin < end && array[end] >= key)
            --end;

        if (begin < end)
            Swap(&array[begin], &array[end]);
    }
    if (begin != right)
        Swap(&array[begin], &array[right - 1]);

    return begin;
}

挖坑法

int Partion2(int* array, int left, int right)
{
    int begin = left;
    int end = right - 1;

    //将基准值保存在key里面,原来基准值所在的位置会出现一个坑
    int key = array[end];

    while (begin < end)
    {
        //从前往后找比基准值大的元素
        while (begin < end && array[begin] <= key)
            ++begin;

        //找到比基准值大的元素后就用该值去填充上次的坑
        if (begin < end)
        {
            array[end] = array[begin];
            end--;
        }

        //从后往前找比基准值小的元素
        while (begin < end && array[end] >= key)
            --end;

        //找到比基准值小的元素后就用该值去填充上次的坑
        if (begin < end)
        {
            array[begin] = array[end];
            begin++;
        }
    }
    //用基准值来填充最后一个坑
    array[begin] = key;

    return begin;
}

前后指针

int Partion3(int* array, int left, int right)
{
    int pre = left - 1;
    int cur = left;
    int key = array[right - 1];

    while (cur < right)
    {
        if (array[cur] < key && ++pre != cur)
            Swap(&array[cur], &array[pre]);
        ++cur;
    }
    if (++pre != right)
        Swap(&array[pre], &array[right - 1]);

    return pre;
}

快排非递归代码


void QuickSortNor(int* array, int size)
{
    if (size < 1)
        return;
    Stack s;
    StackInit(&s);

    //右边元素先入栈
    StackPush(&s, size);
    StackPush(&s, 0);

    while (!StackEmpty(&s))
    {
        int left = 0;
        int right = 0;

        //取栈顶元素即为左边元素
        left = StackTop(&s);
        StackPop(&s);
        right = StackTop(&s);
        StackPop(&s);

        if (left < right)
        {
            int div = Partion1(array, left, right);
        //左半部分元素先入栈
            StackPush(&s, right);
            StackPush(&s,div + 1);

            StackPush(&s,div);
            StackPush(&s, left);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_41289858/article/details/80583058