七大经典排序算法,了解一下?

常见排序算法总结与实现

本文使用Java实现这几种排序。
以下是对排序算法总体的介绍。

冒泡排序

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

时间复杂度:O(n^2),最优时间复杂度:O(n),平均时间复杂度:O(n^2)

 1public static void bubbleSort(Comparable[] a) {
 2    int j, flag;
 3    Comparable temp;
 4    for (int i = 0; i < a.length; i++) {
 5        flag = 0;
 6        for (j = 1; j < a.length - i; j++) {
 7            if (a[j].compareTo(a[j - 1]) < 0) {
 8                temp = a[j];
 9                a[j] = a[j - 1];
10                a[j - 1] = temp;
11                flag = 1;
12            }
13        }
14        // 如果没有交换,代表已经排序完毕,直接返回
15        if (flag == 0) {
16            return;
17        }
18    }
19}
 

插入排序

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2~5

时间复杂度:O(n^2),最优时间复杂度:O(n),平均时间复杂度:O(n^2)

下面展示了三种插入排序的实现,第二种方法减少了交换次数,第三种采用二分查找法查到插入点。

 1public static void insertionSort(Comparable[] a) {
 2    int length = a.length;
 3    Comparable temp;
 4    for (int i = 1; i < length; i++) {
 5        for (int j = i; j > 0 && a[j].compareTo(a[j - 1]) < 0; j--) {
 6            temp = a[j];
 7            a[j] = a[j - 1];
 8            a[j - 1] = temp;
 9        }
10    }
11}
12
13// 对实现Comparable的类型进行排序,先将大的元素都向右移动,减少一半交换次数
14public static void insertionSort(Comparable[] a) {
15    int length = a.length;
16    Comparable temp;
17    int j;
18    for (int i = 1; i < length; i++) {
19        temp = a[i];
20        for (j = i; j > 0 && temp.compareTo(a[j - 1]) < 0; j--) {
21            a[j] = a[j - 1];
22        }
23        a[j] = temp;
24    }
25}
26
27// 二分插入排序,使用二分查找找到插入点,然后进行移位
28public static void insertionSort(Comparable[] a) {
29    int length = a.length;
30    Comparable temp;
31    int j;
32    for (int i = 1; i < length; i++) {
33        if (a[i].compareTo(a[i - 1]) < 0) {
34            temp = a[i];
35            int index = binarySearch(a, a[i], 0, i - 1);
36            for (j = i - 1; j >= index; j--) {
37                a[j + 1] = a[j];
38            }
39            a[index] = temp;
40        }
41    }
42}
43
44private static int binarySearch(Comparable[] a, Comparable target, int start, int end) {
45    int mid;
46    while (start <= end) {
47        mid = (start + end) >> 1;
48        if (target.compareTo(a[mid]) < 0) {
49            end = mid - 1;
50        } else {
51            start = mid + 1;
52        }
53    }
54    return start;
55}
 

选择排序

首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。

时间复杂度:O(n^2),最优时间复杂度:O(n^2),平均时间复杂度:O(n^2)

 1public static void selectionSort1(Comparable[] a) {
 2    int length = a.length;
 3    int min;
 4    Comparable temp;
 5    for (int i = 0; i < length; i++) {
 6        min = i;
 7        for (int j = i + 1; j < length; j++) {
 8            if (a[j].compareTo(a[min]) < 0) {
 9                min = j;
10            }
11        }
12        temp = a[min];
13        a[min] = a[i];
14        a[i] = temp;
15    }
16}
 

希尔排序

希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

时间复杂度:根据步长而不同,最优时间复杂度:O(n),平均时间复杂度:根据步长而不同

 1public static void shellSort(Comparable[] a) {
 2    int length = a.length;
 3    int h = 1;
 4    Comparable temp;
 5    while (h < length / 3) {
 6        h = 3 * h + 1;
 7    }
 8    while (h >= 1) {
 9        for (int i = h; i < length; i++) {
10            for (int j = i; j >= h && a[j].compareTo(a[j - h]) < 0; j -= h) {
11                temp = a[j];
12                a[j] = a[j - h];
13                a[j - h] = temp;
14            }
15        }
16        h /= 3;
17    }
18}
 

堆排序

  1. 创建最大堆(Build_Max_Heap):将堆所有数据重新排序
  2. 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

