Java关于排序的介绍3-高级排序
2016-03-04 09:53
531 查看
本篇博客主要是介绍-希尔排序和快速排序
希尔排序
希尔排序是基于插入排序(关于插入排序的介绍请查看简单排序)。
希尔排序主要是解决了插入排序复制次数太多的问题。例如对一个序列进行从小到大的排序,如果有一个很小的数据在序列的末尾,那么当对该数据进行操作的时候,他左边已经有序的数据需要进行大量的进行右移复制操作。希尔排序会选择一个合理的间隔,开始进行排序,这样实现了数据的大跨度移动,就避免了大量数据的复制操作。
关键点间隔(h)的计算
这个地方不做详细介绍,感兴趣的同学请自行查看相关书籍
- java数据结构和算法
- 算法
这里使用 h=3*h+1 来计算间隔
下面看代码
快速排序
快速排序的一个关键理解点是划分算法,还有要注意关键字的选择
下面看代码
其中divide就是实现了划分的方法
关于特定值的选择,本例是用每次划分的最后一个元素作为特定值,也有使用从第一个数、中间的一个数、末尾的一个数取一个中间的数作为特定值的。
关于排序的介绍系列博客就结束,在博客的结尾给出关于各个排序的时间复杂度
简单排序 - O(N^2)
归并排序 - O(N*logN)
希尔排序 - O(N*(logN)^2)
快速拍戏 - O(N*logN)
简单排序里面虽然时间复杂度都一样,但是一般情况下
冒泡 > 选择 > 插入
冒泡每次比较以后都需要进行数据交换操作。
归并排序的缺点需要新开辟一个与被排序的数组等大的数组空间。
希尔排序是基于插入排序的主要是减少数据复制次数,实现了数据的大跨度移动。
希尔排序
希尔排序是基于插入排序(关于插入排序的介绍请查看简单排序)。
希尔排序主要是解决了插入排序复制次数太多的问题。例如对一个序列进行从小到大的排序,如果有一个很小的数据在序列的末尾,那么当对该数据进行操作的时候,他左边已经有序的数据需要进行大量的进行右移复制操作。希尔排序会选择一个合理的间隔,开始进行排序,这样实现了数据的大跨度移动,就避免了大量数据的复制操作。
关键点间隔(h)的计算
这个地方不做详细介绍,感兴趣的同学请自行查看相关书籍
- java数据结构和算法
- 算法
这里使用 h=3*h+1 来计算间隔
下面看代码
public static void sort(int arr[]) { int size = arr.length; // 获取数组大小 int h = 1; // 间隔 // 计算间隔 while (h < size / 3) { h = h * 3 + 1; } while (h > 0) { // 对h间隔组成的数据进行排序 for (int i = h; i < size; i++) { int j = i; int temp = arr[i]; // 进行判断 将比当前位置大的数据进行移动 while (j > h - 1 && arr[j - h] > temp) { arr[j] = arr[j - h]; j -= h; } arr[j] = temp; // 将当前这次排序的标记数据进行移动 } h = (h - 1) / 3; // 修改间隔 } }
快速排序
快速排序的一个关键理解点是划分算法,还有要注意关键字的选择
下面看代码
/** * 排序 * @param arrs 数组 * @param left 左边边界 * @param right 右边边界 */ public static void sort(int arrs[], int left, int right) { if (left >= right) { return; } int x = arrs[right]; // 选取特定值 选择每一组里面的最后一个元素作为特定值 int leftPtr = divide(arrs, x, left, right); // 进行一次划分 结果 特定值左边都是小于特定值的数,特定值右边的都是大于特定值的数 // 再次进行排序 不必要在对上次特定值进行处理 sort(arrs, left, leftPtr - 1); sort(arrs, leftPtr + 1, right); } /** * 划分 * @param arrs 数组 * @param x 特定值 * @param left 左边边界 * @param right 右边边界 * @return 特定值的位置 */ private static int divide(int arrs[], int x, int left, int right) { int leftPtr = left - 1; int rightPtr = right; while (true) { while (arrs[++leftPtr] > x);// 从左边第一个元素开始,顺序查找到第一个比特定值大的数 while (rightPtr > 0 && arrs[--rightPtr] < x); // 从倒数第二个元素开始,顺序查找到第一个比特定值小的数 if (leftPtr >= rightPtr) { // 已经划分完成 break; } // 进行交换 swap(arrs, leftPtr, rightPtr); } // 交换特定值到合适的位置 swap(arrs, leftPtr, right); return leftPtr; } /** * 交换数组里面俩个位置的值 * arrs 数据源 * leftPtr 左边索引 * rightPtr 右边的索引 */ private static void swap(int[] arrs, int leftPtr, int rightPtr) { int temp = arrs[leftPtr]; arrs[leftPtr] = arrs[rightPtr]; arrs[rightPtr] = temp; }
其中divide就是实现了划分的方法
关于特定值的选择,本例是用每次划分的最后一个元素作为特定值,也有使用从第一个数、中间的一个数、末尾的一个数取一个中间的数作为特定值的。
关于排序的介绍系列博客就结束,在博客的结尾给出关于各个排序的时间复杂度
简单排序 - O(N^2)
归并排序 - O(N*logN)
希尔排序 - O(N*(logN)^2)
快速拍戏 - O(N*logN)
简单排序里面虽然时间复杂度都一样,但是一般情况下
冒泡 > 选择 > 插入
冒泡每次比较以后都需要进行数据交换操作。
归并排序的缺点需要新开辟一个与被排序的数组等大的数组空间。
希尔排序是基于插入排序的主要是减少数据复制次数,实现了数据的大跨度移动。
相关文章推荐
- Javassist简单应用小结
- JAVA CAS原理深度分析
- eclipse EasyExplore插件安装
- Spring Bean 生命周期2
- Eclipse配置信息
- JavaBean
- java中dynamic web project与web project 的区别
- 深入分析Java ClassLoader原理
- 简单模拟spring装载注入bean原理
- 【Javaweb】Eclipse for JavaEE新建的Web工程自动生成web.xml
- Spring MVC之@RequestParam @RequestBody @RequestHeader 等详解
- Java读取UTF-8格式txt文件第一行出现乱码——问号“?”及解决
- Pojo和JavaBean的区别
- Java运算符
- JNI中C调用Java方法
- LintCode 最大数
- JavaBean,POJO,VO,DTO的区别和联系
- Java--容器(Collection)(一)
- Leetcode:198. House Robber(JAVA)
- JAVA SDutOJ 题目收录