Java面试宝典系列之基础排序算法
2017-03-20 17:44
316 查看
1.介绍
排序是一个在编程中间是非常基础的和重要的,网上也有很多有关排序算法的文章,再次我也是总结学习别人的知识,将别人的知识转为自己的知识,因此做此笔记,以便更好地掌握java常见排序算法。2.插入算法
2.1 基本思想每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置(从后向前找到合适位置后),直到全部插入排序完为止。
2.2 实例
2.3 算法实现
public class SortSeries { static int data[] = {57, 68, 59, 52}; public static void insertSort() { int tmp, j = 0; for (int k = 0; k < data.length; k++) { tmp = data[k]; //比较前面所有的数字,如果有大于当前数字的,那个数字就往后移一位,空出来将temp插入 for (j = k - 1; j >= 0 && tmp < data[j]; j--) { data[j + 1] = data[j]; } //因为上面最后运行了一次j--,所有下面是data[j + 1] data[j + 1] = tmp; } } static void print() { for (int i = 0; i < data.length; i++) { System.out.print(data[i] + " "); } } public static void main(String[] args) { insertSort(); print(); } }
结果:52 57 59 68
3.选择排序
3.1 基本思想与直接插入排序正好相反,选择排序是从待排序的数中选出最小的放在已经排好的后面,这个算法选数耗时。
3.2 实例
3.3 算法实现
public class SortSeries { static int data[] = {57, 68, 59, 52}; public static void selectSort() { int i = 0; int j, k, tmp = 0; for (k = 0; k < data.length - 1; k++) { //每次默认起始比较k下标就是待比较数字中最小值i的下标 i = k; //从当前数字开始比较,选择出后面数字最小的小标,存入i值 for (j = k + 1; j < data.length; j++) { if (data[j] < data[i]) { i = j; } } tmp = data[k]; //当前位置放入从当前到最末位置最小值,即进项数字交换 data[k] = data[i]; data[i] = tmp; } } static void print() { for (int i = 0; i < data.length; i++) { System.out.print(data[i] + " "); } } public static void main(String[] args) { selectSort(); print(); } }
结果:52 57 59 68
通过循环,找出最小的数的下标,赋值于i,即i永远保持待排序数据中最小的数的下标,最后和当前位置k互换数据即可。
4.快速排序
4.1 基本思想通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序。
4.2 实例
快排的思路:
设置两个指针:i和j,分别指向第一个和最后一个,i像后移动,j向前移动,选第一个数为标准(一般这样做,当然快排的关键就是这个“标准”的选取,每一轮比较这个标准值是不变的),从后面开始,找到第一个比标准小的数,互换位置,然后再从前面,找到第一个比标准大的数,互换位置,第一趟的结果就是标准左边的都小于标准,右边的都大于标准(但不一定有序),分成两拨后,继续递归的使用上述方法,最终有序!
4.3 算法实现
public class SortSeries { /** * 查找中轴(初始默认最低位作为中轴)所在位置 * @param numbers 排列数组 * @param low 最小起始下标 * @param high 最大起始下标 * @return */ public static int getMiddle(int[] numbers, int low, int high) { int temp = numbers[low]; //数组的第一个作为中轴 while (low < high) { while (low < high && numbers[high] > temp) { high--; } numbers[low] = numbers[high];//比中轴小的记录移到低端 while (low < high && numbers[low] < temp) { low++; } numbers[high] = numbers[low]; //比中轴大的记录移到高端 } numbers[low] = temp; //中轴记录到尾 return low; // 返回中轴的位置 } /** * 递归形式的分治排序算法 * @param numbers * @param low * @param high */ public static void quickSort(int[] numbers, int low, int high) { if (low < high) { int middle = getMiddle(numbers, low, high); //将numbers数组进行一分为二 quickSort(numbers, low, middle - 1); //对低字段表进行递归排序 quickSort(numbers, middle + 1, high); //对高字段表进行递归排序 } } static void print(int[] numbers) { for (int i = 0; i < numbers.length; i++) { System.out.print(numbers[i] + " "); } } public static void main(String[] args) { int[] numbers = {20, 9, 17, 33, 49, 24, 15, 56, 1}; quickSort(numbers, 0, numbers.length - 1); print(numbers); } }
结果:1 9 15 17 20 24 33 49 56
结合代码,我们分析一下一趟排序的过程,
待排列数组int[] numbers = {20, 9, 17, 33, 49, 24, 15, 56, 1}, 首先选取20作为标准,然后比较标准20跟最后一位1,20>1,交换位置:1, 9, 17, 33, 49, 24, 15, 56, 20; 然后20从左往右找出第一个比它大的值33交换位置: 1, 9, 17, 20,49, 24, 15, 56, 33; 然后20从右往左找出第一个比它小的值15交换位置: 1, 9, 17, 15,49, 24, 20, 56, 33; 然后20从左往右找出第一个比它大的值49交换位置: 1, 9, 17, 15,20, 24, 49, 56, 33; 然后20从右往左找出比它小的值,此时没有了,从左往右找比它大的值也没有了,此时第一趟结束,然后以此对1, 9, 17, 15和24, 49, 56, 33重复该过程,知道最后有序!
5.冒泡排序
5.1 基本思想冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
5.2 实例
5.3 算法实现
public class SortSeries { static int[] data = {20, 9, 17, 33, 49, 24, 15, 56, 1}; public static void bubbleSort() { int i, j, tmp = 0; for (i = 0; i < data.length - 1; i++) { for (j = data.length - 1; j > i; j--) { if (data[j - 1] > data[j]) { tmp = data[j - 1]; data[j - 1] = data[j]; data[j] = tmp; } } } } static void print() { for (int i = 0; i < data.length; i++) { System.out.print(data[i] + " "); } } public static void main(String[] args) { bubbleSort(); print(); } }
结果:1 9 15 17 20 24 33 49 56
6.希尔算法
6.1 基本思想希尔排序(缩小增量法) 属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序。希尔排序是对直接插入排序算法的优化和升级。
6.2 实例
以数组{26, 53, 67, 48, 57, 13, 48, 32, 60, 50 }为例,步长序列为{5,2,1}
6.2 算法实现
public class SortSeries { public static void shellsort(int[] data) { int j, tmp = 0; for (int increment = data.length / 2; increment > 0; increment /= 2) { System.out.println("当前步长序列increment:" + increment); for (int i = increment; i < data.length; i++) { tmp = data[i]; for (j = i - increment; j >= 0; j -= increment) { if (tmp < data[j]) { data[j + increment] = data[j]; } else { break; } } //上面循环最后减去了increment,所以此时要加上 data[j + increment] = tmp; } for (int i = 0; i < data.length; i++) { System.out.print(data[i] + " "); } System.out.println(); } } static void print(int[] data) { System.out.println("-----最终排序结果-----"); for (int i = 0; i < data.length; i++) { System.out.print(data[i] + " "); } } public static void main(String[] args) { int[] data = {26, 53, 67, 48, 57, 13, 48, 32, 60, 50}; shellsort(data); print(data); } }
结果:
当前步长序列increment:5 13 48 32 48 50 26 53 67 60 57 当前步长序列increment:2 13 26 32 48 50 48 53 57 60 67 当前步长序列increment:1 13 26 32 48 48 50 53 57 60 67 -----最终排序结果----- 13 26 32 48 48 50 53 57 60 67
7.归并排序
7.1 基本思想归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
7.2 工作原理
(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置;
(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
(4)重复步骤3直到某一指针达到序列尾;
(5)将另一序列剩下的所有元素直接复制到合并序列尾;
7.3 算法实现
public class MergeSortTest { /** * 归并排序 * * @param nums 待排序数组 * @param low * @param high * @return 输出有序数组 */ public static int[] sort(int[] nums, int low, int high) { int mid = (low + high) / 2; if (low < high) { // 左边 sort(nums, low, mid); // 右边 sort(nums, mid + 1, high); // 左右归并 merge(nums, low, mid, high); // System.out.println(Arrays.toString(nums)); } return nums; } /** * 将数组中low到high位置的数进行排序 * * @param nums 待排序数组 * @param low 待排的开始位置 * @param mid 待排中间位置 * @param high 待排结束位置 */ public static void merge(int[] nums, int low, int mid, int high) { int[] temp = new int[high - low + 1]; int i = low;// 左指针 int j = mid + 1;// 右指针 int k = 0; // 把较小的数先移到新数组中 while (i <= mid && j <= high) { if (nums[i] < nums[j]) { temp[k++] = nums[i++]; } else { temp[k++] = nums[j++]; } } // 把左边剩余的数移入数组 while (i <= mid) { temp[k++] = nums[i++]; } // 把右边边剩余的数移入数组 while (j <= high) { temp[k++] = nums[j++]; } // 把新数组中的数覆盖nums数组 for (int k2 = 0; k2 < temp.length; k2++) { nums[k2 + low] = temp[k2]; } } public static void main(String[] args) { int a[] = {51, 46, 20, 18, 65, 97, 82, 30, 77, 50}; sort(a, 0, a.length - 1); System.out.println("排序结果:" + Arrays.toString(a)); } }
结果:
排序结果:[18, 20, 30, 46, 50, 51, 65, 77, 82, 97]
8.堆排序
深入解析堆排序的算法思想及Java代码的实现演示参考文章:
Java之美[从菜鸟到高手演变]之常见的几种排序算法-插入、选择、冒泡、快排、堆排等
必须知道的八大种排序算法【java实现】(二) 选择排序,插入排序,希尔算法【详解】
【排序算法】希尔排序原理及Java实现
相关文章推荐
- Java面试宝典系列之基础排序算法
- Java面试宝典系列之基础排序算法
- Java面试宝典系列之基础排序算法
- Java面试宝典系列之基础排序算法
- Java面试宝典系列之基础排序算法
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH
- Java基础系列--基础排序算法
- C#数据结构和算法学习系列四----基础排序算法
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(二)
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(二)
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(转载)
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(二)
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH
- 数据结构与算法系列(2)基础排序算法
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(二)
- Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH
- 数据库应用基础系列