时间复杂度:O(nlogn),最优时间复杂度:O(nlogn),平均时间复杂度:O(nlogn)

 1public static void heapSort(Comparable[] a) {
 2    int length = a.length;
 3    Comparable temp;
 4    for (int k = length / 2; k >= 1; k--) {
 5        sink(a, k, length);
 6    }
 7    while (length > 0) {
 8        temp = a[0];
 9        a[0] = a[length - 1];
10        a[length - 1] = temp;
11        length--;
12        sink(a, 1, length);
13    }
14}
15
16private static void sink(Comparable[] a, int k, int n) {
17    Comparable temp;
18    while (2 * k <= n) {
19        int j = 2 * k;
20        if (j < n && a[j - 1].compareTo(a[j]) < 0) {
21            j++;
22        }
23        if (a[k - 1].compareTo(a[j - 1]) >= 0) {
24            break;
25        }
26        temp = a[k - 1];
27        a[k - 1] = a[j - 1];
28        a[j - 1] = temp;
29        k = j;
30    }
31}
 

归并排序

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

时间复杂度:O(nlogn),最优时间复杂度:O(n),平均时间复杂度:O(nlogn),空间复杂度O(n)

自顶向下的归并排序

 1private static Comparable[] aux;
 2// 自顶向下
 3public static void mergeSort(Comparable[] a) {
 4    aux = new Comparable[a.length];
 5    mergeSort(a, 0, a.length - 1);
 6}
 7
 8public static void mergeSort(Comparable[] a, int lo, int hi) {
 9    if (hi <= lo) {
10        return;
11    }
12    int mid = (lo + hi) >>> 1;
13    mergeSort(a, lo, mid);
14    mergeSort(a, mid + 1, hi);
15    merge(a, lo, mid, hi);
16}
17
18public static void merge(Comparable[] a, int lo, int mid, int hi) {
19    int i = lo, j = mid + 1;
20
21    for (int k = lo; k <= hi; k++) {
22        aux[k] = a[k];
23    }
24
25    for (int k = lo; k <= hi; k++) {
26        if (i > mid) {
27            a[k] = aux[j++];
28        } else if (j > hi) {
29            a[k] = aux[i++];
30        } else if (aux[j].compareTo(aux[i]) < 0) {
31            a[k] = aux[j++];
32        } else {
33            a[k] = aux[i++];
34        }
35    }
36}
自底向上的归并排序

 1private static Comparable[] aux;
 2
 3// 自底向上
 4public static void mergeSort(Comparable[] a) {
 5    int length = a.length;
 6    aux = new Comparable[length];
 7    for (int sz = 1; sz < length; sz = sz + sz) {
 8        for (int lo = 0; lo < length - sz; lo += sz + sz) {
 9            merge(a, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, length - 1));
10        }
11    }
12}
13
14public static void merge(Comparable[] a, int lo, int mid, int hi) {
15    int i = lo, j = mid + 1;
16
17    for (int k = lo; k <= hi; k++) {
18        aux[k] = a[k];
19    }
20
21    for (int k = lo; k <= hi; k++) {
22        if (i > mid) {
23            a[k] = aux[j++];
24        } else if (j > hi) {
25            a[k] = aux[i++];
26        } else if (aux[j].compareTo(aux[i]) < 0) {
27            a[k] = aux[j++];
28        } else {
29            a[k] = aux[i++];
30        }
31    }
32}

快速排序

  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的 摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

时间复杂度:O(n^2),最优时间复杂度:O(nlogn),平均时间复杂度:O(nlogn)
快排的时间复杂度跟选取基准的方法有关,一下是默认选择了第一个元素作为基准,随机性较大。

可以在序列中选取开始中间结尾三个数的中位数作为基准,进行优化。

 1public static void quickSort(Comparable[] a) {
 2    quickSort(a, 0, a.length - 1);
 3}
 4
 5public static void quickSort(Comparable[] a, int lo, int hi) {
 6    if (hi <= lo) {
 7        return;
 8    }
 9    int j = partition(a, lo, hi);
10    quickSort(a, lo, j - 1);
11    quickSort(a, j + 1, hi);
12}
13
14public static int partition(Comparable[] a, int lo, int hi) {
15    int i = lo, j = hi + 1;
16    Comparable temp;
17    Comparable v = a[lo];
18    while (true) {
19        while (a[++i].compareTo(v) < 0) {
20            if (i == hi) {
21                break;
22            }
23        }
24        while (v.compareTo(a[--j]) < 0) {
25            if (j == lo) {
26                break;
27            }
28        }
29        if (i >= j) {
30            break;
31        }
32        temp = a[i];
33        a[i] = a[j];
34        a[j] = temp;
35    }
36    temp = a[lo];
37    a[lo] = a[j];
38    a[j] = temp;
39    return j;
40}

---恢复内容结束---

原文地址:http://www.cnblogs.com/Tanyboye/p/9054170.html

原文地址:https://www.cnblogs.com/vlsion/p/9056989.html

时间: 2024-11-09 05:52:26

七大经典排序算法,了解一下?的相关文章

经典排序算法总结与实现 ---python

