数据结构之进阶排序(希尔排序、快速排序、归并排序)

我们学习了最基础的三种排序,它们都有个共同点,就是时间复杂度都是O(n^2),

在long long ago,科学家们以为排序时间复杂度已经到了极限了,不可能存在低于O(n^2)

的排序,但是呢!有个家伙叫希尔的。。。。。(此处略去1W字),然后希尔排序就出现了,

希尔排序的本质还是插入排序(什么?插入排序,好熟悉啊!),前面我们学了插入排序,

那么这个希尔到底做了什么使它的时间复杂度降低到O(n^2)呢?闲话少扯,上代码。

#include <stdio.h>
#include <stdlib.h>

void print(int array[], int len)
{
    int i = 0;
    for (i = 0; i < len; i++)
    {
        printf("%d ",array[i]);    
    }     
    
    printf("\n");
}

void swap(int array[], int i, int j)
{
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

void ShellSort(int array[], int len)
{
    int i = 0;
    int j = 0;
    int k = -1;
    int temp = -1;
    int gap = 0;
    
    do
    {
        gap = gap / 3 + 1;
        
        for (i = gap; i < len; i += gap)
        {
            k = i;
            temp = array[k];
            
            for (j = i - gap; (j >= 0) && (array[j] >= temp); j--)
            {
                array[j + gap] = array[j];
                k = j;
            }    
            
            array[k] = temp;
        }
    } while(gap > 1);     
}

int main(int argc, char *argv[])
{
    int a[] = {22,44,11,66,77,44,33};
    int len = sizeof(a) / sizeof(int);
    
    print(a, len);
    
    ShellSort(a, len);
  
    print(a, len);
  
    system("PAUSE");	
    return 0;
}
是不是挺简单的,希尔排序的主要技巧是在gap的设计,但gap具体除以多少暂时还没有规定,

你把gap设为1,那就是最坏的情况,也就是成了插入排序。


下面我们来说下项目中常用到的快速排序,在希尔突破了O(n^2)之后,很多科学家也加入研究中,

所以也就有了快速排序。快速排序它很巧妙的把递归应用到里面,在第一次查找的时候,找到一个元素,

这个元素左边都是小于它,右边都是大于它,所以第一个元素的位置就确定了,然后左边和右边依次递归,

整个算法实现非常巧妙,不得不佩服啊!上代码。

#include <stdio.h>
#include <stdlib.h>

void print(int array[], int len)
{
    int i = 0;
    for (i = 0; i < len; i++)
    {
        printf("%d ",array[i]);    
    }     
    
    printf("\n");
}

void swap(int array[], int i, int j)
{
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

int Postition(int array[], int low, int high)
{
    int pv = array[low];
    
    while (low < high)
    {
        while ((low < high) && (array[high] >= pv))
        {
            high--;      
        }      
        
        swap(array, low, high);
        
        while ((low < high) && (array[low] <= pv))
        {
            low++;      
        }
        
        swap(array, low, high);
    }
    
    array[low] = pv;
    
    return low;
}

void QSort(int array[], int low, int high)
{
    if (low < high)
    {
        int pos = Postition(array, low, high);
        
        QSort(array, low, pos - 1);
        QSort(array, pos + 1, high);        
    }
}

void QuickSort(int array[], int len)
{
    QSort(array, 0, len - 1);   
}

int main(int argc, char *argv[])
{
    int a[] = {22,44,11,66,77,44,33};
    int len = sizeof(a) / sizeof(int);
    
    print(a, len);
    
    QuickSort(a, len);
  
    print(a, len);
  
    system("PAUSE");	
    return 0;
}

看明白了吗?是不是言简意赅,好了下面我们介绍下归并排序,为什么会存在归并排序呢?

主要是因为希尔排序和快速排序不是稳定的排序,在操作过程中有大量的数据移动,所以,

就产生了一种叫归并排序的东东,那么什么是归并排序呢?简单的说就是,把一组数据,

分成几个已经排好的数组,然后把他们合并成一个数组(百度吧!这个一下数不清楚)

好了,show time!

#include <stdio.h>
#include <stdlib.h>

void print(int array[], int len)
{
    int i = 0;
    for (i = 0; i < len; i++)
    {
        printf("%d ",array[i]);    
    }     
    
    printf("\n");
}

void Merge(int src[], int dest[], int low, int mid, int high)
{
    int i = low;
    int j = mid + 1;
    int k = low;
    
    while ((i <= mid) && (j <= high))
    {
        if (src[i] < src[j])
        {
            dest[k++] = src[i++];           
        }      
        else
        {
            dest[k++] = src[j++];    
        }
    }     
    
    while (i <= mid)
    {
        dest[k++] = src[i++];      
    }
    
    while (j <= high)
    {
        dest[k++] = src[j++];      
    }
}

void MSort(int src[], int dest[], int low, int high, int max)
{
    if (low == high)
    {
        dest[low] = src[low];    
    }
    else
    {
        int mid = (low + high) / 2;
        int* space = (int*)malloc(sizeof(int) * max);
        
        if (space != NULL)
        {
            MSort(src, space, low, mid, max);
            MSort(src, space, mid + 1, high, max);
            Merge(space, dest, low, mid, high);          
        }
        
        free(space);
    } 
}

void MergeSort(int array[], int len)
{
    MSort(array, array, 0, len - 1, len);     
}

int main(int argc, char *argv[])
{
    int a[] = {22,44,11,66,77,44,33};
    int len = sizeof(a) / sizeof(int);
    
    print(a, len);
    
    MergeSort(a, len);
  
    print(a, len);
  
    system("PAUSE");	
    return 0;
}

是不是跟快速排序有点像呢?但是它保证稳定性的前提下,牺牲了空间,就是每次分组之后申请的堆空间。

上述三种排序的时间复杂度都是O(nlogn),所以在科学界不断的努力下,排序算法的时间复杂度还是可以改变的嘛!!!


    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值