数据结构—排序问题:冒泡、选择、插入、归并、快排、计数、基数(桶)

缺失:希尔排序、堆排序
优化:快速排序

待补充状态

导读
 简单算法:冒泡排序O(n2)、简单选择排序O(n2)、直接插入排序O(n2)
 改进算法:归并排序O(nlogn)、快速排序(冒泡排序优化)O(nlogn)、计数排序、基数排序或桶子法、希尔排序(插入排序优化)O(n3/2)、堆排序(选择排序优化)O(nlogn)

1. 排序问题

1.0 直接使用Arrays.sort(数组名)方法进行排序

  int[] d={123,456,19};
  Arrays.sort(d);

但有时需要我们使用算法实现,则基本排序常用方法如下:

    public static void main(String[] args) {
        int[] num = {230,229,8,0,26,25,224,223};
        bubbleSort(num);       //1.1 冒泡排序
        selectSort(num);       //1.2 选择排序
        insertSort(num);       //1.3 插入排序
        mergeSort(num);        //1.4 归并排序
        quickSort(num);        //1.5 快速排序
        Arrays.toString(num);  //打印数组
    }

1.1 冒泡排序:BubbleSort

冒泡排序主要是比较相邻的两位数字,取较大值与下一位比较,直至到最高位,完成一轮;第二轮比较至次高位,以此类推

    public static void bubbleSort(int[] num) {
        for (int i = num.length - 1,temp=0; i > 0; i--) {
            for (int j = 0; j < i; j++) {
                if (num[j] > num[j + 1]) {
                    temp = num[j];
                    num[j] = num[j + 1];
                    num[j + 1] = temp;
                }
            }
        }
    }  

1.2 选择排序:SelectSort

选择排序,首先选出最小值放在第一位;第二轮选出次小值放在第二位,以此类推

    public static void selectSort(int[]num) {
        for (int i = 0,temp=0; i < num.length-1; i++) {
            for(int j=i+1;j<num.length;j++){
                if(num[i]>num[j]){
                    temp = num[j];
                    num[j] = num[i];
                    num[i] = temp;
                }
            }
        }
    }

1.3 插入排序:InsertSort

先选定第二个数为标记数,当且仅当第一个数大于等于标记数时,才循环,交换标记数与第一个数的位置,此时设置第一个数为标记数;以此类推

    public static void insertSort(int[]num) {
        for (int i = 1,temp=0,j=0; i < num.length; i++) {
            temp=num[i];
            j=i;
            while(j>0&&num[j-1]>temp){
                num[j]=num[j-1];
                num[j-1]=temp;
                j--;
            }
        }
    }

1.4 归并排序:MergeSort

分治策略;序列一分为二,然后对子序列进行递归排序,最后合并有序子序列

    public static void mergeSort(int[]num){
            sort(num,0,num.length-1);
    }
    public static void sort(int[]num,int left,int right){
        if(left<right){
             int center=(left+right)>>1;
             sort(num,left,center);
             sort(num,center+1,right);
             merge(num,left,center,right);
        }        
    }
    public static void merge(int[]num,int left,int center,int right){
             //创建临时数组,暂存数据
        int[] tmpArr=new int[num.length];
        int third=left;
        int temp=left;
        int mid=center+1;
            //对两个子序列中取出较小的放入临时数组,直至某子序列全部放完 
        while(left<=center&&mid<=right){            
            if(num[left]<=num[mid]){
                tmpArr[third++]=num[left++]; 
            }else{
                tmpArr[third++]=num[mid++]; 
            }
        }
              //此处两个while只能运行一个
        while(mid<=right){
            tmpArr[third++]=num[mid++];
        }
        while(left<=center){
            tmpArr[third++]=num[left++];
        }
               //此处把数据从临时数组中复制回原数组
         while(temp<=right){
            num[temp]=tmpArr[temp++];
        }
    }
      

1.5 快速排序

以数组中的某位随机数为比较值key,从右、左分别向中间逼近,一次排序把小于比较值key的放在左边,大于比较值key的放在右边,然后再对两边子序列分别进行排序,以此类推

1.5.1 基本快速排序:QuickSort

