各类内部排序总结

来源:互联网 发布:学编程书籍推荐 编辑:程序博客网 时间:2024/05/18 18:15
#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXN 100typedef int ElementType;#define BtCount 3//如果存在一些问题告诉我//需要排序的数组为A[MAXN],且默认按从小到大排序void Swap(ElementType *a,ElementType *b){    int tmp = (*a);    (*a) = (*b);    (*b) = tmp;}//插入排序的编写void Inserction_Sort(ElementType *A,int n){    ElementType tmp;    int i,j;    for(i=0;i<n;++i){        tmp = A[i];        for(j=i;j>0;--j){           //判断当前的tmp是否要小于A[j],且满足时,则将A[j]往后移            if(tmp<A[j-1]){                A[j] = A[j-1];            }            else break;        }        A[j] = tmp;    }}//希尔排序void Shell_Sort(ElementType *A,int n){    int i,j,inc;    ElementType tmp;    //选择增量集合为={n/2,n/4,n/8,........,1};    //注意一定要保证最小的增量为1,以保证排序有序性    for(inc = n/2;inc>=1;inc/=2){        //进行相聚为hk的元素间的插入排序        for(i=inc;i<n;++i){            tmp = A[i];            for(j=i;j>=inc;j-=inc){                if(tmp<A[j-inc]){                    A[j] = A[j-inc];                }                else break;            }            A[j] = tmp;        }    }}//建MAX堆(维护MAX堆)void GetMaxHeap(ElementType *A,int paind,int n){    //paind表示当前要维护的父亲节点下标为paind的堆    //对应的左子堆的下标    int chind;    int tmp=A[paind],i;    for(i=paind;i<=n;i = chind){       // tmp = A[i];        chind = 2*i+1;        if(chind>n)break;        //判断左儿子堆与右儿子堆的大小        if(chind+1<=n&&A[chind]<A[chind+1]){            //选取最大的作为与tmp比较            ++chind;        }        //判断当前的父堆权值与子堆权值的比较        //如果父堆权值比子堆权值大,那么当前最大堆建立结束        //否则子堆与父堆的权值进行交换,并继续        if(tmp>=A[chind])break;        else            A[i] = A[chind];    }    A[i] = tmp;}//堆排序void Heap_Sort(ElementType *A,int n){    int i;    //建MAX堆(同维护MAX堆的函数名相同),节点下标从0开始    //因为子堆与父堆之间满足,如果父堆的下标为i,那么左子堆的下标为2i+1,右子堆的下标为2i+2,且    //所以i = n/2开始主要是为了从对应子堆的父堆开始进行创建与维护    for(int i=n/2;i>=0;--i){      GetMaxHeap(A,i,n-1);    }    for(i=n-1;i>0;--i){        //头和尾进行交换,且堆于头节点进行维护        Swap(&A[0], &A[i]);        GetMaxHeap(A,0,i-1);    }}//归并排序//也是利用递归与分治思想//思想:首先我们可以将要排序的数组等分成两半,然后当左,有两边的都排完序后//我们将两个等分的数组进行合并,且有两下标Li,Ri分别对应两边,且并进行元素间的判别,//将小的先放入数组中..即可得到有序的数组void Merge(ElementType *A,int Left,int Center,int Right,ElementType *tmparr){    int i,j;    i = Left;    j = Center+1;    int pos = Left;    //合并判断谁小谁就进入tmparr数组    while(i<=Center&&j<=Right){        if(A[i]<A[j]){            tmparr[pos++] = A[i];            ++i;        }        else{            tmparr[pos++] = A[j];            ++j;        }    }    while(i<=Center){        tmparr[pos++] = A[i];        ++i;    }    while(j<=Right){        tmparr[pos++] = A[j];        ++j;    }    //将存有最小的分入到A[i]中完成合并    for(i=Left;i<=Right;++i){        A[i] = tmparr[i];    }}void MSort(ElementType *A,int Left,int Right,ElementType *tmparr){    if(Left>=Right)return;    int Center = (Left+Right)/2;    MSort(A, Left, Center,tmparr);    MSort(A, Center+1, Right,tmparr);    Merge(A,Left,Center,Right,tmparr);}//归并排序void MergeSort(ElementType *A,int n){    ElementType tmparr[MAXN];    MSort(A, 0, n-1,tmparr);}//快速排序//该函数用来对获取合适的枢纽int GetMidNumber(int L,int Mid,int R,ElementType A[]){        if(A[L]>A[Mid]){        Swap(&A[L],&A[Mid]);    }    if(A[L]>A[R]){        Swap(&A[L],&A[R]);    }    if(A[Mid]>A[R]){        Swap(&A[Mid],&A[R]);    }    //上述交换使得A[L]<A[Mid]<A[R],所以我们目标是将比A[Mid]小得放到他左边,比它大的放到它右边    Swap(&A[R-1],&A[Mid]);    //且现在将A[R-1]就是A[Mid]且现在要做得就是[L+1,R-2]的所有数进行交换    return A[R-1];}//快速排序void InsertionSort(ElementType A[],int L,int R){        int i,j,tmp;    for(i=L;i<=R;++i){        tmp = A[i];        for(j=i;j>L;--j){            if(tmp<A[j-1]){                A[j] = A[j-1];            }            else{                                break;            }        }        A[j] = tmp;    }    }void Quick_Sort(ElementType A[],int L,int R){        if(L+BtCount<=R){        int Mid = (L+R)/2;        int prov = GetMidNumber(L,Mid,R,A);        int i,j;        i = L;        j = R-1;        //对第一个左边大于等枢纽和右边的第一个小于等等于枢纽的进行交换        while(1){            while(1){                if(A[++i]>=prov){                    break;                }            }            while(1){                if(A[--j]<=prov)break;            }            if(i>j)break;            Swap(&A[i],&A[j]);        }        Swap(&A[i],&A[R-1]);        Quick_Sort(A,L,i-1);        Quick_Sort(A,i+1,R);    }    else        InsertionSort(A,L,R);}//桶排序,最简单的排序,就不敲了,说一下思路。//我们可以在创一个Map数组然后Map是记录A[i]出现的次数Map[A[i]]++;//找出a = 最大的A[i],与b = 最小的A[i]//x属于[a,b]时判断Map[x]有没有,如果右就输出Map[A[i]]个x//这样就达到了从小到大的排序//注意Ai太大时就不能用这种方法了..想想为什么void Output(int *A,int n){    int i;    for(i=0;i<n;++i){        printf("%d ",A[i]);    }    printf("\n");}int main(){    ElementType A[MAXN];    int n,i;    //输入排序数的个数    while(scanf("%d",&n)!=EOF){        for(i=0;i<n;++i){            scanf("%d",&A[i]);        }        puts("排序前:");        Output(A, n);       // Inserction_Sort(A, n);       // Shell_Sort(A, n);       // Heap_Sort(A, n);       // MergeSort(A, n);       // Quick_Sort(A, 0, n-1);        puts("排序后:");        Output(A,n);    }    return 0;}

0 0
原创粉丝点击