算法笔记 #006# 快速排序 × 算法导论(第三版)练习 7.1-1 ~ 7.1-4
快排和归并排序一样采用经典的分治思想,不同的地方在于,归并排序的关键步骤在于“合并”,而快速排序的关键步骤在于“分解”。快速排序的最坏运行时间虽然是O(n^2),不过在实际中基本都比归并排序快,并且可以通过随机选择主元来防止极端的输入。它的具体步骤如下↓
分解:快排的核心步骤,其结果是数组被分成以某个数为基准的左右两个子数组(可能为空),其中左边的数都小于该基准数,右边的数都大于该基准数。详细步骤包括计算基准数下标,以及移动数组内元素。
解决:通过递归调用快速排序,对两个子数组进行排序。
合并:因为是原址排序,快速排序不需要合并操作。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> function partition(arr, start, end) { let i = start; let j = end - 1; let x = arr[i]; while (i < j) { while (arr[j] >= x && i < j) j--; arr[i] = arr[j]; while (arr[i] <= x && i < j) i++; arr[j] = arr[i]; } arr[i] = x; return i; } function quicksort(arr, start, end) { if (start >= end - 1) { // 只有一个元素就不用排了 return; } else { let mid = partition(arr, start, end); quicksort(arr, start, mid); quicksort(arr, mid + 1, end); } } function randomNum(min, max) { let rg = max - min; let rand = Math.random(); let digit = min + Math.floor(rand * rg); //舍去 return digit; // min ≤ digit < max } function randomizedPartition(arr, start, end) { // 随机选取主元 let i = randomNum(start, end); let temp = arr[i]; arr[i] = arr[start]; arr[start] = temp; return partition(arr, start, end); } function randomizedQuicksort(arr, start, end) { if (start >= end - 1) { return; } else { let mid = randomizedPartition(arr, start, end); randomizedQuicksort(arr, start, mid); randomizedQuicksort(arr, mid + 1, end); } } let test_arr = [3, 3, 3, 3, 3, 3, 3]; randomizedQuicksort(test_arr, 0, test_arr.length); console.log("", test_arr); </script> </body> </html>
7.1-1
略
7.1-2
输入规模为n,假设数组内元素都相同,则挖坑填数法的partition返回值依次为0,1,2,3,4,...,n-1,修改partition如下:
function partition(arr, start, end) { // 数组元素全部相同的情况 let k = start; for (; k != end - 1; ++k) { if (arr[k] != arr[k + 1]) break; } if (k == end -1) { return Math.floor((start + end) / 2) } let i = start; let j = end - 1; let x = arr[i]; while (i < j) { while (arr[j] >= x && i < j) j--; arr[i] = arr[j]; while (arr[i] <= x && i < j) i++; arr[j] = arr[i]; } arr[i] = x; return i; }
7.1-3
i,j合作扫描了一遍数组,所以是theta n
7.1-4
partition里的>=和<=互换一下。