数据结构之一些常见的排序(Java)


冒泡排序

  • 算法规则: 由于算法每次都将一个最大的元素往上冒,我们可以将待排序集合(0...n)看成两部分,一部分为(k..n)的待排序unsorted集合,另一部分为(0...k)的已排序sorted集合,每一次都在unsorted集合从前往后遍历,选出一个数,如果这个数比其后面的数大,则进行交换。完成一轮之后,就肯定能将这一轮unsorted集合中最大的数移动到集合的最后,并且将这个数从unsorted中删除,移入sorted中。冒泡排序的时间复杂度为O(n^2)。

  • 代码实现(java)

public void bubbleSort(int[] data){
    //这里从数组最后面开始遍历
    for (int i = data.length - 1; i > 0; --i) {
        //在这里体现出 “将每一趟排序选出来的最大的数从sorted中移除”
        for (int j = 0; j < i; j++) {
            //保证在相邻的两个数中比较选出最大的并且进行交换(冒泡过程)
            if (data[j] > data[j + 1]) {
                int temp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = temp;
            }
        }
    }
}

并归排序

  • 算法规则: 像快速排序一样,由于归并排序也是分治算法,因此可使用分治思想:
    1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    2.设定两个指针,最初位置分别为两个已经排序序列的起始位置
    3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    4.重复步骤3直到某一指针到达序列尾
    5.将另一序列剩下的所有元素直接复制到合并序列尾
    空间复杂度为O(n),时间复杂度为O(nlogn)。
  • 代码实现(java)
public void mergeSort(int[] a, int low, int high) {
    int mid = (low + high) / 2;
    if (low < high) {
        //左边
        mergeSort(a, low, mid);
        //右边
        mergeSort(a, mid + 1, high);
        merge(a, low, mid, high);
    }
}

private void merge(int[] a, int low, int mid, int high) {
    int[] temp = new int[high - low + 1];
    //指向左边的指针
    int i = low;
    //指向右边的指针
    int j = mid + 1;
    int k = 0;
    //把较小的数先移到新数组中
    while (i <= mid && j <= high) {
        if (a[i] > a[j]) {
            temp[k++] = a[j++];
        } else {
            temp[k++] = a[i++];
        }
    }
    //左边剩余的数据加入得到新数组
    while (i <= mid) {
        temp[k++] = a[i++];
    }
    //右边剩余的数据加入到新数组
    while (j <= high) {
        temp[k++] = a[j++];
    }
    for (int l = 0; l < temp.length; l++) {
        a[l + low] = temp[l];
    }
}

快速排序

  • 算法规则: 本质来说,快速排序的过程就是不断地将无序元素集递归分割,一直到所有的分区只包含一个元素为止。
    由于快速排序是一种分治算法,我们可以用分治思想将快排分为三个步骤:
    1.分:设定一个分割值,并根据它将数据分为两部分
    2.治:分别在两部分用递归的方式,继续使用快速排序法
    3.合:对分割的部分排序直到完成
    快速排序是不稳定的,其时间平均时间复杂度是O(nlgn)。

  • 代码实现(java)

    public static int dividerAndChange(int[] args, int start, int end) {
        //参照值
        int pivot = args[start];
        while (start < end) {
            //首先从右向左查找,直到找到比参数小的第一个数,然后交换位置
            while (start < end && pivot <= args[end]) {
                end--;
            }
            if (start < end) {
                //开始交换位置
                args[start] = args[end];
                start++;
            }
            //从左往右找,找到比参数大的就交换位置
            while (start < end && pivot > args[start]) {
                start++;
            }
            if (start < end) {
                //开始交换位置
                args[end] = args[start];
                end--;
            }
        }
        args[start] = pivot;
        System.out.println("start:" + start + ",end:" + end);
        return start;
    }
    
    public static void quickSort(int[] args, int start, int end) {
        if (end - start > 1) {
            int mid = dividerAndChange(args, start, end);
            //对左边数组排序
            quickSort(args, start, mid);
            //对右边数组排序
            quickSort(args, mid + 1, end);
        }
    }

选择排序

  • 算法规则: 将待排序集合(0...n)看成两部分,在起始状态中,一部分为(k..n)的待排序unsorted集合,另一部分为(0...k)的已排序sorted集合,在待排序集合中挑选出最小元素并且记录下标i,若该下标不等于k,那么 unsorted[i] 与 sorted[k]交换 ,一直重复这个过程,直到unsorted集合中元素为空为止。选择排序的时间复杂度为O(n^2)

  • 代码实现(java)

public void selectionSort(int[] args){
    for (int i = 0; i < args.length - 1; i++) {
        int k = i;
        for (int j = k + 1; j < args.length; j++) {
            //循环遍历,找到最小值的下标
            if (args[j] < args[k]) {
                k = j;
            }
        }
        if (k != i) {
            //交换args[i]和args[k]
            int temp = args[i];
            args[i] = args[k];
            args[k] = temp;
        }
    }
}

插入排序

  • 算法规则:插入排序不是通过交换位置而是通过比较找到合适的位置插入元素来达到排序的目的的。相信大家都有过打扑克牌的经历,特别是牌数较大的。在分牌时可能要整理自己的牌,牌多的时候怎么整理呢?就是拿到一张牌,找到一个合适的位置插入。这个原理其实和插入排序是一样的。举个栗子,对5,3,8,6,4这个无序序列进行简单插入排序,首先假设第一个数的位置时正确的,想一下在拿到第一张牌的时候,没必要整理。然后3要插到5前面,把5后移一位,变成3,5,8,6,4.想一下整理牌的时候应该也是这样吧。然后8不用动,6插在8前面,8后移一位,4插在5前面,从5开始都向后移一位。注意在插入一个数的时候要保证这个数前面的数已经有序。简单插入排序的时间复杂度也是O(n^2)。
    /**
    * 插入排序
    * @param args
    * @return
    */
   public static int[] insertSort(int[] args) {
       if (args.length == 0) {
           return null;
       }

       // 默认数组的第一个数字已经排好序
       // 这里把第二个数字,作为拿来比较的数字.假设第一个数字位置已经确定.然后将二个数字和第一个数字比较
       for (int i = 1; i < args.length; i++) {
           int k = i;
           //这里将未排序的第一个数字拿出来
           int target = args[i];
           /*for (k = i - 1; k >= 0 && target < args[k]; k--) {
               args[k + 1] = args[k];
           }*/
           //这里循环比较,将未排序的第一个数和前面已排序的数组循环比较
           while (k >= 0 && target < args[k - 1]) {
               args[k] = args[k - 1];
               k--;
           }
           //这里重新设置参照值.
           args[k] = target;
       }
       return args;
   }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,170评论 0 52
  • 概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的...
    Luc_阅读 2,259评论 0 35
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,729评论 0 15
  • 前言 查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中...
    宝塔山上的猫阅读 1,082评论 1 21
  • 给家庭配置保险,怎么配置比较合适呢?针对不同年龄阶段的人,承担的家庭责任不同,配置的保险也不同。 在这里七妈得说明...
    果果希妈阅读 178评论 0 0