项目被搁置了, 看文档看的瞌睡了, 来研究一下算法, 第一次(可能之前学习过,忘掉了)看到这种算法, 觉得挺有意思, 遂来深入分析一下:
第一步分为两段快速排序, 首先用数学公式退到一下遍历的次数(此处假设认为其他操作不耗时, 只有遍历操作耗时).
那么普通排序的遍历次数是n * n-1, 分成两段的遍历次数是n + m * (m - 1) + (n - m - 1) * (n - m - 2) [1 < m < n],
解释一下后面这个公式, 前面的n是进行分组, 后面的是分两段进行普通排序, m代表第一段的长度.
(n * n-1) - (n + m * (m - 1) + (n - m - 1) * (n - m - 2) [1 < m < n]) = m * m - 2 *(n - 1) * (m + 2)
看上去这个公式恒小于零, 推导证明就不做了, 绕啊绕的苦涩难懂, 而且这里忽略了其他操作的耗时, 所以还是直接用代码说话吧:
import now from 'performance-now'; // Generate Array to Sort const originArray = []; const max = 10; for (let k = 0; k < max; k++) { originArray[k] = Math.floor(Math.random() * max) + 1; } console.log("Origin Array", JSON.stringify(originArray)); console.log(); const len = originArray.length; let normalSort = [], quickSort = [], normalTimes = 0, quickTimes = 0; var t0 = now(); //Normal Sort Method normalSort = Array.from(originArray); for (let i = 0; i < len; i++) { for (let j = i + 1; j < len; j++) { normalTimes++; if (normalSort[i] < normalSort[j]) { let temp = normalSort[i]; normalSort[i] = normalSort[j]; normalSort[j] = temp; } } } var t1 = now(); //Quick Sort Method const half = Math.floor(len / 2); let rightPart = []; for (let i = 0; i < len; i++) { if (originArray[i] > originArray[half]) { quickSort.push(originArray[i]); } else { rightPart.push(originArray[i]); } } const splitLen = quickSort.length; quickSort = quickSort.concat(rightPart); for (let i = 0; i < splitLen; i++) { for (let j = i + 1; j < splitLen; j++) { quickTimes++; if (quickSort[i] < quickSort[j]) { let temp = quickSort[i]; quickSort[i] = quickSort[j]; quickSort[j] = temp; } } } for (let i = splitLen; i < len; i++) { for (let j = i + 1; j < len; j++) { quickTimes++; if (quickSort[i] < quickSort[j]) { let temp = quickSort[i]; quickSort[i] = quickSort[j]; quickSort[j] = temp; } } } var t2 = now(); console.log("Normal Sort Result", JSON.stringify(normalSort)); console.log("Quick Sort Result", JSON.stringify(quickSort)); console.log(); console.log("NormalSort took " + (t1 - t0) + " milliseconds. loop times" + normalTimes); console.log("QuickSort took " + (t2 - t1) + " milliseconds. loop times" + quickTimes);
下面分别是数组长度对应10、100、1000...的执行时间:
可以看出, 除了1000次的时候, 慢一点, 其他的时候, 速度优势是很明显的.
刚好最近在学Python, 于是翻译成python, 重新跑了一遍:
import random import timeit import copy import math import json # Generate Array to Sort originArray = [] maxN = 10 for i in range(0, maxN): originArray.append(random.randint(1, maxN)) lenN = len(originArray); normalSort = [] quickSort = [] normalTimes = 0 quickTimes = 0 t0 = timeit.default_timer() # Normal Sort Method normalSort = copy.copy(originArray) for i in range(0, lenN): for j in range(i + 1, lenN): normalTimes = normalTimes + 1 if normalSort[i] < normalSort[j]: temp = normalSort[i] normalSort[i] = normalSort[j] normalSort[j] = temp t1 = timeit.default_timer() # Quick Sort Method half = math.floor(lenN / 2) rightPart = [] for i in range(0, maxN): if originArray[i] > originArray[half]: quickSort.append(originArray[i]) else: rightPart.append(originArray[i]) splitLen = len(quickSort) quickSort = quickSort + rightPart for i in range(0, splitLen): for j in range(i + 1, splitLen): quickTimes = quickTimes + 1 if quickSort[i] < quickSort[j]: temp = quickSort[i] quickSort[i] = quickSort[j] quickSort[j] = temp for i in range(splitLen, lenN): for j in range(i + 1, lenN): quickTimes = quickTimes + 1 if quickSort[i] < quickSort[j]: temp = quickSort[i] quickSort[i] = quickSort[j] quickSort[j] = temp t2 = timeit.default_timer() # print("Normal Sort Result", json.dumps(normalSort)); # print("Quick Sort Result", json.dumps(quickSort)); # console.log(); print("NormalSort took {} milliseconds. loop times {}".format((t1 - t0) * 1000, normalTimes)) print("QuickSort took {} milliseconds. loop times {}".format((t2 - t1) * 1000, quickTimes))
下面分别是数组长度对应10、100、1000...的执行时间:
不继续了,总之快速排序是要快的.
Python性能有点低啊. 哈哈