直接插入、冒泡、快速、简单选择、堆、归并排序算法Java语言
2017-02-28 18:47
441 查看
一、直接插入
第i趟直接插入排序的操作为:在含有i-1个记录的有序子序列r[1...i-1]中插入一个记录r[i]后,变成含有i个记录的有序子序列[1..i];为了避免数组下标出界,在r[0]处设置监视哨。如第一趟排序为:将序列中的第1个记录看成是一个有序的子序列,然后从第2个记录起逐个进行插入,直到整个序列变成按关键字非递减有序序列为止。下面是第一趟排序的图:public void insertionSort( int[] arr) { int guide = 0; for ( int i = 1; i < arr. length; i++) { if ( arr[ i] < arr[ i - 1]) { guide = arr[ i]; arr[ i] = arr[ i - 1]; int j = i - 1; while ( j >= 0 && guide < arr[ j]) { arr[ j + 1] = arr[ j]; j--; } arr[ j+1] = guide; } } }
二、冒泡排序
第i趟冒泡排序是从r[1]到r[n-i+1]依次比较相邻两个记录的关键字,并在“逆序”时交换相邻记录,其结果是这n-i+1个记录中关键字最大的记录被交换到第n-i+1的位置上。下面为第一趟排序的示意图:public void bubbleSort( int[] arr) { for ( int i = arr. length - 1; i >= 1; i--) { for ( int j = 1; j <= i; j++) { if ( arr[ j - 1] > arr[ j]) { int temp = arr[ j]; arr[ j] = arr[ j - 1]; arr[ j - 1] = temp; } } } }
三、快速排序
它的一趟操作为:附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey(可以直接取数组的中间 值和下标),则首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录互相交换,然后从low所指位置起向后搜索,找到第一个关键字大于pivotkey的记录和枢轴记录互相交换,重复这两步直至low=high为止。第一趟的示意图如下:public void quickSort( int[] arr, int low, int high) { if ( arr. length < 2 || low >= high) { return; } if ( low < high) { int pivotloc = partition( arr, low, high); quickSort( arr, low, pivotloc - 1); quickSort( arr, pivotloc + 1, high); } } public int partition (int [] arr , int low, int high) { if ( arr. length < 2) { return 0; } int pivotkey; pivotkey = arr[ low]; while ( low < high) { while ( low < high && arr[ high] >= pivotkey) { high--; } arr[ low] = arr[ high]; while ( low < high && arr[ low] <= pivotkey) { low++; } arr[ high] = arr[ low]; } arr[ low] = pivotkey; return low; }
四、简单选择
一趟简单选择排序的操作为:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之。(i指趟数,n指数组长度)。完整的例子如下图:public void selectionSort( int[] arr) { for ( int i = 0; i < arr. length - 1; i++) { int minIndex = i; for ( int j = i + 1; j < arr. length; j++) { if ( arr[ j] < arr[ minIndex]) { minIndex = j; } } if ( i != minIndex) { int temp = arr[ minIndex]; arr[ minIndex] = arr[ i]; arr[ i] = temp; } } }
五、堆排序
堆是指:完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。堆排序是指:在输出堆顶的最小(大)值后,使得剩余n-1个元素的序列重新建成一个小(大)顶堆,则得到n个元素中的次小( 大)值。如此反复执行,便能得到一个有序序列。算法的大致过程(大顶堆为例):输出堆顶的元素后,以堆中最后一个元素替代之。此时根结点的左、右子树均为堆,则仅需自上而下进行调整即可。首先以堆顶元素和其左、右子树根结点的值比较之,将较大的根结点的值与堆顶交换;这时被交换的结点的树的堆结构被破坏,需再将该结点与其左、右子树根结点的值比较之,将较大的根结点的值与它交换,以此类推重新建成堆。自己根据书本的内容介绍用Java语言实现:
public void heapSort( int[] arr) { for ( int i = arr. length / 2; i > 0; -- i) { heapAdjust( arr, i, arr. length); } for ( int i = arr. length; i > 1; -- i) { swap( arr, 1 - 1, i - 1); //逻辑堆的下标和实际数组的下标错开1个单位,即堆顶与堆末交换 heapAdjust( arr, 1, i - 1); } } /** * 此方法是根据堆的逻辑来处理数组的,而堆的最小值为1,最大值应该是要处理的数组的长度length; * 然而数组的下标最小为0,最大为length -1,所以方法中将逻辑堆的下标和实际数组的下标错开1个单位; * 因此 arr数组取值时,都要将堆计算时的下标数减1 * @param arr 要处理成符合大顶堆的数组 * @param s 要处理处的开始下标 * @param m 结束下标 */ public void heapAdjust( int[] arr, int s, int m) { int rc = arr[ s-1]; for ( int j = 2 * s; j <= m; j *= 2) { if ( j < m && arr[ j-1] < arr[ j ]) { ++ j; } if ( rc >= arr[ j-1]) { break; } arr[ s-1] = arr[ j-1]; s = j; } arr[ s-1] = rc; }
下面根据网上的JavaScript代码写的:
int len; public void buildMaxHeap( int[] arr) { // create a big heap len = arr. length; int i = new Double(Math. floor( len/2)).intValue(); System. out.println( "buildMaxHeap's i=" + i ); for (; i >= 0; i--) { heapify( arr, i); } } public void heapify( int[] arr, int i) { // adjust the heap int left = 2 * i + 1, right = 2 * i + 2, largest = i; if ( left < len && arr[ left] > arr[ largest]) { largest = left; } if ( right < len && arr[ right] > arr[ largest]) { largest = right; } if ( largest != i) { swap( arr, i, largest); heapify( arr, largest); } } public void swap( int[] arr, int i, int j) { int temp = arr[ i]; arr[ i] = arr[ j]; arr[ j] = temp; } public int[] heapSort( int[] arr) { buildMaxHeap( arr); for ( int i = arr. length-1; i > 0; i--) { swap( arr, 0, i); len--; heapify( arr, 0); } return arr; }
六、归并排序
归并排序的理念是:假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再再两两归并,....如此重复下去即可。public int [] mergeSort (int [] arr ) {//sort a array int len = arr. length; if ( len < 2) { return arr; } int middle = len / 2; int[] left = Arrays. copyOfRange( arr, 0, middle); int[] right = Arrays. copyOfRange( arr, middle, len); return merge( mergeSort( left), mergeSort (right )); } public int[] merge( int[] left, int[] right) { //merge two regular arrays into one regular array int j, i, k = 0; int m = left. length; int n = right. length; int result[] = new int[ left. length + right. length] ; for ( j = 0, i = 0; i < m && j < n; k++) { if ( left[ i] < right[ j]) { result[ k] = left[ i]; i++; } else { result[ k] = right[ j]; j++; } } while ( i < m) { result[ k++] = left[ i++]; } while ( j < n) { result[ k++] = right[ j++]; } return result; }
参考《数据结构C语言版》,文字描述基本摘自书中,能保持原汁原味。图片是为了让以后复习时能更快熟悉而从百度上获取的,如有侵权,请联系我。谢谢
相关文章推荐
- 直接插入、冒泡、快速、简单选择、堆、归并排序算法
- C语言实现 排序源程序(包括直接插入、希尔、冒泡、快速、简单选择、堆排序)
- 六、内部排序综合(九种)—插入类排序(直接插入、折半插入、希尔排序);交换类排序(冒泡、快速);选择类排序(简单选择、堆排序);二路归并排序;基数排序
- 常用的排序算法:冒泡,简单选择,直接插入,快速排序,堆排序
- 排序算法总结与C++实现(冒泡、简单选择、直接插入、堆、归并、快速)
- (数据结构排序的实验四)快速,冒泡,简单选择,直接插入排序的c语言实现!!
- 数据结构排序(简单易懂口语化)--冒泡,快速,直接插入,希尔,直接选择,堆,归并,基数
- 八大内部排序算法(上)-冒泡、直接插入、简单选择、快速
- C语言实现 排序源程序(包括直接插入、希尔、冒泡、快速、简单选择、堆排序)
- 从零开始_学_数据结构(六)——排序(冒泡、插入、希尔、简单选择、归并、快速)
- 冒泡,插入,折半插入,希尔,快速,简单选择排序的源代码总结
- 常见排序算法C++实现(冒泡,直接插入,希尔,堆,归并,简单选择,快排)
- 冒泡,插入,折半插入,希尔,快速,简单选择排序的源代码总结
- 六种排序方法的学习(直接插入、希尔、冒泡、快速、选择、归并)
- 七种排序(直接插入、折半插入、希尔、起泡、快速、简单选择、堆排序)
- 排序总结:插入(简单和改进)、希尔、选择、冒泡、快速、堆排序、归并排序
- 冒泡、简单选择、快速插入排序回顾(待续)
- 冒泡、快速、直接插入、选择排序算法(Java语言实现)
- 001-简单的java代码实现几种排序算法(插入,快速,冒泡,选择)
- 排序大全【各种排序】:直接插入,折半插入,冒泡,快排,简单选择,堆排序,归并排序