• 排序


    排序方法:插入、选择、交换、归并、分配排序

    ![img](https://images2018.cnblogs.com/blog/1281268/201804/1281268-20180429081219550-1047189379.png)

    插入排序

    直接插入排序

    流程图:

    img

    代码实现:

    void InsertSort(int *a,int len){
        for(int i=1;i<len;i++){
            int j=i-1;
            //需要插入的数据
            int temp=a[i];
            //当插入的数据小于前面的数据时
            while(temp<a[j]&&j>=0){
                //将插入的数据的前面的数据向后移动
                a[j+1]=a[j];
                j--;
            }
            //插入数据
            a[++j]=temp;
        }
    }
    

    特点:数据有序程度越高,越有效

    适应场景:小规模数据或者基本有序时十分高效。

    希尔排序

    流程图:

    img

    代码实现:

    void shellSort(int *a,int len){
        //gap是分组步长,temp是哨兵
        int i,j,k,temp,gap;
        for(gap=len/2;gap>=1;gap/=2){
            //以gap为间隔分组
            for(i=0;i<gap;i++){
                //每一组做插入排序
                for(j=i+gap;j<length;j=j+gap){
    			   //如果当前元素比这一组中的前一个元素要小
                    if(array[j]<array[j-gap]){
    				   //记录当前这个更小的元素 temp
                        temp = array[j];    //哨兵
                        k = j - gap;
                        //把这一组中之前所有比temp小的元素都往后挪一个位置
                        while(k>=0 && array[k]>temp){
                            array[k + gap] = array[k];
                            k = k - gap;
                        }
                        //把挪出来的空位,放入temp
                        array[k + gap] = temp;
                    }
                }
            }
        }
    }
    

    交换排序

    冒泡排序

    代码实现:

    void bubbleSort(int a[], int n) {   //下面是函数bubbleSort的程序 
        //定义三个整型变量 
        int i,j,temp;   
        //用一个嵌套循环来遍历一遍每一对相邻元素 (所以冒泡函数慢嘛,时间复杂度高) 
        for (j=0;j<n-1;j++){     
            for (i=0;i<n-1-j;i++) {
                if(a[i]>a[i+1]) { //从大到小排就把左边的">"改为"<" !!!
                    temp=a[i];      //a[i]与a[i+1](即a[i]后面那个) 交换
                    a[i]=a[i+1];    //基本的交换原理"c=a;a=b;b=c" 
                    a[i+1]=temp;
                }
            }
        }    
    }
    

    快速排序(双向指针)

    流程图:8

    img

    代码实现:

    void quicksort(int left, int right) {
    	int i, j, t, temp;
    	if(left > right)
    		return;
        temp = a[left]; //temp中存的就是基准数
        i = left;
        j = right;
        while(i != j) { //顺序很重要,要先从右边开始找
        	while(a[j] >= temp && i < j)
        		j--;
        	while(a[i] <= temp && i < j)//再找右边的
        		i++;       
        	if(i < j)//交换两个数在数组中的位置
        	{
        		t = a[i];
        		a[i] = a[j];
        		a[j] = t;
        	}
        }
        //最终将基准数归位
        a[left] = a[i];
        a[i] = temp;
        quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程
        quicksort(i+1, right);//继续处理右边的 ,这里是一个递归的过程
    }
    

    选择排序

    直接选择排序

    流程图:

    img

    代码实现:

    // 选择排序:相邻两个元素进行比较,把大的元素的下标记录下来,一轮完整的比较之后,若最大值的下标不是len-i,则两个元素交换位置
    void selectSort(int arr[],int len) {
        for(int i=0; i<len; i++) { // 总共要找len-1次最大值,每次找最大值的区间 [0,len-i]
            int index_nmax = 0;
            for(int j=1; j<len-i; j++) { // 因为假设了0下标就是最大值,所以循环可以从1开始
                if(arr[j] > arr[index_nmax]){
                    index_nmax = j;
                }
            }        
            if(index_nmax != len-i-1) {// 避免无意义的位置交换
                int tmp = arr[index_nmax];
                arr[index_nmax] = arr[len-i-1];
                arr[len-i-1] = tmp;
            }
        }    
    }
    

    时间复杂度:O((n^2)) 空间复杂度:O(1)

    堆排序(大顶堆 、小顶堆 )

    利用完全二叉树的结构来维护的一维数组

    创建最大堆 :

    img

    堆排序(每次取最大值与叶子节点互换移除掉最大元素) :

    img

    归并排序

    先分后归(先拆分为一个个有序的子序列,再将一个个有序子序列进行归并操作最后合并为一个有序的序列)

    流程图:

    img

    复杂度

    算法 最好情况 平均情况 最坏情况 空间复杂度 稳定性
    归并排序 O(n log n) O(n log n) O(n log n) O(n) 稳定

    分配排序

    箱排序(桶排序)

    流程图:

    这里写图片描述

    基数排序(分配和收集 )

    (1)假设有欲排数据序列如下所示:

    73 22 93 43 55 14 28 65 39 81

    首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。

    分配结果(逻辑想象)如下图所示:

    img

    分配结束后。接下来将所有桶中所盛数据按照桶号由小到大(桶中由顶至底)依次重新收集串起来,得到如下仍然无序的数据序列:

    81 22 73 93 43 14 55 65 28 39

    接着,再进行一次分配,这次根据十位数值来分配(原理同上),分配结果(逻辑想象)如下图所示:

    img

    分配结束后。接下来再将所有桶中所盛的数据(原理同上)依次重新收集串接起来,得到如下的数据序列:

    14 22 28 39 43 55 65 73 81 93

    内部排序的方法比较

    时间复杂度

    (1)直接插入、直接选择、冒泡排序算法的时间复杂度为O((n^2))

    (2)快速、归并、堆排序算法的时间复杂度为O((nlog_{2}n))

    (3)希尔排序算法的时间复杂度很难计算:O(n(log_{2}n))或O((n^{1.25}))

    (4)基数排序算法的时间复杂度为O(d * (rd+n)),其中rd是基数,d是关键字的位数,n是元素个数。

    稳定性

    (1)直接插入、冒泡、归并和基数排序算法的稳定的。

    (2)直接选择、希尔、快速和堆排序是不稳定的。

    辅助空间

    (1)直接插入、直接选择、冒泡、希尔和堆排序算法需要辅助空间为O(1).

    (2)快速排序算法需要辅助空间为O((log_{2}n))

    (3)归并排序算法需要辅助空间为O(n)

    (4)基数排序算法需要辅助空间为O(n+rd)

  • 相关阅读:
    Ubuntu 更换软件源
    Ubuntu 配置 SOCKS5
    Ubuntu 配置 Sha-dow-socks
    frp(内网穿透)
    solr 远程代码执行(CVE-2019-12409)
    多线程处理爬虫
    python实现文件自动排序
    python 实现根据文件名自动分类移动至不同的文件夹
    Centos7如何开启任意端口服务
    centos7默认安装没有连接网络
  • 原文地址:https://www.cnblogs.com/snail-gao/p/11739690.html
Copyright © 2020-2023  润新知