zoukankan      html  css  js  c++  java
  • 排序大法

    关于学习排序相关知识点总结:

      一方面用于巩固,另一方面也是对自己的一个检测。

      代码纯手敲,自己检验了下,结果也都正确。

      弱鸡一只,只能叫,不能跑。如果有错误,或者建议,希望大佬斧正指点。

    ~~~首先当然是冒泡了,其实冒泡排序应该叫沉底排序,但是当时发明冒泡排序的人可能不会沉底这个英语单词,就这能冒泡了吧!这渣渣的英语水平和我差不多,哈哈哈哈。。。

    废话不说,直接上代码:

    #include<bits/stdc++.h>
    //#include<cstdio>
    using namespace std;
    const int MAXN=1010;
    int a[MAXN];
    
    void BubbleSort(int a[], int n)
    {
        for(int i=1; i<n; i++ ){
            for( int j=n; j>=1; j-- ){
                if(a[j-1]>a[j]){
                    int k=a[j-1];
                    a[j-1]=a[j];
                    a[j]=k;
                }
            }
        }
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for( int i=1; i<=n; i++ ){
            scanf("%d",&a[i]);
        }
        BubbleSort(a,n);
        for( int i=1; i<=n; i++){
            printf("%d%c",a[i],i==n?'
    ':' ');
        }
        return 0;
    }
    废话不多说了,选择排序一起出来吧!!!
    #include<bits/stdc++.h>
    //#include<cstdio>
    using namespace std;
    const int MAXN=1010;
    int a[MAXN];
    
    void SelectSort(int a[], int n)
    {
        for(int i=1; i<n; i++ ){
            int flag=i;//设立哨兵
            for( int j=i+1; j<=n; j++  ){
                if(a[j]<a[i]){
                    flag=j;
                }
            }
            if(flag!=i){
                int k =a[i];
                a[i]=a[flag];
                a[flag]=k;
            }
        }
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for( int i=1; i<=n; i++ ){
            scanf("%d",&a[i]);
        }
        SelectSort(a,n);
        for( int i=1; i<=n; i++){
            printf("%d%c",a[i],i==n?'
    ':' ');
        }
        return 0;
    }

      接下来说说归并排序,个人感觉,归并还是非常牛逼的一个排序方法

      他的最好最坏时间复杂度都是O(nlogn),空间复杂度是O(n),还TM稳定。这就是排序比排序,气死排序。

      归并排序:是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。

      将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=1010;
    int num[MAXN];
    
    
    void merge(int a[], int first, int mid, int last)//归并有序代码段
    {
        int i=first,j=mid+1,m=mid,n=last;
        int l=m-i;
        int k=0;
        int temp[MAXN];
        while(i<=m&&j<=n){
            if(a[i]<a[j]){
                temp[k++]=a[i++];
            }
            else{
                temp[k++]=a[j++];
            }
        }
        while(i<=m){
            temp[k++]=a[i++];
        }
        while(j<=m){
            temp[k++]=a[j++];
        }
        for( int i=0; i<k; i++ ){
            a[first+i]=temp[i];
        }
    }
    void mergesort(int a[], int first, int last)//分段有序代码段
    {
        if(first<last){
            int mid=(first+last)/2;
            mergesort(a,first,mid);//左边有序
            mergesort(a,mid+1,last);//右边有序
            merge(a,first,mid,last);//合并有序
        }
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for( int i=1; i<=n; i++ ){
            scanf("%d",&num[i]);
        }
        mergesort(num,1,n);
        for( int i=1; i<=n; i++ ){
            printf("%d%c",num[i],i==n?'
    ':' ');
        }
    
        return 0;
    }

     另外说说希尔排序,原来我一直一位希尔排序也叫哈希排序,就像一个人的小名似的,但是现实往往是残酷的,Oh,Mygod!

    希尔排序:该方法实质上是一种分组插入方法 比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比[2] 较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。 一般的初次取序列的一半为增量,以后每次减半,直到增量为1。 给定实例的shell排序的排序过程 假设待排序文件有10个记录,其关键字分别是: 49,38,65,97,76,13,27,49,55,04。 增量序列的取值依次为: 5,3,1

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int MAXN=101;
    int num[MAXN];
    void shell_sort(int *data,int len)
    {
        if(len<1||data==NULL){
            return ;
        }
    //    for( int div=len/2; div>=1; div=div/2)//定量div
    //    {
    //        for( int i=0; i<=div; i++ ){//分成div组
    //            for(int j=i;j<len-div;j+=div) //对每组进行插入排序
    //            for(int k=j;k<len;k+=div)
    //            if(data[j]>data[k])
    //            swap(*(data+j),*(data+k));       //交换两个数的值
    //        }
    //    }
        int div=len/2;
        do{
            for( int i=0; i<=div; i++ ){//分成divfor( int j=i;j<len-div; j+=div ){//对每组进行div排序
                    for( int k=j; k<len; k+=div ){
                        if(data[j]>data[k]){
                            swap(*(data+j),*(data+k));
                        }
                    }
                }
            }
            div=div/2;
       }while(div>=1);
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for( int i=0; i<n; i++ ){
            scanf("%d",&num[i]);
        }
        shell_sort(num,n);
        for( int i=0; i<n; i++ )
        {
            printf("%d%c",num[i],i==n-1?'
    ':' ');
        }
        return 0;
    }
    

     接下来说说快排,总体来说,快排还是很不错的排序,只不过他有一点臭毛病,有时候很快,有时候是真的慢,或许还赶不上冒泡,平均时间复杂度O(nlogn),这个还是不错的,不稳定,另外说说他的臭毛病,正序和逆序的时候他的臭毛病就出来了,时间复杂度都O(n^2)了,有辅助栈,空间复杂度最坏为O(n),值得一提的是,在快排时枢纽的选择直接影响快排的效率,当选择枢纽为素数时性能会更好。

    上代码:

    #include<bits/stdc++.h>
    //#include<cstdio>
    using namespace std;
    const int MAXN=1010;
    int a[MAXN];
    
    void QuickSort(int first, int last)
    {
        int i=first,j=last,temp;
        if(first>last){
            return ;
        }
        temp=a[first];//temp存储基准枢纽
        while(i<j){
            while(a[j]>=temp&&i<j){//先找右边的
                j--;
            }
            while(a[i]<=temp&&i<j){//在找左边的
                i++;
            }
            if(i<j){
                int k=a[i];
                a[i]=a[j];
                a[j]=k;
            }
        }
        a[first]=a[i];
        a[i]=temp;
    
        QuickSort(first,i-1);
        QuickSort(i+1,last);
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for( int i=1; i<=n; i++ ){
            scanf("%d",&a[i]);
        }
        QuickSort(1,n);
        for( int i=1; i<=n; i++){
            printf("%d%c",a[i],i==n?'
    ':' ');
        }
        return 0;
    }
    关于堆排序:这涉及到一些堆的知识,像最大堆,最小堆,大家可以自己百度下。。。
    啊啊啊啊,你们都会,就我不会,让我伤心一会。
    这个代码是当时做PTA遇到的一道题,就像用堆排序跑一边,
    于是查阅了各种资料,改了无数的bug,才写出来,至今印象深刻啊!!!
    #include<bits/stdc++.h>
    using namespace std;
    #define MAXSIZE 100010
    
    typedef long ElementType;
    typedef struct TNode *Position;
    typedef Position BinTree;
    struct TNode {
        ElementType Data;
        BinTree Left;
        BinTree Right;
    };
    
    BinTree Insert(BinTree,ElementType);
    void InorderTraversal(BinTree);
    
    int main(){
        int n;
        scanf("%d",&n);
        BinTree B=NULL;
        long num;
    for(int i=0;i<n;i++){
        scanf("%ld",&num);
        B=Insert(B,num);
    }
    
    InorderTraversal(B);
    
    
        return 0;
    }
    BinTree Insert( BinTree BST, ElementType X ) { //二分生长树
    
        BinTree NewT=(BinTree)malloc(sizeof(struct TNode));
        NewT->Data=X;
        NewT->Left=NULL;
        NewT->Right=NULL;
    
        BinTree head=BST;
        while(BST) {
            if(BST->Data>=X) {
                if(BST->Left)BST=BST->Left;
                else {//相同的树将其插入左子树,为左子树的最右结点
                    BST->Left=NewT;
                    return head;
                }
            } else {
                if(BST->Right)BST=BST->Right;
                else {
                    BST->Right=NewT;
                    return head;
                }
            }
        }
        return NewT;//若为空树 则新建
    }
    void InorderTraversal( BinTree BT ) {
    static char flag=0;
        if(BT) {
            InorderTraversal(BT->Left);
            if(flag)printf(" ");else flag=1;
            printf("%d",BT->Data);
            InorderTraversal(BT->Right);
        }
    
    }
    下面总结一下:

    直接插入排序正序时最好时间复杂度O(n),逆序最坏O(n2),平均O(n2),空间复杂度O(1);稳定;原始序列基本有序时该方法好


    折半插入排序T(n)=O(n2),原本有序无序均如此,最好O(NLogN) S(n)=O(1);稳定


    希尔排序(缩小增量排序):平均时间复杂度O(n1.x),S(n)=O(1);不稳定


    冒泡排序(改进)正序时间复杂度最好O(n),逆序最坏O(n2),平均O(n2),S(n)=O(1); 稳定


    快速排序平均时间复杂度O(nlogn),平均性能最优,正序或逆序最坏O(n2), 有辅助栈,空间复杂度最坏O(n),平均O(logn);不稳定. 枢轴改进


    选择排序复杂度T(n)=O(n2),原本有序无序均如此,S(n)=O(1);稳定


    堆排序T(n)=O(nlogn),S(n)=O(1);不稳定(因为间隔着比和移动)


    归并排序最好最坏复杂度为O(nlogn),空间复杂度O(n),稳定


    链式基数排序最好最坏时间复杂度为O(d*(n+ rd )),空间O(rd),稳定


    内部排序方法分类:复杂度O(n2)的简单排序方法,O(nlogn)的高效排序方法(比较法的理论下界),O(d*(n+rd))的基数排序方法.

    在学习排序这一章的时候,印象很深刻,也悟出了一个道理,思想啊 ,思想很重要,学习就是学习思想的过程,只要思想理解了,代码就好敲了,脑海中的印象也深

    ,更不容易忘。

    题后话:如果有人能够光临寒舍,看到我的这一篇开头博客,哈哈哈,大家一定要给我指点一下哈,哇,谢大佬!!!

    有些目标看似很遥远,但只要付出足够多的努力,这一切总有可能实现!!!拜托诸位,为了不辜负以前经历过的困难,为了自己的努力,也为了将来遇见更好的自己,请坚守自己的初心!!!
    有些目标看似很遥远,但只要付出足够多的努力,这一切总有可能实现!
  • 相关阅读:
    Thinkphp各种方法知识图谱
    Yii2.0学习笔记:创建登录表单
    Yii2.0学习笔记:第一个页面Saying Hello
    4.1
    4
    flask(3.0)
    flask(2.0)
    flask(1.1)装饰器装饰多个视图函数出现的问题
    flask(1.0)
    Flask之上下文管理机制
  • 原文地址:https://www.cnblogs.com/Bravewtz/p/10041029.html
Copyright © 2011-2022 走看看