排序(希尔排序,堆排序,归并排序,快速排序)

1.希尔排序
1.1 算法
希尔排序(shell-sort)使用一个序列h1,h2,...,ht,叫做增量序列。只要h1 = 1,任何增量序列都是可行的。在使用增量hk的一趟排序之后,对于每一个i都有A[i] ≤ A[i + hk]。所有相隔hk的元素都被排序。此时称文件是hk-排序。直到h1排序完成,排序完成。
1.2 增量的序列
增量序列的选择极大的影响了希尔算法的效率。
好的增量序列有
(1)1,3,7,...,2^k - 1
(2){1,5,19,41,...}
该序列中的项或者是9*4^i - 9 * 2^i + 1,或者是4^i - 3 * 2^i + 1
1.3 实现
//
//  main.c
//  ShellSort
//
//  Created by Wuyixin on 2017/6/2.
//  Copyright © 2017年 Coding365. All rights reserved.
//

#include <stdio.h>

void shellSort(int a[],int n){
    int j,i,increment,temp;
    for (increment = n/2; increment > 0; increment /= 2) {
        for (i = increment; i < n; i++) {
            temp = a[i];
            for (j = i ; j >= increment ; j -= increment){
                if (temp < a[j - increment])
                    a[j] = a[j - increment];
                else
                    break;
            }
            a[j] = temp;
        }
    }
}

int main(int argc, const char * argv[]) {
    
    int a[] = {9,3,1,4,7,6,5,8,2};
    shellSort(a, 9);
    int i = 0;
    while (i < 9)
        printf("%d ",a[i++]);
    return 0;
}


2.堆排序
2.1 算法
堆排序(heap-sort)是指利用堆积树(堆)这种 数据结构 所设计的一种 排序算法 ,它是选择排序的一种。可以利用 数组 的特点快速定位指定索引的元素。
2.2 实现
//
//  main.c
//  HeapSort
//
//  Created by Wuyixin on 2017/6/3.
//  Copyright © 2017年 Coding365. All rights reserved.
//

#include <stdio.h>


typedef int ElemType;
#define LEFTCHILD(i) (2 * (i) + 1)

/* a是数组,n是数组大小,p是下滤的位置 */
void percolateDown(ElemType a[],int p,int n){
    int child,parent,pvalue;
    parent = p;
    pvalue = a[p];
    while ((child = LEFTCHILD(parent)) < n) {
        /* 取左右孩子中的大者 */
        if (child != n -1 && a[child] < a[child + 1])
            child++;
        /* 下滤 */
        if (pvalue < a[child])
            a[parent] = a[child];
        /* 找到位置 */
        else
            break;
        parent = child;
    }
    
    a[parent] = pvalue;
}

void swap(ElemType* a,ElemType* b){
    ElemType temp = *a;
    *a = *b;
    *b = temp;
}

void heapSort(ElemType a[],int n){
    int i;
    /*构建堆*/
    for (i = n/2; i >= 0; i--)
        percolateDown(a, i, n);
    /* DeleteMax */
    for (i = n - 1; i > 0; i--) {
        swap(&a[0], &a[i]);
        percolateDown(a, 0, i);
    }
    
}


int main(int argc, const char * argv[]) {
    int a[] = {9,3,1,4,7,6,5,8,2,10,11,13,26,26};
    heapSort(a, 14);
    int i = 0;
    while (i < 14)
        printf("%d ",a[i++]);
    
    return 0;
}