以数组中的首数或尾数为比较值key:

    public static void quickSort(int[]num){
        if(num==null||num.length<=0){
            System.out.println("error data");
            return;
        }
        sort(num,0,num.length-1);
    }
    public static void sort(int[] num,int left,int right){
        if(left<right){
            int center=getMiddle(num,left,right);
            sort(num,left,center-1);
            sort(num,center+1,right);
        }
    }
    public static int getMiddle(int[] num,int left,int right){
        int tmp=num[left];
        while(left<right){
                  //两个while分别从右、左向中间逼近
            while(left<right&&tmp<=num[right]){
                right--;
            }
            if(left<right){
                num[left]=num[right];
                left++;
            }
            while(left<right&&num[left]<=tmp){
                left++;
            }
            if(left<right){
                num[right]=num[left];
                right--;
            }            
        }
        num[left]=tmp;
        return left;
    }
1.5.2 随机化快速排序:RandomQuickSort

随机设定比较值key:

    public static void randomQuickSort(int[] num) {
        if (num == null || num.length <= 0) {
            System.out.println("error data");
            return;
        }
        sort(num, 0, num.length - 1);
    }
    public static void sort(int[] num, int left, int right) {
        if (left < right) {
            int middle = randomNum(num, left, right); //内容有变动
            sort(num, left, middle - 1);
            sort(num, middle + 1, right);
        }
    }
         //新增方法
    public static int randomNum(int[] num, int left, int right) {
        //获取left与right中间的任意随机值
        int random = (int) (left + Math.random() * (right - left)); 
        int temp = num[left];
        num[left] = num[random];
        num[random] = temp;
        return getMiddle(num, left, right);
    }
    public static int getMiddle(int[] num, int left, int right) {
        int tmp = num[left];
        while (left < right) {
            while (left < right && tmp <= num[right]) {
                right--;
            }
            if (left < right) {
                num[left] = num[right];
                left++;
            }
            while (left < right && num[left] <= tmp) {
                left++;
            }
            if (left < right) {
                num[right] = num[left];
                right--;
            }
        }
        num[left] = tmp;
        return left;
    }

1.6 计数排序:CountSort

统计数组中的各数出现的次数,然后再安排先后顺序一一打印出来

    public static void countSort(int[] num) {
        if(num==null||num.length<=0){
            System.out.println("error data");
            return;
        }
        int max=0,min=0;
        for(int i=0;i<=num.length-1;i++){
            if(num[i]<min){
                min=num[i];
            }
            if(num[i]>max){
                max=num[i];
            }
        }
        int [] newNum=new int[max-min+1];
        for(int i=0;i<=num.length-1;i++){
            newNum[num[i]-min]++;
        }
        int count=0;
        for(int i=0;i<newNum.length;i++){
            while(newNum[i]>0){
                num[count++]=min+i;
                newNum[i]--;
            }
        }
    }

1.7 基数排序或桶子法:RadixSort 或 BucketSort

1.7.1 LSD法

最低位优先(Least Significant Digit first)法:先获取最高位数,然后从低向高依次排序,即个、十、百、千位···

    import java.util.List;           //导入List集合包
    import java.util.ArrayList;      //导入ArrayList包
   public static void radixSort(int[] num) {
        if (num == null || num.length <= 0) {
            System.out.println("error data");
            return;
        }
        sort(num);
    }

    public static void sort(int[] num) {
        // 计算数组中最大数k的位数time
        int k = num[0], time = 1;
        for (int i = 0; i < num.length; i++) {
            k = k < num[i] ? num[i] : k;
        }
        while (k / 10 != 0) {
            time++;
            k /= 10;
        }
        // 创建0-9个ArrayList存放数据
        List<ArrayList> queue = new ArrayList<ArrayList>();
        for (int i = 0; i < 10; i++) {
            ArrayList<Integer> queue1 = new ArrayList<Integer>();
            queue.add(queue1);
        }
        // 进行time次分配
        for (int i = 0; i < time; i++) {
            for (int j = 0; j < num.length; j++) {
                int x = num[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                ArrayList<Integer> queue2 = queue.get(x);
                queue2.add(num[j]);
                queue.set(x, queue2);
            }
            // printqueue(queue); //打印list数组
            int count = 0;
            // 收集队列元素
            for (int m = 0; m < 10; m++) {
                for (int t = 0; t < queue.get(m).size(); t++) {
                    num[count++] = (int) queue.get(m).get(t);
                }
                queue.get(m).clear();
            }
        }
    }
1.7.2 MSD法

最高位优先(Most Significant Digit first)法:先获取最高位数,然后依次从高位到低位进行排序;即···千、百、十、个位

暂时缺失


## 排序的稳定性与不变性
#### 不变性
在算法运行时保持不变的条件
#### 稳定性
如果具有相同关键字的数据项,经过排序它们的顺序保持不变,这样的排序就是稳定的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容