总记
排序指根据一定的规则,将所给的若干数据有序化处理,使其更方便算法处理的操作。它在各种各样的场景中出场率都很高,本文介绍两个非常常用的排序算法:归并排序和快速排序,它们都和分治思想有联系。
归并排序
要想把两个已经排序了的数组合并是很简单的,只需要使用双指针逐位比较即可;把一个数组切片油炸为一个个单独的元素,然后逐个两两合并为更大的数组,再对更大的数组两两合并,最终就可以将其排序成为有序的数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public void SortArr(int[] arr, int left, int right) { if (left >= right) return; int mid = (left + right) / 2; SortArr(arr, left, mid); SortArr(arr, mid + 1, right); int[] mergedArr = new int[right - left + 1]; int indexL = left; int indexR = mid + 1; int mergedIndex = 0; while (mergedIndex < mergedArr.Length) { if (indexL < mid + 1 && indexR < right + 1) { if (arr[indexL] <= arr[indexR]) { mergedArr[mergedIndex] = arr[indexL++]; } else { mergedArr[mergedIndex] = arr[indexR++]; } } else { if (indexL > mid) { mergedArr[mergedIndex] = arr[indexR++]; } else { mergedArr[mergedIndex] = arr[indexL++]; } } mergedIndex++; } for (int i = left; i <= right; i++) { arr[i] = mergedArr[i - left]; } }
|
快速排序
如果可以在数组中设置一个哨兵,让哨兵左边的元素都比它小/大,右边的都比它大/小,那么我们继续对哨兵的左右两个子数组这样操作,操作到子数组只是一个单元素,我们也就完成了对整个数组的排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public void SortArr(int[] arr, int left, int right) { if (left >= right) { return; } int indexL = left; int indexR = right; int sentry = arr[left]; int swap; while (indexL < indexR) { while (indexL < indexR && arr[indexR] >= sentry) { indexR--; } while (indexL < indexR && arr[indexL] <= sentry) { indexL++; } swap = arr[indexL]; arr[indexL] = arr[indexR]; arr[indexR] = swap; } swap = arr[left]; arr[left] = arr[indexL]; arr[indexL] = swap; SortArr(arr, left, indexL - 1); SortArr(arr, indexL + 1, right); }
|
总结
上述两个排序的核心思想都是分治,将大问题拆成简单的子问题求解。
理解上述两个排序的工作原理对我们进一步理解分治思想很有帮助。