排序很多种,其中,七种排序是比较基本的排序方式,这七种排序分别是选择,冒泡,归并,快速,基数,插入,希尔排序。其他排序还有堆排序,桶排序,二叉树排序,图书馆排序,鸡尾酒排序等等,有兴趣的可以去研究。
一:冒泡排序
在所有的排序中,冒泡排序是最简单的,每一趟扫描都将最大值或者最小值扫描到队首/队尾,经过n趟扫描,这就可以了。这种排序的时间复杂度是O(n*n),最最理想的情况,可以达到O(1)
程序员都应该去看代码:
private static void bubbleSort(int[] a, int length) { boolean flag = true; for (int i = 0; i < length && flag; i++) { flag = false; for (int j = 0; j < length - i - 1; j++) { if (a[j] < a[j + 1]) { change(a, j + 1, j); flag = true; } } } }
代码中,change是改变数组a中两个参数的位置。这个算法需要注意的是定义一个flag标量,当已经排好序但是扫描没有完成的时候,可以提前完成,只有这样,可以将时间复杂度降低到n(1)。
二:选择排序
这中算法的思想也很简单,每一次扫描都选出将未排序的部分的最大or最小值,与预定位置相比较,其时间复杂度也为O(n*n)
代码:
private static void selectionSort(int[] a, int length) { for (int i = 0; i < length; i++) { int num = a[i]; int loc = i; for (int j = i + 1; j < length; j++) { if (a[j] > num) { num = a[j]; loc = j; } } change(a, i, loc); } }
与冒泡排序相同,也可以加入一个flag标量,这里就不详细说了。
三and四:归并排序 快速排序
归并排序与快速排序其实上是逆过程,他们都可以采用分治策略来实现。归并排序是将一个数组分为两部分,两部分分别排序好之后,然后将两个已经排序好的数组进行合并;快速排序是先将数组分为两个数组A,B,其中A中的每一个元素的数值都小于B中的元素,然后对A,B两个数组再分别进行排序,就可以了。
代码:
// 快速排序 private static void quickSort(int[] a, int i, int j) { if (i >= j) { return; } if (i + 1 == j) { if (a[i] < a[j]) { change(a, i, j); } return; } int[] first = new int[j - i + 1]; int[] last = new int[j - i + 1]; int firstNum = 0; int lastNum = 0; int sentinel = a[i]; // System.out.println(i+" "+sentinel); for (int n = i + 1; n <= j; n++) { if (a[n] > sentinel) { first[firstNum++] = a[n]; } else { last[lastNum++] = a[n]; } } for (int n = 0; n < firstNum; n++) { a[n + i] = first[n]; } a[firstNum + i] = sentinel; for (int n = 0; n < lastNum; n++) { a[n + firstNum + 1 + i] = last[n]; } quickSort(a, i, firstNum - 1 + i); quickSort(a, firstNum + 1 + i, j); } // 归并排序 private static void mergeSort(int[] a, int i, int j) { if (i >= j) { return; } if (i + 1 == j) { if (a[i] < a[j]) { change(a, i, j); } return; } int middle = (i + j) / 2; mergeSort(a, i, middle); mergeSort(a, middle + 1, j); int[] b = new int[j - i + 1]; int beforeMiddle = i; int afterMiddle = middle + 1; int bNum = 0; while (beforeMiddle <= middle && afterMiddle <= j) { if (a[beforeMiddle] > a[afterMiddle]) { b[bNum] = a[beforeMiddle]; beforeMiddle++; bNum++; } else { b[bNum] = a[afterMiddle]; afterMiddle++; bNum++; } } while (beforeMiddle <= middle) { b[bNum] = a[beforeMiddle]; bNum++; beforeMiddle++; } while (afterMiddle <= j) { b[bNum] = a[afterMiddle]; bNum++; afterMiddle++; } // print(b,0,b.length-1); for (int n = i; n <= j; n++) { a[n] = b[n - i]; } }
两种算法的时间复杂度都为O(n*log(n))
五 基数排序
基数排序是一种很有趣的排序方式,它首先将数组中元素的个位数进行排序,然后以此从十位数,百位数进行排序。这种算法很巧妙,其时间复杂度为O(k*n),非常理想是吧?
// 基数排序 private static void baseSort(int[] array, int redix, int distance) { int[] temp = new int[array.length]; int[] count = new int[redix]; int divide = 1; for (int i = 0; i < distance; i++) { System.arraycopy(array, 0, temp, 0, array.length); Arrays.fill(count, 0); for (int j = 0; j < array.length; j++) { int key = (temp[j] / divide) % redix; count[key]++; } for (int j = 1; j < redix; j++) { count[j] += count[j - 1]; } for (int j = array.length - 1; j >= 0; j--) { int key = (temp[j] / divide) % redix; count[key]--; array[count[key]] = temp[j]; } divide *= redix; } }
该方法中,redix是基数,distance是最大的位数,例如数组{66,77,9834,7812,67,8,673445},redix可以设定为10,distance为6。
六or七:插入排序和希尔排序
希尔排序是插入排序的升级版,所以先讲插入排序。有一个未排序的数组A,则新建一个数组B,B可以认定为有序的,将A中的元素依次插入到B中,那么就可以达到排序的目的。
代码:
private static void insertSort(int[] a, int length) { for(int i=1;i<a.length;i++){ int temp=a[i]; int j=i-1; while(j>=0&&a[j]>temp){ a[j+1]=a[j]; j--; } a[j+1]=temp; } }
希尔排序比这个要复杂一点,希尔排序是先设定一个步长,然后再。。。呃。。我讲不清楚,维基百科上讲的不错,我直接复制过来吧。
例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10
然后我们对每列进行排序:
10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
将上述四行数字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:
10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
排序之后变为:
10 14 13 25 23 33 27 25 59 39 65 73 45 94 82 94
最后以1步长进行排序(此时就是简单的插入排序了)。
代码如下:
//希尔排序 private static void shellSort(int[] a){ int gap=0; while(gap<a.length){ gap=gap*3+1; } while(gap>0){ for(int i=gap;i<a.length;i++){ int j=i-gap; int temp=a[i]; while(j>=0&&a[j]>temp){ a[j+gap]=a[j]; j-=gap; } a[j+gap]=temp; } gap=(gap-1)/3; } }
相关推荐
本文将详细介绍七种基本排序算法,包括插入排序、快速排序、希尔排序、归并排序、选择排序、冒泡排序(以及双向冒泡排序)和堆排序,这些都是用C语言实现的。对于初学者来说,理解和掌握这些算法有助于提升编程技能...
在本文中,我们将讨论七种使用`qsort`函数实现快速排序的方法。 1. **对整型(int)数组排序**: 当处理整型数组时,`qsort`函数需要一个比较函数`cmp`来确定元素的相对顺序。在这个例子中,`cmp`函数比较两个整数的...
本资源包含了七种经典的排序算法实现,它们分别是冒泡排序、插入排序、递归排序(这里可能是指归并排序)、基数排序、快速排序、选择排序和希尔排序。下面我们将详细探讨这些排序算法的工作原理和实现方式。 1. **...
以上就是七种基本排序算法的Python实现。在实际应用中,根据数据特性和性能需求,可以选择不同的排序算法。例如,对于大量数据,快速排序和归并排序通常表现更优;而对于小规模数据,简单排序如插入排序和选择排序...
### 七种排序方式详解及优化 #### 一、冒泡排序 冒泡排序是一种简单的排序算法,通过不断地比较相邻两个元素的值来达到排序的目的。对于数组中的每个元素,冒泡排序都会从第一个元素开始,依次比较相邻的两个元素...
本文将详细介绍标题提及的七种排序算法:冒泡排序、选择排序、快速排序、堆排序、归并排序、基数排序以及插入排序。这些排序算法各有特点,适用场景不同,理解它们的原理和实现方式对于提升编程技能和优化程序性能...
本书《更多Windows白话经典算法之七大排序第2版》是一部深入浅出讲解七种经典排序算法的著作,旨在帮助读者理解并掌握冒泡排序、直接插入排序、直接选择排序、希尔排序、归并排序、快速排序以及堆排序等基本概念和...
本文将详细探讨PHP中实现的七种基本排序算法。 首先,直接插入排序是七种排序方法中最直观的一种。算法思路是将数组分为已排序和未排序两部分,每次从未排序部分取出一个元素,插入到已排序部分的适当位置,直到...
【排序算法概述】 排序是计算机科学中的一项基本操作,它涉及将一组数据按照特定规则(通常是升序或降序)重新排列。排序算法是数据结构和算法领域的...然而,了解这些基本排序算法有助于深入理解排序过程和算法设计。
Bubble sort是一种简单的排序算法,其基本思想是通过相邻元素的比较和交换来实现排序。算法的时间复杂度为O(n^2),因此它不适合大规模数据的排序。 Bubble sort的优点是实现简单,易于理解和实现。 在上面的代码中...
《七种qsort排序方法详解》 在编程领域,排序是一项基本且重要的操作,尤其是在算法竞赛(ACM)中更是必不可少。C语言的标准库提供了一个名为`qsort`的通用排序函数,它允许用户自定义比较函数以适应各种类型的排序...
Java 版七种排序算法是计算机科学中的一种基本算法,用于对数据进行排序。排序算法的时间复杂度和空间复杂度是评估其性能的重要指标。本文将对七种常用的排序算法进行详细的介绍,包括冒泡排序、选择排序、快速排序...
七种排序算法Java版 以下是对七种排序算法Java版的详细解释: 1. 冒泡排序 冒泡排序是一种简单的排序算法,时间复杂度为O(n2),算法具有稳定性。冒泡排序的基本思想是:通过对数组的多次遍历,逐渐将最大(或最小...
这篇内部排序算法比较课程设计报告主要探讨了七种基本的内部排序算法,包括它们的原理、操作步骤以及在实际应用中的表现。以下是这七种排序算法的详细解释: 1. 冒泡排序(Bubble Sort):冒泡排序通过不断交换相邻...
以上七种排序算法各有优缺点,适用于不同的场景。在实际应用中,需要根据数据的特点选择合适的排序方法。例如,当数据规模较小时,冒泡排序和直接插入排序简单且容易实现;对于较大规模的数据,归并排序和快速排序...
C语言是一种广泛应用的编程语言,尤其适合处理底层系统级任务和算法实现。本资源提供了各种常用排序算法的C语言实现,源自严蔚敏的经典教材《数据结构》。下面将详细介绍这些排序算法及其在C语言中的实现原理。 1. ...
### 十大基本排序算法详解 #### 一、插入排序(Insertion Sort) **定义:** 插入排序是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并...
Hoare在1960年提出,是一种高效的排序算法,它的基本思想是通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分记录继续进行排序,以达到整个序列有序。...
七、堆排序 堆排序利用了堆这种数据结构,将待排序的元素构造成一个大顶堆或小顶堆,然后将堆顶元素与末尾元素交换,再调整堆。时间复杂度为O(n log n),空间复杂度为O(1)。 八、拓扑排序 拓扑排序主要用于有向无环...