add bucket sort and binary search
This commit is contained in:
parent
e714cc2c9f
commit
de13b81887
58
typescript/12_sorts/MergeSort.ts
Normal file
58
typescript/12_sorts/MergeSort.ts
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 归并排序
|
||||
* 稳定排序,稳定的O(nlgn)时间复杂度
|
||||
* O(n)的空间复杂度
|
||||
* 在小规模数据排序中很常用
|
||||
*/
|
||||
class MergeSort {
|
||||
public static mergeSort(array: number[]) {
|
||||
if (!array || !array.length) return
|
||||
const length = array.length
|
||||
this.mergeSortInternally(array, 0, length - 1)
|
||||
}
|
||||
|
||||
static mergeSortInternally(array: number[], p: number, r: number) {
|
||||
if (p >= r) return
|
||||
// 严格按照中间值作切分点
|
||||
// js中除法需要做取整操作,不然结果有可能是小数
|
||||
const q = Math.floor(p + (r - p) / 2)
|
||||
this.mergeSortInternally(array, p, q)
|
||||
this.mergeSortInternally(array, q + 1, r)
|
||||
this.mergeArray(array, p, q, r)
|
||||
}
|
||||
|
||||
private static mergeArray(a: number[], p: number, q: number, r: number) {
|
||||
let i = p
|
||||
let j = q + 1
|
||||
let k = 0
|
||||
// 定义一个临时数组来存放排序的值
|
||||
const tmp: number[] = []
|
||||
while (i <= q && j <= r) {
|
||||
if (a[i] <= a[j]) {
|
||||
tmp[k++] = a[i++]
|
||||
} else {
|
||||
tmp[k++] = a[j++]
|
||||
}
|
||||
}
|
||||
// 判断哪个子数组中有剩余的数据
|
||||
let start = i
|
||||
let end = q
|
||||
if (j <= r) {
|
||||
start = j
|
||||
end = r
|
||||
}
|
||||
// 将剩余的数据拷贝到临时数组tmp
|
||||
while (start <= end) {
|
||||
tmp[k++] = a[start++]
|
||||
}
|
||||
|
||||
// 将tmp中的数组拷贝回a[p...r]
|
||||
for (i = 0; i <= r - p; i++) {
|
||||
a[p + i] = tmp[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const test4 = [1, 3, 2, 3, 10, 9, 7, 6, 0, 12]
|
||||
MergeSort.mergeSort(test4)
|
||||
console.log(test4)
|
@ -3,24 +3,19 @@
|
||||
* 原地排序,空间复杂度O(1),比归并排序使用更广泛
|
||||
* 平均复杂度基本接近O(nlg(n))
|
||||
*/
|
||||
interface ArraySort {
|
||||
sort(array: number[]): void
|
||||
}
|
||||
|
||||
class QuickSort implements ArraySort {
|
||||
sort(array: number[]): void {
|
||||
export class QuickSort {
|
||||
static sort(array: number[]): void {
|
||||
this.sortInternally(array, 0, array.length - 1)
|
||||
}
|
||||
|
||||
private sortInternally(array: number[], p: number, r: number) {
|
||||
private static sortInternally(array: number[], p: number, r: number) {
|
||||
if (p >= r) return
|
||||
// 获取分界点
|
||||
const q: number = this.partition(array, p, r)
|
||||
this.sortInternally(array, p, q - 1)
|
||||
this.sortInternally(array, q + 1, r)
|
||||
}
|
||||
|
||||
private partition(array: number[], p: number, r: number): number {
|
||||
private static partition(array: number[], p: number, r: number): number {
|
||||
/**
|
||||
* 参考值pivot,小于pivot的放在左边,大于pivot的在右边,最后再把分界点的值和它做交换
|
||||
* 这样返回的index一定是值在中间的下标
|
||||
@ -39,7 +34,7 @@ class QuickSort implements ArraySort {
|
||||
return index - 1
|
||||
}
|
||||
|
||||
private swap(array: number[], p: number, q: number) {
|
||||
private static swap(array: number[], p: number, q: number) {
|
||||
const temp = array[p]
|
||||
array[p] = array[q]
|
||||
array[q] = temp
|
||||
@ -47,6 +42,5 @@ class QuickSort implements ArraySort {
|
||||
}
|
||||
|
||||
const testSort = [1, 3, 2, 3, 10, 9, 7, 6, 0, -12]
|
||||
const quickSort: ArraySort = new QuickSort()
|
||||
quickSort.sort(testSort)
|
||||
QuickSort.sort(testSort)
|
||||
console.log(testSort)
|
||||
|
52
typescript/13_sorts/BucketSort.ts
Normal file
52
typescript/13_sorts/BucketSort.ts
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 桶排序对数据的要求比较高
|
||||
* 首先要知道数据的范围
|
||||
* 然后根据范围将数据分到小范围的桶中
|
||||
* 每个桶采用快速排序
|
||||
* 当桶的数量接近数据量大小的时候,时间复杂度为O(n)
|
||||
*/
|
||||
import { QuickSort } from '../12_sorts/quickSort'
|
||||
|
||||
class BucketSort {
|
||||
static sort(array: number[], bucketSize: number = 5) {
|
||||
const length = array.length
|
||||
if (length === 0) return array
|
||||
// 首先要确定数据的范围
|
||||
let min = array[0]
|
||||
let max = array[0]
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (array[i] < min) {
|
||||
min = array[i]
|
||||
} else if (array[i] > max) {
|
||||
max = array[i]
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化桶,确定桶的数量
|
||||
// 因为不能保证正好被整除,需要+1 存放剩余的元素
|
||||
const bucketCount = Math.floor((max - min) / bucketSize) + 1
|
||||
// 桶是个二维数组
|
||||
const buckets = new Array(bucketCount)
|
||||
for (let i = 0; i < bucketCount; i++) {
|
||||
buckets[i] = []
|
||||
}
|
||||
|
||||
// 利用映射函数将数据分配到各个桶中
|
||||
// 这个时间复杂度为O(n)
|
||||
for (let i = 0; i < length; i++) {
|
||||
buckets[Math.floor((array[i]-min) / bucketSize)].push(array[i])
|
||||
}
|
||||
array.length = 0 // 返回数组
|
||||
for (let i = 0; i < bucketCount; i++) {
|
||||
// 每个桶里根据具体情况排序,使用插入排序或者快速排序等等
|
||||
QuickSort.sort(buckets[i])
|
||||
for (let j = 0; j < buckets[i].length; j++) {
|
||||
array.push(buckets[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bucketTest = [1, 3, 2, 3, 10, 9, 7, 6, 0, -12]
|
||||
BucketSort.sort(bucketTest)
|
||||
console.log(bucketTest)
|
51
typescript/13_sorts/CountingSort.ts
Normal file
51
typescript/13_sorts/CountingSort.ts
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 计数排序
|
||||
* 也是线性时间复杂度,和桶排序非常类似
|
||||
* 适用于值范围较小的大数据排序
|
||||
* 注意值范围需要不小于0,不然需要将数据预处理
|
||||
* 并非原地排序
|
||||
*/
|
||||
class CountingSort {
|
||||
static sort(array: number[]) {
|
||||
const length = array.length
|
||||
|
||||
// 找到这个数组的最大值
|
||||
let max = array[0]
|
||||
array.forEach((item) => {
|
||||
if (item > max) {
|
||||
max = item
|
||||
}
|
||||
})
|
||||
|
||||
// 初始化值范围数组
|
||||
const countArray = new Array(max + 1).fill(0, 0, max + 1)
|
||||
// 先计算每个元素的出现个数
|
||||
for (let i = 0; i < length; i++) {
|
||||
countArray[array[i]] = countArray[array[i]] + 1
|
||||
}
|
||||
// 计算元素的累计出现个数
|
||||
for (let i = 1; i <= max; i++) {
|
||||
countArray[i] = countArray[i - 1] + countArray[i]
|
||||
}
|
||||
|
||||
// 接下来开始计数排序了
|
||||
// 空间还是要申请
|
||||
const sortedArray = []
|
||||
// 倒序遍历能够达到稳定排序的作用
|
||||
for (let i = length - 1; i >= 0; i--) {
|
||||
// -1是为了填补sortedArray在0的位置,因为countArray在0的位置中一定么有值
|
||||
const index = countArray[array[i]] - 1
|
||||
sortedArray[index] = array[i]
|
||||
countArray[array[i]]--
|
||||
}
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = sortedArray[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const testSort2 = [1, 3, 2, 3, 10, 9, 7, 6, 0]
|
||||
CountingSort.sort(testSort2)
|
||||
console.log(testSort2)
|
||||
|
28
typescript/14_binarysearch/BinarySearch.ts
Normal file
28
typescript/14_binarysearch/BinarySearch.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 二分查找适合于连续内存的数组查找
|
||||
* 并且是已经排好序的数组
|
||||
* 时间复杂度只有log(n)
|
||||
*/
|
||||
class BinarySearch {
|
||||
static bSearch(array: number[], target: number) {
|
||||
if (!array || array.length === 0) return -1
|
||||
const length = array.length
|
||||
let low = 0
|
||||
let high = length - 1
|
||||
while (low <= high) {
|
||||
// 一定是整数,这边的移位运算优先级低于+,-运算符,需要加括号
|
||||
const mid = low + ((high - low) >> 1)
|
||||
if (array[mid] === target) {
|
||||
return mid
|
||||
} else if (array[mid] > target) {
|
||||
high = mid - 1
|
||||
} else {
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
const testBinarySearch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
console.log(BinarySearch.bSearch(testBinarySearch, 10))
|
Loading…
Reference in New Issue
Block a user