排序总结(java版本)
来源:互联网 发布:开源财务系统 php 编辑:程序博客网 时间:2024/06/06 01:19
本文总结的排序算法有简单选择排序、直接插入排序、冒泡排序、希尔排序、快速排序、堆排序、归并排序,桶排序,基数排序。
简单选择排序
private void selectSort(int[] nums){ for(int i = 0; i < nums.length-1; i++){ int index = i; for(int j = i+1; j < nums.length; j++){ if(nums[j] < nums[index]){ index = j; } } if(index != i){ int tmp = nums[i]; nums[i] = nums[index]; nums[index] = tmp; } } }
插入排序
private void insertSort(int[] nums){ for(int i = 0; i < nums.length-1; i++){ int index = i+1; while(index > 0 && nums[index] < nums[index-1] ){ int tmp = nums[index]; nums[index] = nums[index-1]; nums[index-1] = tmp; index--; } } }
冒泡排序
void bobbleSort(int[] nums){ for(int i = 0; i < nums.length; i++){ for(int j = 0; j < nums.length - i -1; j++){ if(nums[j] > nums[j+1]){ int tmp = nums[j]; nums[j] = nums[j+1]; nums[j+1] = tmp; } } }}
归并排序
private void mergeSort(int[] nums, int low, int high){ if(low < high){ int mid = (low + high)/2; mergeSort(nums, low, mid); mergeSort(nums, mid+1, high); merge(nums, low, mid, high); } } private void merge(int[] nums, int low, int mid, int high){ int[] tmp = new int[high-low+1]; int i = low, j = mid+1; int index = 0; while(i <= mid && j <= high){ if(nums[i] > nums[j]){ tmp[index++] = nums[j++]; }else{ tmp[index++] = nums[i++]; } } for(; i <= mid;){ tmp[index++] = nums[i++]; } for(; j <= high;){ tmp[index++] = nums[j++]; } for(int k = 0; k < tmp.length; k++){ nums[low+k] = tmp[k]; } }
快速排序
partition函数
快排里面的partition函数用来解决这样的问题:给定一个数组arr[]和数组中任意一个元素a,重排数组使得a左边都小于它,右边都不小于它。
public class Partition { public static void main(String[] args) { // TODO Auto-generated method stub Partition p = new Partition(); int[] a = {1,4,3,6,7,9,2}; System.out.println(p.partition(a,0,6,2)); for(int i : a){ System.out.print(i + " "); } } // arr[]为数组,start、end分别为数组第一个元素和最后一个元素的索引 // povitIndex为数组中任意选中的数的索引 int partition(int arr[], int start, int end, int pivotIndex) { int pivot = arr[pivotIndex]; int tmp = arr[pivotIndex]; arr[pivotIndex] = arr[end]; arr[end] = tmp; int storeIndex = start; for(int i = start; i < end; ++i) { if(arr[i] < pivot) { tmp = arr[i]; arr[i] = arr[storeIndex]; arr[storeIndex] = tmp; ++storeIndex; } } tmp = arr[storeIndex]; arr[storeIndex] = arr[end]; arr[end] = tmp; return storeIndex; }}
以上代码作为思想,改进后的快排代码:
void sort(int nums){ quickSort(nums, 0, nums.length - 1);}void quickSort(int[] nums, int low, int high){ if(low >= high){ return; } int tmp = nums[low]; int i = low; int j = high; while(i < j){ while(i < j && nums[j] >= nums[j-1]){ j--; } if(i < j){ nums[i++] = nums[j]; } while(i < j && nums[i] < nums[i+1]){ i++; } if(i < j){ nums[j--] = nums[i]; } } nums[i] = tmp; quickSort(nums, low, i-1); quickSort(nums, i+1, high);}
希尔排序
比较清晰的思路,作为算法思想的参考,可以直接跳过这个:
private void shellSort1(int[] nums)//Simple implementation { int i , j ,gap; int n = nums.length; for(gap = n/2; gap > 0; gap /= 2){ for(i = 0; i < gap; i++){ for(j = i + gap; j < n; j += gap){ if(nums[j] < nums[j-gap]){ int temp = nums[j]; int k = j - gap; while(k >= 0 && nums[k] > temp){ nums[k + gap] = nums[k]; k -= gap; } nums[k + gap] = temp; } } } } }
比较简洁的代码,还是要用三重循环实现:
private void shellSort2(int[] nums){ int gap, i, j; for(gap = nums.length/2; gap > 0; gap /= 2){ for(i = gap; i < nums.length; i++){ int temp = nums[i]; for(j = i - gap; j >= 0; j -= gap){ if(temp < nums[j]){ nums[j + gap] = nums[j]; }else{ break; } } nums[j + gap] = temp; } } }
堆排序
用数组来存储堆,下标为i的结点,父节点的编号为(i-1)/2,子结点的编号为2*i+1, 2*i+2。
建立堆:每次插入一个元素并调整堆的过程。
插入一个元素:插入到数组最后,更新堆。
删除一个元素:删除发生在nums[0],将最后一个元素调整到nums[0]处,更新堆。
堆排序:堆排序主要包括两步,一是构建堆,二是交换堆顶元素与最后一个元素的位置。
private void minHeapSort(int[] nums) { int i; int len = nums.length; for(i = len/2-1; i >= 0; i--){ adjustMinHeap(nums, i, len -1); } for(i = len-1; i >= 0; i--){ int tmp = nums[0]; nums[0] = nums[i]; nums[i] = tmp; adjustMinHeap(nums, 0, i - 1); } } private void adjustMinHeap(int[] nums, int pos, int len){ int temp; int child; for(temp = nums[pos]; 2 * pos + 1 <= len; pos = child){ child = pos * 2 + 1; if(child < len && nums[child] > nums[child + 1]){ child++; } if(nums[child] < temp){ nums[pos] = nums[child]; }else{ break; } } nums[pos] = temp; }
基数排序
参考http://blog.csdn.net/lg1259156776/article/details/48783753
以10进制排序为例,
思想:分配和收集。新建10个链表(或数组或其他容器),迭代n次(n为最大数的位数),对迭代i,将数字分配从右到左的第i位数字的桶号,最后按照顺序收集。
用链表来收集(n个),并增加指向链表的尾指针,尾指针2*r(基,此处为10),增加总的空间(n+2*r)。
一般分配代价O(n),收集代价O(r),总代价O(d(r+n))
时间复杂度,平均O(d(r+n)),最坏O(d(n+rd)),最好O(d(r+n))
空间复杂度,O(rd+n)(r代表关键字的基数,d代表长度,n代表关键字的个数)
稳定。
桶排序
建立桶,将一个数据表分到各个桶(每个桶按照分区来接收数据),对非空桶各自排序再按顺序合并。(分治)
算法性能比较
后来又添加的一些排序算法比较:
可参考常用排序算法时间复杂度和空间复杂度。
在这个表格中,n是要被排序的纪录数量以及k是不同键值的数量。
稳定的排序
冒泡排序(bubble sort)— O(n2)
鸡尾酒排序(cocktail sort)—O(n2)
插入排序(insertion sort)—O(n2)
桶排序(bucket sort)—O(n);需要O(k)额外空间
计数排序(counting sort)—O(n+k);需要O(n+k)额外空间
归并排序(merge sort)—O(n log n);需要O(n)额外空间
原地归并排序— O(n2)
二叉排序树排序(binary tree sort)— O(n log n)期望时间; O(n2)最坏时间;需要O(n)额外空间
鸽巢排序(pigeonhole sort)—O(n+k);需要O(k)额外空间
基数排序(radix sort)—O(n·k);需要O(n)额外空间
侏儒排序(gnome sort)— O(n2)
图书馆排序(library sort)— 时间复杂度通常是O(n log n),需要(1+ε)n额外空间
不稳定的排序
选择排序(selection sort)—O(n2)
希尔排序(shell sort)—O(n log2 n)如果使用最佳的现在版本
Clover排序算法(Clover sort)—O(n)期望时间,O(n^2/2)最坏情况
梳排序— O(n log n)
堆排序(heap sort)—O(n log n)
平滑排序(smooth sort)— O(n log n)
快速排序(quick sort)—O(n log n)期望时间, O(n2)最坏情况;对于大的、乱数列表一般相信是最快的已知排序
内省排序(introsort)—O(n log n)
耐心排序(patience sort)—O(n log n + k)最坏情况时间,需要额外的O(n + k)空间,也需要找到最长的递增子序列(longest increasing subsequence)
不实用的排序
Bogo排序— O(n × n!),最坏的情况下期望时间为无穷。
Stupid排序—O(n3);递归版本需要O(n2)额外存储器
珠排序(bead sort)— O(n) or O(√n),但需要特别的硬件
煎饼排序—O(n),但需要特别的硬件
臭皮匠排序(stooge sort)算法简单,但需要约n^2.7的时间
平均时间复杂度由高到低为:
冒泡排序O(n2)
选择排序O(n2)
插入排序O(n2)
希尔排序O(n1.25)
堆排序O(n log n)
归并排序O(n log n)
快速排序O(n log n)
基数排序O(n)
说明:虽然完全逆序的情况下,快速排序会降到选择排序的速度,不过从概率角度来说(参考信息学理论,和概率学),不对算法做编程上优化时,快速排序的平均速度比堆排序要快一些。
- 排序总结(java版本)
- Java版本 排序算法总结
- 排序算法(java版本)
- 基础排序算法Java版本(上)
- 选择排序java版本
- 堆排序 java版本
- 快速排序 java版本
- 桶排序java版本
- 快速排序Java版本
- java版本 堆排序
- 归并排序 --Java版本
- 快速排序 --Java版本
- java排序(数组)常用排序总结
- java排序(6):总结
- 对排序算法的一些总结(python版本)
- 归并排序 (java版本的)
- 冒泡排序优化 java版本
- 快速排序的java版本
- Android热修复之Tinker
- 购物车项目总结
- java中泛型的使用
- 简单小结一下关于JavaScript中的闭包
- adnroid.appwidget.AppWidgetProvider
- 排序总结(java版本)
- 【AngularJS】使用ng-repeat中$index的注意点
- RabbitMQ官网教程3——发布订阅
- 在(2~100)找到不大于X的最大质数
- canvas绘图详解+demo解释
- <div>/<span>/<label>标签
- 在活动中使用menu(以及简单地销毁一个活动)
- 基于spark排序的一种更廉价的实现方案-附基于spark的性能测试
- 朴素贝叶斯分类器与贝叶斯估计