Skip to content

Commit

Permalink
add sort and search
Browse files Browse the repository at this point in the history
  • Loading branch information
knewbie committed Apr 30, 2017
1 parent ecfecdd commit b0f4912
Show file tree
Hide file tree
Showing 8 changed files with 367 additions and 5 deletions.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,23 @@
- [X] 二叉树(BiTree)
- [X] 二叉查找树(BST)
- [X] 图(Grap)
- [ ] 排序算法(Sort)
- [ ] 查找算法(Search)
- [X] 排序算法(Sort)
- [X] 冒泡排序(Bubble Sort)
- [X] 梳排序(冒泡改进版)(Comb Sort)
- [X] 选择排序 (Select sort)
- [X] 插入排序 (Insert Sort)
- [X] 希尔排序 (Shell Sort)
- [X] 快速排序 (Quick Sort)
- [X] 单基准快排(递归 & 非递归)
- [X] 双基准快排 (Dual Pivot)
- [X] 三路快排 (3 way)
- [X] 查找算法(Search)
- [X] 顺序查找(Seq Search) *使用自组织数据*
- [X] 二分查找(Binary Search)

### 补充:
> 排序算法中还有一些算法书中介绍过的未在这里列出与实现,还有这些基础算法的改进升级版,比如上面的双基准快排和三路快排。其他的算法会慢慢被充
(未完待续....)

### How To Run & Test
每个对应的数据结构都有一个test_XXX的测试文件,
Expand Down
35 changes: 35 additions & 0 deletions Search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

// 根据 80-20 原则(是指对某一数据集执行的80%的查找操作都是对其中20%的数据元素进行查找
// 自组织的方式最终会把这20%的数据位置置于数据集的起始位置
export function SeqSearch<T>(data: T[], elem:T):boolean {
let len = data.length;
for(let i=0;i<len; i++ ) {
if(data[i] == elem) {
if(i>len*0.2 && i>1) {
let temp = data[i-1];
data[i-1] = data[i];
data[i] = temp;
}
return true;
}
}
return false;
}

export function BinarySearch<T>(data: T[], elem:T):number {
let start = 0;
let end = data.length - 1;
let mid = 0;

while(start <= end) {
mid = Math.floor((start+end)/2);
if(elem > data[mid]) {
start = mid + 1;
} else if(elem < data[mid]) {
end = mid - 1;
} else {
return mid;
}
}
return -1;
}
234 changes: 234 additions & 0 deletions Sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@

import { Stack } from "./Stack";

function swap<T>(d: T[], index1: number, index2: number) {
let temp = d[index1];
d[index1] = d[index2];
d[index2] = temp;
}

export function BubbleSort<T>(data: T[]) {
let len = data.length;
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - 1; j++) {
if (data[j] > data[j + 1]) {
swap(data, j, j + 1);
}
}
}
}

export function CombSort<T>(data: T[]) {
let n = data.length;
let j = n,
s = 1.3,
flag = false;
while (j > 1 || flag) {
let i = 0;
j = Math.max(Math.floor(j / s), 1);
flag = false;
while (i + j < n) {
if (data[i] > data[i + j]) {
swap(data, i, i + j);
flag = true;
}
i++;
}
}
}

export function SelectSort<T>(data: T[]) {
let n = data.length;
for (let i = 0; i < n - 1; i++) {
let minIdx = i;
for (let j = i + 1; j < n; j++) {
if (data[minIdx] > data[j]) {
minIdx = j;
}
}
if (minIdx != i) {
swap(data, i, minIdx);
}
}
}

export function InsertSort<T>(data: T[]) {
let temp, inner;
let n = data.length;
for (let i = 1; i < n; i++) {
temp = data[i];
inner = i;
while (inner > 0 && data[inner - 1] >= temp) {
data[inner] = data[inner - 1];
inner--;
}
data[inner] = temp;
}
}

export function ShellSort<T>(data: T[]) {
let n = data.length;
let h = 1;
while (h < n / 3) {
h = 3 * h - 1;
}
while (h >= 1) {
for (let i = h; i < n; i++) {
for (let j = i; j >= h && data[j] < data[j - h]; j -= h) {
swap(data, j, j - h);
}
}
h = Math.ceil((h - 1) / 3);
}
}

export function QuickSortRecursive<T>(data: T[]): T[] {
return qsort(data);
}
function qsort<T>(d: T[]): T[] {
if (d.length == 0) {
return [];
}
let left = [], right = [];
let pivot = d[0];
for (let i = 1; i < d.length; i++) {
if (d[i] < pivot) {
left.push(d[i]);
} else {
right.push(d[i]);
}
}
return qsort(left).concat(pivot, qsort(right));
}

// 严尉敏数据结构实现
function partion_v1<T>(d: T[], low: number, high: number): number {
let pivotKey = d[low];
while (low < high) {
while (high > low && d[high] >= pivotKey) {
high--;
}
d[low] = d[high];
while (low < high && d[low] <= pivotKey) {
low++;
}
d[high] = d[low];
}
// now low == high
d[low] = pivotKey;
return low;
}

