算法——快速排序迭代式和递归式的Java实现
快速排序迭代式和递归式的Java实现
快速排序基于分治法的思想,在待排序表中任选一值作为中枢值 pivot,一趟快排将所有大于该值的元素置于一边,小于该值的元素置于另一边,这样一个元素在排序中的最终位置就已确定。接下来将中枢值左右两边的区域分别进行下一趟快排,直到所有的元素都有序排列。
空间效率:最好情况为 O(log2(n+1)),最坏情况为 O(n),平均空间复杂度 O(log2(n))。
时间效率:最好情况为 O(n*log2(n)),最坏情况 O(n^2),平均时间复杂度 O(n*log2(n))。
快速排序是所有内部排序中平均性能最优的算法,同时也是一个不稳定的排序算法。
递归式
1 public class Test { 2 3 public static void main(String[] args) { 4 5 int[] nums = {2, 12, 32, 32, 43, 5, 74, 13, 87, 12, 44, 2, 41, 5, 33}; 6 7 recursiveQuicksort(nums,0,nums.length-1); 8 9 System.out.println("Sorted array : " + Arrays.toString(nums)); 10 11 } 12 13 //recursiveQuicksort(int[] 被排序数组, int 数组下界, int 数组上界) 14 private static void recursiveQuicksort(int[] nums, int low, int high) { 15 16 if(low < high){ 17 18 int pivotpos = partition(nums, low, high); 19 20 recursiveQuicksort(nums, low, pivotpos -1); 21 recursiveQuicksort(nums, pivotpos + 1, high); 22 23 } 24 } 25 26 private static int partition(int[] nums, int low, int high) { 27 28 //将当前列表中第一个元素设为中枢值 29 int pivot = nums[low]; 30 31 while(low < high){ 32 33 //找到第一个小于中枢值的数,置于low的位置 34 while(low < high && nums[high] >= pivot){ 35 --high; 36 } 37 nums[low] = nums[high]; 38 39 //找到第一个大于中枢值的数,置于high的位置 40 while(low < high && nums[low] <= pivot){ 41 ++low; 42 } 43 nums[high] = nums[low]; 44 } 45 46 //这样一趟下来nums[low]左端都是小于中枢值的数,右端都是大于中枢值的数,一个元素的最终排序位置确定 47 nums[low] = pivot; 48 49 return low; 50 } 51 }
1 public class Test { 2 3 public static void main(String[] args) { 4 5 int[] nums = {34, 32, 43, 12, 11, 32, 22, 21, 32}; 6 7 System.out.println("Unsorted array : " + Arrays.toString(nums)); 8 9 iterativeQuicksort(nums); 10 11 System.out.println("Sorted array : " + Arrays.toString(nums)); 12 13 } 14 15 public static void iterativeQuicksort(int[] nums) { 16 17 //新建栈,模拟递归操作 18 Stack stack = new Stack(); 19 20 stack.push(0); 21 stack.push(nums.length); 22 23 while (!stack.isEmpty()) { 24 int high = (int)stack.pop(); 25 int low = (int)stack.pop(); 26 27 if (high - low < 2) { 28 continue; 29 } 30 31 //pivot为low与high的平均值,保证随机性,降低抽到数组中最小值或最大值的概率 32 int p = low + ((high - low) / 2); //pivot为low与high的平均值,这样写防止溢出 33 34 //经过一趟partition后,p所在的位置已是排序后的最终位置 35 p = partition(nums, p, low, high); 36 37 stack.push(p + 1); 38 stack.push(high); 39 40 stack.push(low); 41 stack.push(p); 42 } 43 } 44 45 private static int partition(int[] input, int position, int start, int end) { 46 47 int l = start; 48 int h = end - 2; 49 50 int pivot = input[position]; 51 52 //将pivot换至最右端 53 swap(input, position, end - 1); 54 55 //筛选pivot的最终位置 56 while (l < h) { 57 if (input[l] < pivot) { 58 l++; 59 } else if (input[h] >= pivot) { 60 h--; 61 } else { 62 swap(input, l, h); 63 } 64 } 65 //pos为pivot的最终位置 66 int pos = h; 67 68 //如果pivot左边的数都小于它,说明它本来就应该在最右端的位置,因此pos++ 69 if (input[h] < pivot) { 70 pos++; 71 } 72 swap(input, end - 1, pos); 73 74 return pos; 75 } 76 77 private static void swap(int[] arr, int i, int j) { 78 int temp = arr[i]; 79 arr[i] = arr[j]; 80 arr[j] = temp; 81 } 82 }
递归与迭代
-
优点:
-
极大的减少了代码量,代码简单易读
-
将大问题转化成小问题,逻辑清晰
-
-
缺点:
-
递归不断调用函数,不断压栈,浪费空间容易造成栈溢出
-
频繁的入栈出栈操作也会导致性能损失
-
迭代:函数内某段代码实现循环,不断把变量的原值推导成新值,直到最终结果产生
-
优点:
-
效率比递归高,运行时间只随循环的增加而增加
-
不需要反复调用从而占用栈的空间
-
-
缺点:
-
代码复杂,较难理解
-
面对复杂问题时,难以构思代码
-

浙公网安备 33010602011771号