基于数组的排序算法

来源:互联网 发布:powerdesign mac 编辑:程序博客网 时间:2024/05/21 17:40

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


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

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]<arr[i+1])        {            i++;        }        if(tmp > arr[i])        {            break;        }        else if(tmp <arr[i])        {            arr[start] = arr[i];        }        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<stdio.h>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;}

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

                     排序算法的分类

这里写图片描述

                      排序算法性能比较

这里写图片描述

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

原创粉丝点击