// 算法导论实现
function partion_v2<T>(d: T[], low: number, high: number): number {
let pivotKey = d[high];
let p = low - 1;
for (let j = low; j < high; j++) {
if (d[j] <= pivotKey) {
p++;
if (p != j) {
swap(d, p, j);
}
}
}
p += 1;
swap(d, p, high);
return p;
}

export function QuickSort<T>(data: T[]) {
let s = new Stack<number>();
let low = 0, high = data.length - 1;
if (low < high) {
let p = partion_v2(data, low, high);
if (p - 1 > low) {
s.push(low);
s.push(p - 1);
}
if (p + 1 < high) {
s.push(p + 1);
s.push(high);
}
while (!s.empty()) {
let r = s.pop();
let l = s.pop();
p = partion_v2(data, l, r);
if (p - 1 > l) {
s.push(l);
s.push(p - 1);
}
if (p + 1 < r) {
s.push(p + 1);
s.push(r);
}
}
}
}

// 3 way quick sort
function sort3way<T>(d: T[], low: number, high: number) {
if (high <= low) {
return;
}
let lt = low;
let gt = high;
let i = low + 1;
let pivot = d[low];
while (i <= gt) {
if (d[i] < pivot) {
swap(d, i++, lt++);
} else if (pivot < d[i]) {
swap(d, i, gt--);
} else {
i++;
}
}

sort3way(d, low, lt - 1);
sort3way(d, gt + 1, high);
}

export function QuickSort3Way<T>(data: T[]) {
sort3way(data, 0, data.length - 1);
}

// dual pivot
function sortDualPiovt<T>(d: T[], low: number, high: number) {
if (high <= low) {
return;
}

let pivot1 = d[low];
let pivot2 = d[high];
if (pivot1 > pivot2) {
swap(d, low, high);
} else if (pivot1 == pivot2) {
while (pivot1 == pivot2 && low < high) {
low++;
pivot1 = d[low];
}
}

let i = low + 1;
let lt = low + 1;
let gt = high - 1;
while (i <= gt) {
if (d[i] < pivot1) {
swap(d, i++, lt++);
} else if (d[i] > pivot2) {
swap(d, i, gt--);
} else {
i++;
}
}
swap(d, low, --lt);
swap(d, high, ++gt);

sortDualPiovt(d, low, lt - 1);
sortDualPiovt(d, lt + 1, gt - 1);
sortDualPiovt(d, gt + 1, high);
}

export function QuickSortDualPivot<T>(data: T[]) {
sortDualPiovt(data, 0, data.length - 1);
}
4 changes: 4 additions & 0 deletions Stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class Stack<T> {
return this.top;
}

public empty():boolean {
return this.top == 0;
}

public clear() {
this.top = 0;
}
Expand Down
14 changes: 14 additions & 0 deletions test_Search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {SeqSearch, BinarySearch} from "./Search";
import {QuickSort3Way} from "./Sort";


let d = [4,8,5,10,3,9,6,11,2];
QuickSort3Way(d);

console.log(BinarySearch(d, 6));

console.log(BinarySearch(d, 1));

console.log(BinarySearch(d, 7));

console.log(BinarySearch(d, 12));
3 changes: 2 additions & 1 deletion test_Set.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Set } from "./Set";
// import { Set } from "./Set";
import {deepcopy, print} from "./util";

let s1 = new Set<number>();

let s = new Set<any>();
s.add("David");
Expand Down
62 changes: 62 additions & 0 deletions test_Sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as sort from "./Sort";
import { deepcopy, print } from "./util";


function printSort<T>(d: T[], sortFunc: string) {
let data = deepcopy(d);
let ret;
let start = new Date().getTime();
print(sortFunc," before sort: ", data);
switch (sortFunc) {
case "bubble": {
sort.BubbleSort(data);
break;
}
case "comb": {
sort.CombSort(data);
break;
}
case "select": {
sort.SelectSort(data);
break;
}
case "insert": {
sort.InsertSort(data);
break;
}
case "shell": {
sort.ShellSort(data);
break;
}
case "quick": {
ret = sort.QuickSortRecursive(data);
break;
}
case "quick-nr": {
sort.QuickSort(data);
break;
}
case "quick3way":{
sort.QuickSort3Way(data);
break;
}
case "quickDualPivot": {
sort.QuickSortDualPivot(data);
break;
}
}
print(sortFunc," after sort: ", !ret?data:ret);
print(sortFunc," use times: ", new Date().getTime() - start, "ms");
}

let d = [10,8,3,7,2,4,9,5,4,6];

printSort(d, "bubble");
printSort(d, "comb");
printSort(d, "select");
printSort(d, "insert");
printSort(d, "shell");
printSort(d, "quick-recursive");
printSort(d, "quick-nr");
printSort(d, "quick3way");
printSort(d, "quickDualPivot");
Loading

0 comments on commit b0f4912

Please sign in to comment.