基于数组的排序算法

常用的基于数组的排序算法代码详解(二)


上次已经对几种排序算法进行了分析,接下来对剩余的几种排序算法进行分析,以及给出测试函数。

int *get_arr(int len)
{
    //srand(time(NULL));
    srand(100);

    int *arr = (int *)malloc(sizeof(int)*len);
    assert(arr != NULL);

    for(int i = 0;i < len;i++)
    {
        arr[i] = rand();
    }
    return arr;
}

5,希尔排序
空间复杂度:O(1) 时间复杂度:O(n^1.35)/O(n^1.5)
思路:将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。

static void shell(int *arr,int len,int gap)
{
    int i;
    int j;
    int tmp;
    for(i = gap;i < len;i++)
    {
        tmp = arr[i];
        for(j = i-gap;j>=0;j = j-gap)
        {
            if(tmp > arr[j])
            {
                break;
            }
            arr[j+gap] = arr[j];
        }
        arr[j+gap] = tmp;
    }
}

void shell_sort(int *arr,int len)
{
    shell(arr,len,3);
    shell(arr,len,1);
}

6,快速排序
空间复杂度:O(logn) 时间复杂度:O(n*logn)
思路:挖坑填数+分治法。从序列当中选择一个基准数,在这里我们选择序列当中第一个数最为基准数,将序列当中的所有数依次遍历,比基准数大的位于其右侧,比基准数小的位于其左侧,重复步骤1.2,直到所有子集当中只有一个元素为止。

//递归形式快速排序
int partition(int *arr,int left,int right)
{
    int tmp = arr[left];
    while(left < right)
    {
        while(arr[right] >= tmp && left < right)
        {
            right--;
        }
        arr[left] = arr[right];

        while(arr[left] <= tmp && left < right)
        {
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = tmp;
    return left;
}

void quick(int *arr,int left,int right)
{
    if(left < right)
    {
        int base = partition(arr,left,right);
        quick(arr,left,base-1);
        quick(arr,base+1,right);
    }
}

void quick_sort(int *arr,int len)
{
    quick(arr,0,len-1);
}

//非递归形式快速排序
void quick_sort_stack(int *arr,int len)
{
    int *stack = (int *)malloc(sizeof(int) * len * len);
    assert(stack != NULL);

    int top = 0;
    stack[top++] = 0;
    stack[top++] = len - 1;

    int left = 0;
    int right = 0;
    int base = 0;
    while(top != 0)
    {
        right = stack[--top];
        left = stack[--top];
        base = partition(arr,left,right);
        if(left < base-1)
        {
            stack[top++] = left;
            stack[top++] = base - 1;
        }
        if(right > base+1)
        {
            stack[top++] = base + 1;
            stack[top++] = right;
        }
    }
    free(stack);
}

7,堆排序
空间复杂度:O(1) 时间复杂度:O(n*logn)
堆:本质是一种数组对象。特别重要的一点性质:任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆,大顶堆要求节点的元素都要大于其孩子,小顶堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求。
利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。

  static void heap_adjust(int *arr,int start,int end)
{
    int tmp = arr[start];
    for(int i = 2*start+1;i <= end;i = 2*i+1)
    {
        if(i < end && arr[i]+1])
        {
            i++;
        }
        if(tmp > arr[i])
        {
            break;
        }
        else if(tmp else    //tmp == arr[i]
        {
            ;
        }
        start = i;
    }
    arr[start] = tmp;
}

void heap_sort(int *arr,int len)
{
    for(int start = len/2-1;start >= 0;start--)
    {
        heap_adjust(arr,start,len-1);
    }
    swap(&arr[0],&arr[len-1]);
    for(int k = len-1;k>0;k--)
    {
        heap_adjust(arr,0,k-1);
        swap(&arr[0],&arr[k-1]);
    }
}  

8,归并排序
空间复杂度:O(n) 时间复杂度:O(n*logn)
思路:通过序列中各个元素的值,对排序的N个元素进行若干趟的“分配”与“收集”来实现排序。
分配:我们将L[i]中的元素取出,首先确定其个位上的数字,根据该数字分配到与之序号相同的桶中
收集:当序列中所有的元素都分配到对应的桶中,再按照顺序依次将桶中的元素收集形成新的一个待排序列L[ ]对新形成的序列L[]重复执行分配和收集元素中的十位、百位…直到分配完该序列中的最高位,则排序结束。

void meger(int *arr,int len,int gap)
{
    int *buff = (int *)malloc(sizeof(int)*len);
    int k = 0;

    int L1 = 0;
    int H1 = L1+gap-1;

    int L2 = H1+1;
    int H2 = L2+gap-1 < len ? L2+gap-1 : len-1;

    while(L2 < len)
    {
        while(L1 <= H1 && L2 <= H2)
        {
            if(arr[L1] <= arr[L2])
            {
                buff[k++] = arr[L1++];
            }
            else if(arr[L1] > arr[L2])
            {
                buff[k++] = arr[L2++];
            }
        }

        while(L1 <= H1)
        {
            buff[k++] = arr[L1++];
        }
        while(L2 <= H2)
        {
            buff[k++] = arr[L2++];
        }

        L1 = H2+1;
        H1 = L1+gap-1;
        L2 = H1+1;
        H2 = L2+gap-1 < len ? L2+gap-1 : len-1;
    }
    while(L1 < len)
    {
        buff[k++] = arr[L1++];
    }

    for(int i = 0;i<len;i++)
    {
        arr[i] = buff[i];
    }

    free(buff);
}

void meger_sort(int *arr,int len)
{
    for(int gap = 1;gap < len;gap = gap*2)
    {
        meger(arr,len,gap);
    }
}

测试用例:

#include"sort.h"
#include

int main()
{
    int arr[] = {13,34,32,21,13,45,30,56,43,31,11};
    int len = sizeof(arr)/sizeof(arr[0]);

    /*int *arr = get_arr(100000);
    int len = 100000;
*/
    //exchange_sort (arr,len);
    //show(arr,len);
    //bubble_sort(arr,len);
    //show(arr,len);
    //bubble_sort_ex(arr,len);
    //show(arr,len);
    //select_sort(arr,len);
    quick_sort(arr,len);
    //show(arr,len);
    quick_sort_stack(arr,len);
    //shell_sort(arr,len);
    meger_sort(arr,len);
    show(arr,len);
    /*insert_sort_ex(arr,len);
    show(arr,len);*/
    return 0;
}

最后,对几种排序算法进行比较:

                     排序算法的分类

基于数组的排序算法_第1张图片

                      排序算法性能比较

基于数组的排序算法_第2张图片

若文章中或代码中存在问题,欢迎指正。

你可能感兴趣的:(c语言核心)