原文:http://wuchong.me/blog/2014/02/09/algorithm-sort-summary/ 经典排序算法在面试中占有很大的比重,也是基础,为了未雨绸缪,在寒假里整理并用Python实现了七大经典排序算法,包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序.希望能帮助到有需要的同学.之所以用Python实现,主要是因为它更接近伪代码,能用更少的代码实现算法,更利于理解. 本篇博客所有排序实现均默认从小到大. 一.冒泡排序 BubbleSort 介绍

【最全】经典排序算法(C语言)

本文章包括所有基本排序算法(和其中一些算法的改进算法): 直接插入排序.希尔排序.直接选择排序.堆排序.冒泡排序.快速排序.归并排序.基数排序. 算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首元素,并把它赋值给temp变量: 从排好的序列中,依次与temp进行比较,如果元素比temp大,则将元素后移(实际上放置temp的元素位置已经空出) 直到

算法系列15天速成——第三天 七大经典排序【下】

原文:算法系列15天速成--第三天 七大经典排序[下] 今天跟大家聊聊最后三种排序: 直接插入排序,希尔排序和归并排序. 直接插入排序: 这种排序其实蛮好理解的,很现实的例子就是俺们斗地主,当我们抓到一手乱牌时,我们就要按照大小梳理扑克,30秒后, 扑克梳理完毕,4条3,5条s,哇塞......  回忆一下,俺们当时是怎么梳理的. 最左一张牌是3,第二张牌是5,第三张牌又是3,赶紧插到第一张牌后面去,第四张牌又是3,大喜,赶紧插到第二张后面去, 第五张牌又是3,狂喜,哈哈,一门炮就这样产生了.

算法系列15天速成——第一天 七大经典排序【上】

原文:算法系列15天速成--第一天 七大经典排序[上] 今天是开篇,得要吹一下算法,算法就好比程序开发中的利剑,所到之处,刀起头落. 针对现实中的排序问题,算法有七把利剑可以助你马道成功. 首先排序分为四种: 交换排序: 包括冒泡排序,快速排序. 选择排序: 包括直接选择排序,堆排序. 插入排序: 包括直接插入排序,希尔排序. 合并排序: 合并排序. 那么今天我们讲的就是交换排序,我们都知道,C#类库提供的排序是快排,为了让今天玩的有意思点, 我们设计算法来跟类库提供的快排较量较量.争取KO对手

算法系列15天速成——第二天 七大经典排序【中】

原文:算法系列15天速成--第二天 七大经典排序[中] 首先感谢朋友们对第一篇文章的鼎力支持,感动中.......  今天说的是选择排序,包括“直接选择排序”和“堆排序”. 话说上次“冒泡排序”被快排虐了,而且“快排”赢得了内库的重用,众兄弟自然眼红,非要找快排一比高下. 这不今天就来了两兄弟找快排算账. 1.直接选择排序: 先上图: 说实话,直接选择排序最类似于人的本能思想,比如把大小不一的玩具让三岁小毛孩对大小排个序, 那小孩首先会在这么多玩具中找到最小的放在第一位,然后找到次小的放在第二位

经典排序算法 - 希尔排序Shell sort

经典排序算法 - 希尔排序Shell sort 希尔排序Shell Sort是基于插入排序的一种改进,同样分成两部分, 第一部分,希尔排序介绍 第二部分,如何选取关键字,选取关键字是希尔排序的关键 第一块希尔排序介绍 准备待排数组[6 2 4 1 5 9] 首先需要选取关键字,例如关键是3和1(第一步分成三组,第二步分成一组),那么待排数组分成了以下三个虚拟组: [6 1]一组 [2 5]二组 [4 9]三组 看仔细啊,不是临近的两个数字分组,而是3(分成了三组)的倍数的数字分成了一组, 就是每

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

经典排序算法

经典排序算法(via  kkun) 经典排序算法,以下文章参考了大量网上的资料,大部分都给出了出处 这一系列重点在理解,所以例子什么的都是最简单的情况,难免失误之处,多指教 大多数排序算法都给出了每一步的状态,以方便初学者更容易理解,通俗易懂,部分难以理解的排序算法则给出了大量的图示,也算是一个特色吧 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix so

C#实现所有经典排序算法

C# 实现所有经典排序算法 1 .选择排序 选择排序 原理: 选择排序是从冒泡排序演化而来的,每一轮比较得出最小的那个值,然后依次和每轮比较的第一个值进行交换. 目的:按从小到大排序. 方法:假设存在数组:72, 54, 59, 30, 31, 78, 2, 77, 82, 72 第一轮依次比较相邻两个元素,将最小的一个元素的索引和值记录下来,然后和第一个元素进行交换. 如上面的数组中,首先比较的是72,54,记录比较小的索引是54的索引1.接着比较54和59,比较小的索引还是1.直到最后得到最