3.归并排序
3.1 算法
归并排序(merge-sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路 归并
归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
3.2 实现
//
//  main.c
//  MergeSort
//
//  Created by Wuyixin on 2017/6/3.
//  Copyright © 2017年 Coding365. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;

void merge(ElemType a[],ElemType* tmpArr,int lPos,int rPos,int rEnd){
    int lEnd,tmpPos,numElements;
    lEnd = rPos -1;
    numElements = rEnd - lPos + 1;
    
    tmpPos = lPos;
    while (lPos <= lEnd && rPos <= rEnd)
        if (a[lPos] <= a[rPos])
            tmpArr[tmpPos++] = a[lPos++];
        else
            tmpArr[tmpPos++] = a[rPos++];
    
    while (lPos <= lEnd)
        tmpArr[tmpPos++] = a[lPos++];
    
    while (rPos <= rEnd)
        tmpArr[tmpPos++] = a[rPos++];
    
    for (lPos = 0;lPos < numElements;lPos++,rEnd--)
        a[rEnd] = tmpArr[rEnd];
    
}

void msort(ElemType a[],ElemType* tmpArr,int left,int right){
    int center;
    if (left < right){
        center = (left + right) / 2;
        msort(a, tmpArr, left, center);
        msort(a, tmpArr, center + 1, right);
        merge(a, tmpArr, left, center + 1, right);
    }
}

void mergeSort(ElemType a[],int n){
    ElemType* tmpArr = (ElemType*)malloc(n * sizeof(ElemType));
    if (tmpArr == NULL)
        exit(EXIT_FAILURE);
    msort(a, tmpArr, 0, n - 1);
    free(tmpArr);
}

int main(int argc, const char * argv[]) {
    
    int a[] = {9,3,1,4,7,6,5,8,2,10,11,13,26,26};
    mergeSort(a, 14);
    int i = 0;
    while (i < 14)
        printf("%d ",a[i++]);
    return 0;
}






4.快速排序
4.1算法
快速排序(quick-sort)是对 冒泡排序 的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以 递归 进行,以此达到整个数据变成有序 序列
4.2实现
//
//  main.c
//  QuickSort
//
//  Created by Wuyixin on 2017/6/3.
//  Copyright © 2017年 Coding365. All rights reserved.
//

#include <stdio.h>

#define CUTOFF (3)
typedef int ElemType;

/* 交换a,b的值 */
void swap(ElemType* a,ElemType* b){
    ElemType temp = *a;
    *a = *b;
    *b = temp;
}

/* 插入排序 */
void insertionSort(int a[],int left,int right){
    int i,j,tmp;
    for (i = left + 1; i <= right; i++) {
        tmp = a[i];
        for (j = i; j > left; j--) {
            if (a[j - 1] > tmp)
                a[j] = a[j - 1];
            else
                break;
        }
        
        a[j] = tmp;
    }
}


/* 选择枢纽元 */
ElemType median(ElemType a[],int left,int right){
    int center = (left + right) / 2;
    
    if (a[left] > a[center])
        swap(&a[left], &a[center]);
    if (a[center] > a[right])
        swap(&a[center], &a[right]);
    if (a[left] > a[right])
        swap(&a[left], &a[right]);
    
    /* a[left] <= a[center] <= a[right] */
    
    /* 由于a[right]肯定大于等于枢纽元a[center],因此比较可以从a[right - 1]开始 */
    swap(&a[center], &a[right - 1]);/* 把枢纽元与参与比较的最后一个位置的元素对换 */
    /* 返回枢纽元 */
    return a[right - 1];
}

/* 核心算法 */
void Qsort(ElemType a[],int left,int right){
    ElemType pivot;
    int i,j;
    if (left + CUTOFF > right){
        pivot = median(a, left, right);
        
        for (; ; ) {
            /* 左边可以从left + 1开始比较,以为left上的元素肯定比pivot小 */
            /* 右边可以从right - 1开始比较,以为right上的元素肯定比pivot大 */
            i = left + 1;
            j = right - 2;
            /* 左边跳过比pivot小的数 */
            while (a[i++] < pivot);
            /* 右边跳过比pivot大的数 */
            while (a[j--] > pivot);
            /* 如果i还在j的左边,交换位置*/
            if (i < j)
                swap(&a[i], &a[j]);
            else
                break;
        }
        /* 将枢纽元调换回来 */
        swap(&a[i], &a[right - 1]);
        /* 此时枢纽元的左边都是比它小的元素,右边都是比它大的元素 */
        Qsort(a, left, i - 1);
        Qsort(a, i + 1, right);
        
    }else
        insertionSort(a,left,right);
}

/* 驱动函数 */
void quickSort(ElemType a[],int n){
    Qsort(a, 0, n - 1);
}

int main(int argc, const char * argv[]) {
    
    int a[] = {9,3,1,4,7,6,5,8,2,10,11,13,26,26,12,23,44,55,22,12,1};
    quickSort(a, 21);
    int i = 0;
    while (i < 21)
        printf("%d ",a[i++]);
    
    
    return 0;
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值