zoukankan      html  css  js  c++  java
  • 复习一下各种排序算法

    复习一下各种排序算法
    1.冒泡
    2.选择
    3.插入
    4.快速排序
    5.堆排序
    6.归并排序
    7.希尔排序 
    8.基数排序

    有个博客讲原理讲的挺好的:
    https://www.cnblogs.com/chengxiao/p/6104371.html

    冒泡排序 
    每次交换相邻两个元素 
    
    ------冒泡排序------
    5 8 3 4 9 6 1 2 7 0
    5 3 4 8 6 1 2 7 0 9
    3 4 5 6 1 2 7 0 8 9
    3 4 5 1 2 6 0 7 8 9
    3 4 1 2 5 0 6 7 8 9
    3 1 2 4 0 5 6 7 8 9
    1 2 3 0 4 5 6 7 8 9
    1 2 0 3 4 5 6 7 8 9
    1 0 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9
    void Sort1(int data[],int size){
        cout<<"------冒泡排序------"<<endl;
        for(int i=0;i<size-1;i++){
            Show(data);
            for(int j=0;j<size-i-1;j++){
                if(data[j]>data[j+1]){
                    int temp = data[j];
                    data[j] = data[j+1];
                    data[j+1] = temp;
                }
            }
        }
    }

    选择排序
    遍历找到未排序区最小,然后放到已排序区后面

    ------选择排序------
    5 8 3 4 9 6 1 2 7 0
    0 8 3 4 9 6 1 2 7 5
    0 1 3 4 9 6 8 2 7 5
    0 1 2 4 9 6 8 3 7 5
    0 1 2 3 9 6 8 4 7 5
    0 1 2 3 4 6 8 9 7 5
    0 1 2 3 4 5 8 9 7 6
    0 1 2 3 4 5 6 9 7 8
    0 1 2 3 4 5 6 7 9 8
    0 1 2 3 4 5 6 7 8 9

    void Sort2(int data[],int size){
        cout<<"------选择排序------"<<endl;
        for(int i=0;i<size-1;i++){
            Show(data);
            //遍历未排序,找出最小的数 
            int min=i;//min是最小的数的索引 
            for(int j=i+1;j<size;j++){
                if(data[min]>data[j]){
                    min=j;
                }
            }
            //最小数与已排区域后面第一个元素交换位置 
            Swap(data[min],data[i]); 
        }
    }

    插入排序
    每次将一个元素插入已排序区域相应位置

    ------插入排序------
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    3 5 8 4 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 6 8 9 1 2 7 0
    1 3 4 5 6 8 9 2 7 0
    1 2 3 4 5 6 8 9 7 0
    1 2 3 4 5 6 7 8 9 0
    0 1 2 3 4 5 6 7 8 9

    void Sort3(int data[],int size){
        cout<<"------插入排序------"<<endl;
        for(int i=1;i<size;i++){
            Show(data);
            int temp=data[i];
            int j=i-1;
            //把已排区域后第一个数插入到已排区域 
            //这里做了优化,交换次数少了 
            while(j>=0&&data[j]>temp){
                data[j+1]=data[j];
                j--;
            }
            data[j+1]=temp;
        }
    } 


    快速排序
    选择一个枢轴点,把小于它的放左边,大于他的放右边
    然后对左右两边继续应用快速排序

    ------快速排序------
    5 8 3 4 9 6 1 2 7 0
    0 2 3 4 1 5 6 9 7 8
    0 2 3 4 1 5 6 9 7 8
    0 1 2 4 3 5 6 9 7 8
    0 1 2 3 4 5 6 9 7 8
    0 1 2 3 4 5 6 9 7 8
    0 1 2 3 4 5 6 8 7 9
    0 1 2 3 4 5 6 7 8 9

    void Sort4fun(int data[],int left,int right){
        //当左已经大于或等于右,最多只有一个元素,不用排序了 
        if(left>=right)return;
        Show(data);
        //选择区域中第一个数作为枢轴 
        int choice = data[left];
        int i=left,j=right;
        while(i<j){
            //从右向左找比枢轴小的,保存到前面 
            while(i<j&&choice<data[j])j--;
            if(i<j){data[i]=data[j];i++;}
            
            //从左往右找比枢轴大的,保存到后面 
            while(i<j&&choice>data[i])i++;
            if(i<j){data[j]=data[i];j--;}
        }
        //最终,左右标志重合,这个位置就是枢轴存的位置 
        data[i]=choice;
        
        //对枢轴两侧的元素分别调用快速排序 
        Sort4fun(data,i+1,right);
        Sort4fun(data,left,i-1);
    }
    void Sort4(int data[],int size){
        cout<<"------快速排序------"<<endl;
        Sort4fun(data,0,size-1);
    }

    堆排序
    将数组视为完全二叉树,把他调整为一个堆,
    依次对换第一个元素和最后一个元素,并调整堆。

    ------堆排序--------
    5 8 3 4 9 6 1 2 7 0
    9 8 6 7 5 3 1 2 4 0
    8 7 6 4 5 3 1 2 0 9
    7 5 6 4 0 3 1 2 8 9
    6 5 3 4 0 2 1 7 8 9
    5 4 3 1 0 2 6 7 8 9
    4 2 3 1 0 5 6 7 8 9
    3 2 0 1 4 5 6 7 8 9
    2 1 0 3 4 5 6 7 8 9
    1 0 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9

    void Sort5fun(int data[],int target,int size){
        //调整堆 
        int left = target*2+1;
        int right = target*2+2;
        
        //如果左节点都不存在,那么它没有子节点可以直接退出 
        if(left>=size)return;
        
        //选择左右节点中最大的 
        int max = left;
        //如果没有右节点,只判断是否需要与左交换即可 
        if(right<size&&data[max]<data[right]){
            max=right;
        }
        
        //如果左右节点中最大的大于自己,交换并继续调整这个子节点 
        //否则堆已经成立,调整结束 
        if(data[max]>data[target]){
            Swap(data[max],data[target]);
        ////查看每次排序交换的元素 
        //    printf("Swap {[%d]=%d} , {[%d]=%d}
    "
        //        ,max,data[max],target,data[target]);
            Sort5fun(data,max,size);
        }
    }
    //堆其实就是一个以数组方式存储的完全二叉树 
    //对于节点i,左子节点为2*i+1,右子节点为2*i+2 
    void Sort5(int data[],int size){
        cout<<"------堆排序--------"<<endl;
        Show(data);
        //建堆 
        for(int i=size-1;i>=0;i--){
            Sort5fun(data,i,size);
        }
        
        //调整 
        for(int i=size-1;i>0;i--){
            Show(data);
            Swap(data[i],data[0]);
            Sort5fun(data,0,i);
        }
    } 

    归并排序
    把数组逐渐分解为小区间,对每两个个小区间使用
    合并有序数组算法,最终合并为一个

    ------归并排序------
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    3 5 8 4 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 1 2 6 7 0
    0 1 2 3 4 5 6 7 8 9

    void Sort6fun(int data[],int left,int right,int temp[]){
        if(left>=right)return;
        Show(data); 
        
        //将数据分为两个组 
        int mid=(left+right)/2;
        Sort6fun(data,left,mid,temp);
        Sort6fun(data,mid+1,right,temp);
        
        //执行两路归并 
        int i=left,j=mid+1,k=left;
        while(i<=mid&&j<=right){
            if(data[i]<data[j]){
                temp[k]=data[i];
                k++;i++;
            }else{
                temp[k]=data[j];
                k++;j++;
            }
        }
        //最后可能有一些数据没有加入 
        while(i<=mid){
            temp[k]=data[i];k++;i++;
        }
        while(j<=right){
            temp[k]=data[j];k++;j++;
        }
        
        //两路归并完成,数据复制到原数组中 
        k=left;
        while(k<=right){
            data[k]=temp[k];
            k++;
        }
    }
    void Sort6(int data[],int size){
        cout<<"------归并排序------"<<endl;
        int temp[size];
        Sort6fun(data,0,size-1,temp);
    }

    希尔排序
    间隔若干元素的视为一组,应用插入排序,
    然后减少间隔,直到间隔达到1
    gap为size/2,以后每次都除2

    ------希尔排序------
    5 8 3 4 9 6 1 2 7 0
    5 1 2 4 0 6 8 3 7 9
    0 1 2 3 5 4 7 6 8 9
    0 1 2 3 4 5 6 7 8 9

    void Sort7(int data[],int size){
        cout<<"------希尔排序------"<<endl;
        for(int gap=size/2;gap>0;gap/=2){
            Show(data); 
            for(int n=0;n<gap;n++){
                
                //内部为一个简单插入排序 
                for(int i=n+gap;i<size;i+=gap){
                    int j=i-gap,temp=data[i];
                    while(0<=j&&temp<data[j]){
                        data[j+gap]=data[j];
                        j-=gap;
                    }
                    data[j+gap]=temp;
                }
            }
        }
    }

    /*
    实现各种排序算法
    1.冒泡
    2.选择
    3.插入
    4.快速排序
    5.堆排序
    6.归并排序
    7.希尔排序 
    8.基数排序
    (基本是链表实现了,这里没实现) 
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    //在这里改变待待排序数据 
    int source[]={5,8,3,4,9,6,1,2,7,0};
    //每次改变数据,需要修改数据个数!!! 
    int count=10;
    
    //输出数组中全部数据 
    void Show(int data[]){
        for(int i=0;i<count;i++){
            cout<<data[i]<<" ";
        }cout<<endl;
    }
    void Copy(int data[],int target[],int size){
        for(int i=0;i<size;i++){
            target[i]=data[i];
        }
    }
    void Swap(int &a,int &b){
        int temp = a;
        a=b;b=temp;
    } 
    
    //冒泡排序 
    //每次交换相邻两个元素 
    /*
    ------冒泡排序------
    5 8 3 4 9 6 1 2 7 0
    5 3 4 8 6 1 2 7 0 9
    3 4 5 6 1 2 7 0 8 9
    3 4 5 1 2 6 0 7 8 9
    3 4 1 2 5 0 6 7 8 9
    3 1 2 4 0 5 6 7 8 9
    1 2 3 0 4 5 6 7 8 9
    1 2 0 3 4 5 6 7 8 9
    1 0 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9
    */
    void Sort1(int data[],int size){
        cout<<"------冒泡排序------"<<endl;
        for(int i=0;i<size-1;i++){
            Show(data);
            for(int j=0;j<size-i-1;j++){
                if(data[j]>data[j+1]){
                    int temp = data[j];
                    data[j] = data[j+1];
                    data[j+1] = temp;
                }
            }
        }
    }
    
    //选择排序 
    //遍历找到未排序区最小,然后放到已排序区后面 
    /*
    ------选择排序------
    5 8 3 4 9 6 1 2 7 0
    0 8 3 4 9 6 1 2 7 5
    0 1 3 4 9 6 8 2 7 5
    0 1 2 4 9 6 8 3 7 5
    0 1 2 3 9 6 8 4 7 5
    0 1 2 3 4 6 8 9 7 5
    0 1 2 3 4 5 8 9 7 6
    0 1 2 3 4 5 6 9 7 8
    0 1 2 3 4 5 6 7 9 8
    0 1 2 3 4 5 6 7 8 9
    */ 
    void Sort2(int data[],int size){
        cout<<"------选择排序------"<<endl;
        for(int i=0;i<size-1;i++){
            Show(data);
            //遍历未排序,找出最小的数 
            int min=i;//min是最小的数的索引 
            for(int j=i+1;j<size;j++){
                if(data[min]>data[j]){
                    min=j;
                }
            }
            //最小数与已排区域后面第一个元素交换位置 
            Swap(data[min],data[i]); 
        }
    }
    
    //插入排序
    //每次将一个元素插入已排序区域相应位置 
    /*
    ------插入排序------
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    3 5 8 4 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 6 8 9 1 2 7 0
    1 3 4 5 6 8 9 2 7 0
    1 2 3 4 5 6 8 9 7 0
    1 2 3 4 5 6 7 8 9 0
    0 1 2 3 4 5 6 7 8 9
    */ 
    void Sort3(int data[],int size){
        cout<<"------插入排序------"<<endl;
        for(int i=1;i<size;i++){
            Show(data);
            int temp=data[i];
            int j=i-1;
            //把已排区域后第一个数插入到已排区域 
            //这里做了优化,交换次数少了 
            while(j>=0&&data[j]>temp){
                data[j+1]=data[j];
                j--;
            }
            data[j+1]=temp;
        }
    } 
    
    
    //快速排序 
    //选择一个枢轴点,把小于它的放左边,大于他的放右边
    //然后对左右两边继续应用快速排序 
    /*
    ------快速排序------
    5 8 3 4 9 6 1 2 7 0
    0 2 3 4 1 5 6 9 7 8
    0 2 3 4 1 5 6 9 7 8
    0 1 2 4 3 5 6 9 7 8
    0 1 2 3 4 5 6 9 7 8
    0 1 2 3 4 5 6 9 7 8
    0 1 2 3 4 5 6 8 7 9
    0 1 2 3 4 5 6 7 8 9
    */ 
    void Sort4fun(int data[],int left,int right){
        //当左已经大于或等于右,最多只有一个元素,不用排序了 
        if(left>=right)return;
        Show(data);
        //选择区域中第一个数作为枢轴 
        int choice = data[left];
        int i=left,j=right;
        while(i<j){
            //从右向左找比枢轴小的,保存到前面 
            while(i<j&&choice<data[j])j--;
            if(i<j){data[i]=data[j];i++;}
            
            //从左往右找比枢轴大的,保存到后面 
            while(i<j&&choice>data[i])i++;
            if(i<j){data[j]=data[i];j--;}
        }
        //最终,左右标志重合,这个位置就是枢轴存的位置 
        data[i]=choice;
        
        //对枢轴两侧的元素分别调用快速排序 
        Sort4fun(data,i+1,right);
        Sort4fun(data,left,i-1);
    }
    void Sort4(int data[],int size){
        cout<<"------快速排序------"<<endl;
        Sort4fun(data,0,size-1);
    }
    
    //堆排序
    //将数组视为完全二叉树,把他调整为一个堆,
    //依次对换第一个元素和最后一个元素,并调整堆。 
    /*
    ------堆排序--------
    5 8 3 4 9 6 1 2 7 0
    9 8 6 7 5 3 1 2 4 0
    8 7 6 4 5 3 1 2 0 9
    7 5 6 4 0 3 1 2 8 9
    6 5 3 4 0 2 1 7 8 9
    5 4 3 1 0 2 6 7 8 9
    4 2 3 1 0 5 6 7 8 9
    3 2 0 1 4 5 6 7 8 9
    2 1 0 3 4 5 6 7 8 9
    1 0 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9
    */
    void Sort5fun(int data[],int target,int size){
        //调整堆 
        int left = target*2+1;
        int right = target*2+2;
        
        //如果左节点都不存在,那么它没有子节点可以直接退出 
        if(left>=size)return;
        
        //选择左右节点中最大的 
        int max = left;
        //如果没有右节点,只判断是否需要与左交换即可 
        if(right<size&&data[max]<data[right]){
            max=right;
        }
        
        //如果左右节点中最大的大于自己,交换并继续调整这个子节点 
        //否则堆已经成立,调整结束 
        if(data[max]>data[target]){
            Swap(data[max],data[target]);
        ////查看每次排序交换的元素 
        //    printf("Swap {[%d]=%d} , {[%d]=%d}
    "
        //        ,max,data[max],target,data[target]);
            Sort5fun(data,max,size);
        }
    }
    //堆其实就是一个以数组方式存储的完全二叉树 
    //对于节点i,左子节点为2*i+1,右子节点为2*i+2 
    void Sort5(int data[],int size){
        cout<<"------堆排序--------"<<endl;
        Show(data);
        //建堆 
        for(int i=size-1;i>=0;i--){
            Sort5fun(data,i,size);
        }
        
        //调整 
        for(int i=size-1;i>0;i--){
            Show(data);
            Swap(data[i],data[0]);
            Sort5fun(data,0,i);
        }
    } 
    
    //归并排序 
    //把数组逐渐分解为小区间,对每两个个小区间使用
    //合并有序数组算法,最终合并为一个 
    /*
    ------归并排序------
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    5 8 3 4 9 6 1 2 7 0
    3 5 8 4 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 6 1 2 7 0
    3 4 5 8 9 1 2 6 7 0
    0 1 2 3 4 5 6 7 8 9
    */ 
    void Sort6fun(int data[],int left,int right,int temp[]){
        if(left>=right)return;
        Show(data); 
        
        //将数据分为两个组 
        int mid=(left+right)/2;
        Sort6fun(data,left,mid,temp);
        Sort6fun(data,mid+1,right,temp);
        
        //执行两路归并 
        int i=left,j=mid+1,k=left;
        while(i<=mid&&j<=right){
            if(data[i]<data[j]){
                temp[k]=data[i];
                k++;i++;
            }else{
                temp[k]=data[j];
                k++;j++;
            }
        }
        //最后可能有一些数据没有加入 
        while(i<=mid){
            temp[k]=data[i];k++;i++;
        }
        while(j<=right){
            temp[k]=data[j];k++;j++;
        }
        
        //两路归并完成,数据复制到原数组中 
        k=left;
        while(k<=right){
            data[k]=temp[k];
            k++;
        }
    }
    void Sort6(int data[],int size){
        cout<<"------归并排序------"<<endl;
        int temp[size];
        Sort6fun(data,0,size-1,temp);
    }
    
    //希尔排序 
    //间隔若干元素的视为一组,应用插入排序,
    //然后减少间隔,直到间隔达到1 
    //gap为size/2,以后每次都除2 
    /*
    ------希尔排序------
    5 8 3 4 9 6 1 2 7 0
    5 1 2 4 0 6 8 3 7 9
    0 1 2 3 5 4 7 6 8 9
    0 1 2 3 4 5 6 7 8 9
    */
    void Sort7(int data[],int size){
        cout<<"------希尔排序------"<<endl;
        for(int gap=size/2;gap>0;gap/=2){
            Show(data); 
            for(int n=0;n<gap;n++){
                
                //内部为一个简单插入排序 
                for(int i=n+gap;i<size;i+=gap){
                    int j=i-gap,temp=data[i];
                    while(0<=j&&temp<data[j]){
                        data[j+gap]=data[j];
                        j-=gap;
                    }
                    data[j+gap]=temp;
                }
            }
        }
    }
    
    int main(){
        int data[count];
        
        Copy(source,data,count);
        Sort1(data,count);
        Show(data);
        
        Copy(source,data,count);
        Sort2(data,count);
        Show(data);
        
        Copy(source,data,count);
        Sort3(data,count);
        Show(data);
        
        Copy(source,data,count);
        Sort4(data,count);
        Show(data);
    
        Copy(source,data,count);
        Sort5(data,count);
        Show(data);
    
        Copy(source,data,count);
        Sort6(data,count);
        Show(data);
        
        Copy(source,data,count);
        Sort7(data,count);
        Show(data);
        
        return 0;
    } 
    View Code
  • 相关阅读:
    配置Log4j(非常具体)
    System.Net.WebClient.cs
    Code:获取指定汉字的首字母
    DBS:目录
    Jasper:推送 API
    Jasper-template
    Code:Base64 编码/解码
    DCloud-HTML5+:5+ App开发入门指南
    DCloud-HTML5+:barcode
    Nuget-QRCode:QRCoder
  • 原文地址:https://www.cnblogs.com/Wonder007/p/12577328.html
Copyright © 2011-2022 走看看