commit
9e8e091286
6
.gitignore
vendored
6
.gitignore
vendored
@ -44,4 +44,8 @@ bld/
|
|||||||
[Ll]og/
|
[Ll]og/
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
|
|
||||||
|
**/*.idea
|
||||||
|
**/*.iml
|
||||||
|
**/*out
|
||||||
|
136
DynamicStackBaseArray.java
Normal file
136
DynamicStackBaseArray.java
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
package Stack;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顺序栈的动态扩容
|
||||||
|
* Author: PeiJiaNi
|
||||||
|
* @param <T> 顺序栈元素类型
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DynamicStackBaseArray<T> implements Iterable<T> {
|
||||||
|
private T[] items; // 数组
|
||||||
|
private int count; // 栈中的元素个数
|
||||||
|
private int length; // 栈空间大小
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化栈
|
||||||
|
*
|
||||||
|
* @param length 栈空间大小
|
||||||
|
*/
|
||||||
|
public DynamicStackBaseArray(int length) {
|
||||||
|
this.items = (T[]) new Object[length];
|
||||||
|
this.count = 0;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入栈操作 平均时间复杂度O(1)
|
||||||
|
*
|
||||||
|
* @param item 入栈元素
|
||||||
|
*/
|
||||||
|
public void push(T item) {
|
||||||
|
// 栈空间已满,则扩容
|
||||||
|
if (count == length) {
|
||||||
|
resize(2 * items.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
items[count++] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出栈操作 平均时间复杂度O(1)
|
||||||
|
*
|
||||||
|
* @return 如果栈内不为空,则返回栈顶元素,否则返回-1
|
||||||
|
*/
|
||||||
|
public T pop() {
|
||||||
|
if (count == 0) {
|
||||||
|
System.out.println("当前栈已空,无法进行出栈操作");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
T item = items[--count];
|
||||||
|
items[count] = null;
|
||||||
|
|
||||||
|
if (count > 0 && (count == items.length / 4)) {
|
||||||
|
resize(items.length / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回下标为 count-1 的数组元素,并且栈中元素个数count-1
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 栈空间动态增加或减小
|
||||||
|
*
|
||||||
|
* @param size
|
||||||
|
*/
|
||||||
|
private void resize(int size) {
|
||||||
|
T[] newItems = (T[]) new Object[size];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
newItems[i] = this.items[i];
|
||||||
|
}
|
||||||
|
this.items = newItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回栈中最近添加的元素而不删除它
|
||||||
|
public T peek() {
|
||||||
|
return items[count - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前栈是否为空
|
||||||
|
*
|
||||||
|
* @return 栈为空,则返回true,否则返回-1
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回栈中元素个数
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return new ArrayIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 内部类
|
||||||
|
class ArrayIterator implements Iterator {
|
||||||
|
int numOfItems = count;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return numOfItems > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
return items[--numOfItems];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DynamicStackBaseArray<Integer> stack = new DynamicStackBaseArray<Integer>(6);
|
||||||
|
stack.push(1);
|
||||||
|
stack.push(2);
|
||||||
|
stack.push(3);
|
||||||
|
stack.push(4);
|
||||||
|
stack.push(5);
|
||||||
|
// System.out.println(stack.peek());
|
||||||
|
Iterator iterator = stack.iterator();
|
||||||
|
// System.out.println(iterator.hasNext());
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
System.out.println(iterator.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
|||||||
# 数据结构和算法必知必会的50个代码实现
|
# 数据结构和算法必知必会的50个代码实现
|
||||||
## (关注“小争哥”公众号,获取我的更多技术、非技术分享)
|
### 微信搜索我的公众号“小争哥”,或者微信扫描下面二维码, 获取更多压箱底的干货分享
|
||||||
|
|
||||||
|
![t2](https://github.com/wangzheng0822/markdownphotos/blob/master/pics/qrcode_for_gh_9b0e7afdff20_258.jpg)
|
||||||
|
|
||||||
## 数组
|
## 数组
|
||||||
* 实现一个支持动态扩容的数组
|
* 实现一个支持动态扩容的数组
|
||||||
|
64
StackBaseArray.java
Normal file
64
StackBaseArray.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顺序栈(基于数组实现)
|
||||||
|
* Author: PeiJiaNi
|
||||||
|
*/
|
||||||
|
public class StackBaseArray {
|
||||||
|
private int[] items; // 数组
|
||||||
|
private int count; // 栈中元素个数
|
||||||
|
private int length; // 栈空间大小
|
||||||
|
|
||||||
|
public StackBaseArray(int capactiy) {
|
||||||
|
this.items = new int[capactiy];
|
||||||
|
this.count = 0;
|
||||||
|
this.length = capactiy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入栈操作 时间复杂度O(1)
|
||||||
|
* @param item 要入栈的元素
|
||||||
|
* @return 入栈成功则返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public boolean push(int item) {
|
||||||
|
if(count == length) {
|
||||||
|
System.out.println("当前栈已满,无法进行入栈操作");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
items[count] = item;
|
||||||
|
++count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出栈操作 时间复杂度O(1)
|
||||||
|
* @return 如果栈内不为空,则返回栈顶元素,否则返回-1
|
||||||
|
*/
|
||||||
|
public int pop(){
|
||||||
|
if(count == 0) {
|
||||||
|
System.out.println("当前栈已空,无法进行出栈操作");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回下标为 count-1 的数组元素,并且栈中元素个数count-1
|
||||||
|
return items[--count];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
StackBaseArray stack = new StackBaseArray(6);
|
||||||
|
stack.push(1);
|
||||||
|
stack.push(2);
|
||||||
|
stack.push(3);
|
||||||
|
stack.push(4);
|
||||||
|
stack.push(5);
|
||||||
|
System.out.println(stack.pop());
|
||||||
|
System.out.println(stack.pop());
|
||||||
|
System.out.println(stack.pop());
|
||||||
|
System.out.println(stack.pop());
|
||||||
|
System.out.println(stack.pop());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ int delete(struct array *array, int idx)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memmove(&array->arr[idx], &array->arr[idx+1],
|
memmove(&array->arr[idx], &array->arr[idx+1],
|
||||||
(array->used - idx) * sizeof(int));
|
(array->used - idx - 1) * sizeof(int));
|
||||||
array->used--;
|
array->used--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
22
go/29_priority_queue/heap.go
Normal file
22
go/29_priority_queue/heap.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package pqueue
|
||||||
|
|
||||||
|
func adjustHeap(src []Node, start, end int) {
|
||||||
|
if start >= end {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只需要保证优先级最高的节点在 src[1] 的位置即可
|
||||||
|
for i := end / 2; i >= start; i-- {
|
||||||
|
high := i
|
||||||
|
if src[high].priority < src[2*i].priority {
|
||||||
|
high = 2 * i
|
||||||
|
}
|
||||||
|
if 2*i+1 <= end && src[high].priority < src[2*i+1].priority {
|
||||||
|
high = 2*i + 1
|
||||||
|
}
|
||||||
|
if high == i {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
src[high], src[i] = src[i], src[high]
|
||||||
|
}
|
||||||
|
}
|
14
go/29_priority_queue/heap_test.go
Normal file
14
go/29_priority_queue/heap_test.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package pqueue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_AdjustHeap(t *testing.T) {
|
||||||
|
list := []Node{Node{0, 0}, Node{1, 1}, Node{2, 2}, Node{3, 3}, Node{4, 1}, Node{6, 6}}
|
||||||
|
|
||||||
|
adjustHeap(list, 1, len(list)-1)
|
||||||
|
assert.Equal(t, 6, list[1].value)
|
||||||
|
}
|
62
go/29_priority_queue/priority_queue.go
Normal file
62
go/29_priority_queue/priority_queue.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package pqueue
|
||||||
|
|
||||||
|
// Node 队列节点
|
||||||
|
type Node struct {
|
||||||
|
value int
|
||||||
|
priority int
|
||||||
|
}
|
||||||
|
|
||||||
|
// PQueue priority queue
|
||||||
|
type PQueue struct {
|
||||||
|
heap []Node
|
||||||
|
|
||||||
|
capacity int
|
||||||
|
used int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPriorityQueue new
|
||||||
|
func NewPriorityQueue(capacity int) PQueue {
|
||||||
|
return PQueue{
|
||||||
|
heap: make([]Node, capacity+1, capacity+1),
|
||||||
|
capacity: capacity,
|
||||||
|
used: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push 入队
|
||||||
|
func (q *PQueue) Push(node Node) {
|
||||||
|
|
||||||
|
if q.used > q.capacity {
|
||||||
|
// 队列已满
|
||||||
|
return
|
||||||
|
}
|
||||||
|
q.used++
|
||||||
|
q.heap[q.used] = node
|
||||||
|
// 堆化可以放在 Pop 中
|
||||||
|
// adjustHeap(q.heap, 1, q.used)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop 出队列
|
||||||
|
func (q *PQueue) Pop() Node {
|
||||||
|
if q.used == 0 {
|
||||||
|
return Node{-1, -1}
|
||||||
|
}
|
||||||
|
// 先堆化, 再取堆顶元素
|
||||||
|
adjustHeap(q.heap, 1, q.used)
|
||||||
|
node := q.heap[1]
|
||||||
|
|
||||||
|
q.heap[1] = q.heap[q.used]
|
||||||
|
q.used--
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top 获取队列顶部元素
|
||||||
|
func (q *PQueue) Top() Node {
|
||||||
|
if q.used == 0 {
|
||||||
|
return Node{-1, -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustHeap(q.heap, 1, q.used)
|
||||||
|
return q.heap[1]
|
||||||
|
}
|
74
go/29_priority_queue/priority_queue_test.go
Normal file
74
go/29_priority_queue/priority_queue_test.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package pqueue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Push(t *testing.T) {
|
||||||
|
queue := NewPriorityQueue(100)
|
||||||
|
|
||||||
|
queue.Push(Node{0, 1})
|
||||||
|
assert.Equal(t, 0, queue.Top().value)
|
||||||
|
|
||||||
|
queue.Push(Node{3, 1})
|
||||||
|
assert.Equal(t, 0, queue.Top().value)
|
||||||
|
|
||||||
|
queue.Push(Node{3, 2})
|
||||||
|
assert.Equal(t, 3, queue.Top().value)
|
||||||
|
|
||||||
|
queue.Push(Node{6, 6})
|
||||||
|
assert.Equal(t, 6, queue.Top().value)
|
||||||
|
|
||||||
|
queue.Push(Node{12, 5})
|
||||||
|
assert.Equal(t, 6, queue.Top().value)
|
||||||
|
|
||||||
|
queue.Push(Node{13, 8})
|
||||||
|
assert.Equal(t, 13, queue.Top().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_PushPop(t *testing.T) {
|
||||||
|
queue := NewPriorityQueue(100)
|
||||||
|
|
||||||
|
queue.Push(Node{0, 1})
|
||||||
|
queue.Push(Node{3, 1})
|
||||||
|
queue.Push(Node{3, 2})
|
||||||
|
queue.Push(Node{6, 6})
|
||||||
|
queue.Push(Node{12, 5})
|
||||||
|
queue.Push(Node{13, 8})
|
||||||
|
assert.Equal(t, 13, queue.Top().value)
|
||||||
|
|
||||||
|
assert.Equal(t, 13, queue.Pop().value)
|
||||||
|
assert.Equal(t, 6, queue.Pop().value)
|
||||||
|
assert.Equal(t, 12, queue.Top().value)
|
||||||
|
assert.Equal(t, 12, queue.Pop().value)
|
||||||
|
|
||||||
|
queue.Push(Node{24, 8})
|
||||||
|
assert.Equal(t, 24, queue.Top().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无法保证入队顺序和出队顺序的一致性
|
||||||
|
// func Test_PushPop_Equal(t *testing.T) {
|
||||||
|
// queue := NewPriorityQueue(9)
|
||||||
|
|
||||||
|
// queue.Push(Node{0, 1}) // 8
|
||||||
|
// queue.Push(Node{3, 1}) // 9
|
||||||
|
// queue.Push(Node{3, 2}) // 3
|
||||||
|
// queue.Push(Node{6, 2}) // 4
|
||||||
|
// queue.Push(Node{11, 3}) // 2
|
||||||
|
// queue.Push(Node{12, 2}) // 5
|
||||||
|
// queue.Push(Node{13, 2}) // 6
|
||||||
|
// queue.Push(Node{19, 5}) // 1
|
||||||
|
// queue.Push(Node{17, 2}) // 7
|
||||||
|
|
||||||
|
// assert.Equal(t, 19, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 11, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 3, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 6, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 12, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 13, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 17, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 0, queue.Pop().value)
|
||||||
|
// assert.Equal(t, 3, queue.Pop().value)
|
||||||
|
// }
|
3
go/29_priority_queue/readme.md
Normal file
3
go/29_priority_queue/readme.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
## TODO
|
||||||
|
- 该实现方式不能保证 相同优先级的元素在出队列时 和入队列的顺序是一致的
|
42
go/42_dynamic_programming/longest_common_substring.go
Normal file
42
go/42_dynamic_programming/longest_common_substring.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func lsc(s1 string, s2 string) int {
|
||||||
|
m := len(s1)
|
||||||
|
n := len(s2)
|
||||||
|
|
||||||
|
memo := make([][]int, m + 1)
|
||||||
|
for i := 0; i < m + 1; i++ {
|
||||||
|
memo[i] = make([]int, n + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for i := 1; i < m + 1; i++ {
|
||||||
|
for j := 1; j < n + 1; j++ {
|
||||||
|
if s1[i - 1] == s2[j - 1] {
|
||||||
|
memo[i][j] = memo[i - 1][j - 1] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(memo)
|
||||||
|
longest := 0
|
||||||
|
for i, _ := range memo {
|
||||||
|
for j, e2 := range memo[i] {
|
||||||
|
if longest < memo[i][j] {
|
||||||
|
longest = e2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return longest
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(lsc("blue", "clues")) //3
|
||||||
|
fmt.Println(lsc("fosh", "fish")) //2
|
||||||
|
fmt.Println(lsc("fosh", "fort")) //2
|
||||||
|
fmt.Println(lsc("hish", "fish")) //3
|
||||||
|
fmt.Println(lsc("hish", "vista")) //2
|
||||||
|
}
|
@ -13,21 +13,14 @@ public class LinkedListAlgo {
|
|||||||
|
|
||||||
// 单链表反转
|
// 单链表反转
|
||||||
public static Node reverse(Node list) {
|
public static Node reverse(Node list) {
|
||||||
Node headNode = null;
|
Node curr = list, pre = null;
|
||||||
|
while (curr != null) {
|
||||||
Node previousNode = null;
|
Node next = curr.next;
|
||||||
Node currentNode = list;
|
curr.next = pre;
|
||||||
while (currentNode != null) {
|
pre = curr;
|
||||||
Node nextNode = currentNode.next;
|
curr = next;
|
||||||
if (nextNode == null) {
|
|
||||||
headNode = currentNode;
|
|
||||||
}
|
|
||||||
currentNode.next = previousNode;
|
|
||||||
previousNode = currentNode;
|
|
||||||
currentNode = nextNode;
|
|
||||||
}
|
}
|
||||||
|
return pre;
|
||||||
return headNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检测环
|
// 检测环
|
||||||
|
@ -5,7 +5,7 @@ package stack;
|
|||||||
*
|
*
|
||||||
* Author: Zheng
|
* Author: Zheng
|
||||||
*/
|
*/
|
||||||
public class StackBasedLinkedList {
|
public class StackBasedOnLinkedList {
|
||||||
private Node top = null;
|
private Node top = null;
|
||||||
|
|
||||||
public void push(int value) {
|
public void push(int value) {
|
||||||
|
@ -27,8 +27,9 @@ public class KthSmallest {
|
|||||||
int pivot = arr[r];
|
int pivot = arr[r];
|
||||||
|
|
||||||
int i = p;
|
int i = p;
|
||||||
for (int j = p; j <= r - 1; j++) {
|
for (int j = p; j < r; j++) {
|
||||||
if (arr[j] < pivot) {
|
// 这里要是 <= ,不然会出现死循环,比如查找数组 [1,1,2] 的第二小的元素
|
||||||
|
if (arr[j] <= pivot) {
|
||||||
swap(arr, i, j);
|
swap(arr, i, j);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
131
java/36_ac_automata/ACAutoMata.java
Normal file
131
java/36_ac_automata/ACAutoMata.java
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wayne
|
||||||
|
*/
|
||||||
|
public class ACAutoMata {
|
||||||
|
private ACNode root;
|
||||||
|
|
||||||
|
public ACAutoMata() {
|
||||||
|
this.root = new ACNode("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insert (String pattern) {
|
||||||
|
ACNode node = this.root;
|
||||||
|
int len = pattern.length();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
String c = pattern.charAt(i) + "";
|
||||||
|
if(Objects.isNull(node.children.get(c))) {
|
||||||
|
node.children.put(c, new ACNode(c));
|
||||||
|
}
|
||||||
|
node = node.children.get(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.isEndingChar = true;
|
||||||
|
node.length = pattern.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildFailurePointer() {
|
||||||
|
ACNode root = this.root;
|
||||||
|
LinkedList<ACNode> queue = new LinkedList<>();
|
||||||
|
queue.add(root);
|
||||||
|
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
ACNode p = queue.pop();
|
||||||
|
|
||||||
|
for(ACNode pc: p.children.values()){
|
||||||
|
if (Objects.isNull(pc)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p == root) {
|
||||||
|
pc.fail = root;
|
||||||
|
} else {
|
||||||
|
ACNode q = p.fail;
|
||||||
|
while (Objects.nonNull(q)) {
|
||||||
|
ACNode qc = q.children.get(pc.data);
|
||||||
|
if(Objects.nonNull(qc)) {
|
||||||
|
pc.fail = qc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
q = q.fail;
|
||||||
|
}
|
||||||
|
if(Objects.isNull(q)) {
|
||||||
|
pc.fail = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue.add(pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean match (String text) {
|
||||||
|
ACNode root = this.root;
|
||||||
|
ACNode p = root;
|
||||||
|
|
||||||
|
int n = text.length();
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
String c = text.charAt(i) + "";
|
||||||
|
while(Objects.isNull(p.children.get(c)) && p != root){
|
||||||
|
p = p.fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p.children.get(c);
|
||||||
|
if(Objects.isNull(p)) {
|
||||||
|
p = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACNode tmp = p;
|
||||||
|
while ( tmp != root) {
|
||||||
|
if (tmp.isEndingChar == true) {
|
||||||
|
System.out.println("Start from " + (i - p.length + 1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tmp = tmp.fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean match(String text, String[] patterns) {
|
||||||
|
ACAutoMata automata = new ACAutoMata();
|
||||||
|
for (String pattern: patterns) {
|
||||||
|
automata.insert(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
automata.buildFailurePointer();
|
||||||
|
return automata.match(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ACNode {
|
||||||
|
private String data;
|
||||||
|
private Map<String, ACNode> children;
|
||||||
|
private Boolean isEndingChar;
|
||||||
|
private Integer length;
|
||||||
|
private ACNode fail;
|
||||||
|
|
||||||
|
public ACNode(String data) {
|
||||||
|
this.data = data;
|
||||||
|
this.children = new HashMap<>();
|
||||||
|
this.isEndingChar = false;
|
||||||
|
this.length = 0;
|
||||||
|
this.fail = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String[] patterns = {"at", "art", "oars", "soar"};
|
||||||
|
String text = "soarsoars";
|
||||||
|
System.out.println(match(text, patterns));
|
||||||
|
|
||||||
|
String[] patterns2 = {"Fxtec Pro1", "谷歌Pixel"};
|
||||||
|
|
||||||
|
String text2 = "一家总部位于伦敦的公司Fxtex在MWC上就推出了一款名为Fxtec Pro1的手机,该机最大的亮点就是采用了侧滑式全键盘设计。DxOMark年度总榜发布 华为P20 Pro/谷歌Pixel 3争冠";
|
||||||
|
System.out.println(match(text2, patterns2));
|
||||||
|
}
|
||||||
|
}
|
@ -86,7 +86,7 @@ LList.insert('curry', 'chen')
|
|||||||
LList.insert('sang', 'head')
|
LList.insert('sang', 'head')
|
||||||
LList.insert('zhao', 'head')
|
LList.insert('zhao', 'head')
|
||||||
console.log('-------------remove item------------')
|
console.log('-------------remove item------------')
|
||||||
LList.remove('curry', 'chen')
|
LList.remove('curry')
|
||||||
LList.display()
|
LList.display()
|
||||||
console.log('-------------find by item------------')
|
console.log('-------------find by item------------')
|
||||||
LList.findByValue('chen')
|
LList.findByValue('chen')
|
||||||
|
40
javascript/12_sorts/KthNum.js
Normal file
40
javascript/12_sorts/KthNum.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* 第k大的数
|
||||||
|
* @param {array} arr
|
||||||
|
* @param {number} k
|
||||||
|
*/
|
||||||
|
function kthNum(arr, k) {
|
||||||
|
const len = arr.length;
|
||||||
|
if (k > len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
let p = partition(arr, 0, len - 1);
|
||||||
|
while (p + 1 !== k) {
|
||||||
|
if (p + 1 > k) {
|
||||||
|
p = partition(arr, 0, p - 1);
|
||||||
|
} else {
|
||||||
|
p = partition(arr, p + 1, len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
function partition(arr, start, end) {
|
||||||
|
let i = start;
|
||||||
|
let pivot = arr[end];
|
||||||
|
for (let j = start; j < end; j++) {
|
||||||
|
if (arr[j] > pivot) {
|
||||||
|
swap(arr, i, j);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swap(arr, i, end);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
function swap(arr, i, j) {
|
||||||
|
if (i === j) return;
|
||||||
|
let tmp = arr[i];
|
||||||
|
arr[i] = arr[j];
|
||||||
|
arr[j] = tmp;
|
||||||
|
}
|
109
javascript/36_ac_automata/ac_automata_unicode.js
Normal file
109
javascript/36_ac_automata/ac_automata_unicode.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
class ACNode {
|
||||||
|
constructor(data){
|
||||||
|
this.data = data;
|
||||||
|
this.children = new Map();
|
||||||
|
this.isEndingChar = false;
|
||||||
|
this.length = 0;
|
||||||
|
this.fail = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ACTree {
|
||||||
|
|
||||||
|
constructor(data){
|
||||||
|
this.root = new ACNode('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
insert (text) {
|
||||||
|
let node = this.root;
|
||||||
|
for (let char of text) {
|
||||||
|
if(!node.children.get(char)) {
|
||||||
|
node.children.set(char, new ACNode(char));
|
||||||
|
}
|
||||||
|
node = node.children.get(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.isEndingChar = true;
|
||||||
|
node.length = text.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFailurePointer() {
|
||||||
|
let root = this.root;
|
||||||
|
let queue = [];
|
||||||
|
queue.push(root);
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
let p = queue.shift();
|
||||||
|
|
||||||
|
for(var pc of p.children.values()){
|
||||||
|
if (!pc) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p == root) {
|
||||||
|
pc.fail = root;
|
||||||
|
} else {
|
||||||
|
let q = p.fail;
|
||||||
|
while (q) {
|
||||||
|
let qc = q.children.get(pc.data);
|
||||||
|
if(qc) {
|
||||||
|
pc.fail = qc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
q = q.fail;
|
||||||
|
}
|
||||||
|
if(!q) {
|
||||||
|
pc.fail = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue.push(pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (text) {
|
||||||
|
let root = this.root;
|
||||||
|
let n = text.length;
|
||||||
|
let p = root;
|
||||||
|
|
||||||
|
for(let i = 0; i < n; i++) {
|
||||||
|
let char = text[i];
|
||||||
|
while(!p.children.get(char) && p != root){
|
||||||
|
p = p.fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p.children.get(char);
|
||||||
|
if(!p) {
|
||||||
|
p = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tmp = p;
|
||||||
|
while ( tmp != root) {
|
||||||
|
if (tmp.isEndingChar == true) {
|
||||||
|
console.log(`Start from ${i - p.length + 1}, length: ${p.length}`);
|
||||||
|
}
|
||||||
|
tmp = tmp.fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function match( text, patterns) {
|
||||||
|
let automata = new ACTree();
|
||||||
|
for (let pattern of patterns) {
|
||||||
|
automata.insert(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
automata.buildFailurePointer();
|
||||||
|
automata.match(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
let patterns = ["at", "art", "oars", "soar"];
|
||||||
|
let text = "soarsoars";
|
||||||
|
match(text, patterns);
|
||||||
|
|
||||||
|
let patterns2 = ["Fxtec Pro1", "谷歌Pixel"];
|
||||||
|
let text2 = "一家总部位于伦敦的公司Fxtex在MWC上就推出了一款名为Fxtec Pro1的手机,该机最大的亮点就是采用了侧滑式全键盘设计。DxOMark年度总榜发布 华为P20 Pro/谷歌Pixel 3争冠";
|
||||||
|
match(text2, patterns2);
|
||||||
|
|
91
javascript/43_topological_sorting/dsf.js
Normal file
91
javascript/43_topological_sorting/dsf.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
function Graph() {
|
||||||
|
var graph = {
|
||||||
|
adj: new Map(),
|
||||||
|
addEdge: function (from, to){
|
||||||
|
if(!this.adj.get(from)) {
|
||||||
|
this.adj.set(from, [ to ]);
|
||||||
|
} else {
|
||||||
|
this.adj.get(from).push(to);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sortingByDsf: function(){
|
||||||
|
var inverseAdj = new Map();
|
||||||
|
var keys = this.adj.keys();
|
||||||
|
for(let key of keys) {
|
||||||
|
let blk = this.adj.get(key);
|
||||||
|
if(blk) {
|
||||||
|
for(let v of blk) {
|
||||||
|
if(!inverseAdj.get(v)) {
|
||||||
|
inverseAdj.set(v, [key]);
|
||||||
|
} else {
|
||||||
|
inverseAdj.get(v).push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let inKeys = inverseAdj.keys();
|
||||||
|
let vertexes = new Set([...keys, ...inKeys]);
|
||||||
|
let visited = [];
|
||||||
|
for(let vertex of vertexes) {
|
||||||
|
if(!visited.includes(vertex)) {
|
||||||
|
visited.push(vertex);
|
||||||
|
this.dsf(vertex, inverseAdj, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dsf: function(vertex, inverseAdj, visited) {
|
||||||
|
if(!inverseAdj.get(vertex)) {
|
||||||
|
inverseAdj.set(vertex, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let v of inverseAdj.get(vertex)) {
|
||||||
|
if(visited.includes(v)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visited.push(v);
|
||||||
|
|
||||||
|
this.dsf(v, inverseAdj, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("->" + vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dag = new Graph();
|
||||||
|
dag.addEdge(2, 1);
|
||||||
|
dag.addEdge(3, 2);
|
||||||
|
dag.addEdge(2, 4);
|
||||||
|
dag.addEdge(4, 1);
|
||||||
|
dag.sortingByDsf();
|
||||||
|
|
||||||
|
|
||||||
|
var dag2 = new Graph();
|
||||||
|
dag2.addEdge("main", "parse_options");
|
||||||
|
dag2.addEdge("main", "tail_file");
|
||||||
|
dag2.addEdge("main", "tail_forever");
|
||||||
|
dag2.addEdge("tail_file", "pretty_name");
|
||||||
|
dag2.addEdge("tail_file", "write_header");
|
||||||
|
dag2.addEdge("tail_file", "tail");
|
||||||
|
dag2.addEdge("tail_forever", "recheck");
|
||||||
|
dag2.addEdge("tail_forever", "pretty_name");
|
||||||
|
dag2.addEdge("tail_forever", "write_header");
|
||||||
|
dag2.addEdge("tail_forever", "dump_remainder");
|
||||||
|
dag2.addEdge("tail", "tail_lines");
|
||||||
|
dag2.addEdge("tail", "tail_bytes");
|
||||||
|
dag2.addEdge("tail_lines", "start_lines");
|
||||||
|
dag2.addEdge("tail_lines", "dump_remainder");
|
||||||
|
dag2.addEdge("tail_lines", "file_lines");
|
||||||
|
dag2.addEdge("tail_lines", "pipe_lines");
|
||||||
|
dag2.addEdge("tail_bytes", "xlseek");
|
||||||
|
dag2.addEdge("tail_bytes", "start_bytes");
|
||||||
|
dag2.addEdge("tail_bytes", "dump_remainder");
|
||||||
|
dag2.addEdge("tail_bytes", "pipe_bytes");
|
||||||
|
dag2.addEdge("file_lines", "dump_remainder");
|
||||||
|
dag2.addEdge("recheck", "pretty_name");
|
||||||
|
dag2.sortingByDsf();
|
44
javascript/45_bitmap/bitmap.js
Normal file
44
javascript/45_bitmap/bitmap.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
class BitMap {
|
||||||
|
constructor(n) {
|
||||||
|
this.nbits = n;
|
||||||
|
this.blk = new Array(Math.floor(n / 16) + 1);
|
||||||
|
this.blk.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(k) {
|
||||||
|
if( k > this.nbits) return false;
|
||||||
|
|
||||||
|
let byteIndex = Math.floor(k / 16);
|
||||||
|
let bitIndex = k % 16;
|
||||||
|
|
||||||
|
return !((this.blk[byteIndex] & (1 << bitIndex)) === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(k) {
|
||||||
|
if( k > this.nbits) return;
|
||||||
|
|
||||||
|
let byteIndex = Math.floor(k / 16);
|
||||||
|
let bitIndex = k % 16;
|
||||||
|
|
||||||
|
this.blk[byteIndex] = this.blk[byteIndex] | (1 << bitIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let aBitMap = new BitMap(20);
|
||||||
|
|
||||||
|
aBitMap.set(1);
|
||||||
|
aBitMap.set(3);
|
||||||
|
aBitMap.set(5);
|
||||||
|
aBitMap.set(7);
|
||||||
|
aBitMap.set(9);
|
||||||
|
aBitMap.set(11);
|
||||||
|
aBitMap.set(13);
|
||||||
|
aBitMap.set(15);
|
||||||
|
aBitMap.set(17);
|
||||||
|
aBitMap.set(19);
|
||||||
|
|
||||||
|
for(let i = 0; i < 21; i++) {
|
||||||
|
console.log(aBitMap.get(i));
|
||||||
|
}
|
@ -52,7 +52,7 @@ class MyArray
|
|||||||
*/
|
*/
|
||||||
private function checkOutOfRange($index)
|
private function checkOutOfRange($index)
|
||||||
{
|
{
|
||||||
if($index > $this->length+1) {
|
if($index >= $this->length) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -68,18 +68,16 @@ class MyArray
|
|||||||
{
|
{
|
||||||
$index = intval($index);
|
$index = intval($index);
|
||||||
$value = intval($value);
|
$value = intval($value);
|
||||||
if($index < 0) {
|
if ($index < 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if($this->checkIfFull()) {
|
|
||||||
|
if ($this->checkIfFull()) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if($this->checkOutOfRange($index)) {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
for($i=$this->length-1;$i>=$index;$i--) {
|
for ($i = $this->length - 1; $i >= $index; $i--) {
|
||||||
$this->data[$i+1] = $this->data[$i];
|
$this->data[$i + 1] = $this->data[$i];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->data[$index] = $value;
|
$this->data[$index] = $value;
|
||||||
@ -96,22 +94,21 @@ class MyArray
|
|||||||
{
|
{
|
||||||
$value = 0;
|
$value = 0;
|
||||||
$index = intval($index);
|
$index = intval($index);
|
||||||
if($index < 0) {
|
if ($index < 0) {
|
||||||
$code = 1;
|
$code = 1;
|
||||||
return array($code, $value);
|
return [$code, $value];
|
||||||
}
|
}
|
||||||
if($index != $this->length+1 && $this->checkOutOfRange($index)) {
|
if ($this->checkOutOfRange($index)) {
|
||||||
$code = 2;
|
$code = 2;
|
||||||
return array($code, $value);
|
return [$code, $value];
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $this->data[$index];
|
$value = $this->data[$index];
|
||||||
for($i=$index;$i<$this->length-1;$i++) {
|
for ($i = $index; $i < $this->length - 1; $i++) {
|
||||||
$this->data[$i] = $this->data[$i+1];
|
$this->data[$i] = $this->data[$i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->length--;
|
$this->length--;
|
||||||
return array(0, $value);
|
return [0, $value];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,23 +120,23 @@ class MyArray
|
|||||||
{
|
{
|
||||||
$value = 0;
|
$value = 0;
|
||||||
$index = intval($index);
|
$index = intval($index);
|
||||||
if($index < 0) {
|
if ($index < 0) {
|
||||||
$code = 1;
|
$code = 1;
|
||||||
return array($code, $value);
|
return [$code, $value];
|
||||||
}
|
}
|
||||||
if($this->checkOutOfRange($index)) {
|
if ($this->checkOutOfRange($index)) {
|
||||||
$code = 2;
|
$code = 2;
|
||||||
return array($code, $value);
|
return [$code, $value];
|
||||||
}
|
}
|
||||||
return array(0, $this->data[$index]);
|
return [0, $this->data[$index]];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function printData()
|
public function printData()
|
||||||
{
|
{
|
||||||
$format = "";
|
$format = "";
|
||||||
for($i=0;$i<$this->length;$i++) {
|
for ($i = 0; $i < $this->length; $i++) {
|
||||||
$format .= "|".$this->data[$i];
|
$format .= "|" . $this->data[$i];
|
||||||
}
|
}
|
||||||
print($format."\n");
|
print($format . "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ Class SingleLinkedListAlgo
|
|||||||
++$i;
|
++$i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($fast == null) {
|
if (null == $fast) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,4 +305,4 @@ echo '---------------------- 求链表的中间结点 ----------------------' .
|
|||||||
$listAlgo->setList($list);
|
$listAlgo->setList($list);
|
||||||
$middleNode = $listAlgo->findMiddleNode();
|
$middleNode = $listAlgo->findMiddleNode();
|
||||||
var_dump($middleNode->data);
|
var_dump($middleNode->data);
|
||||||
echo '-------------------------------------------------------------'. PHP_EOL . PHP_EOL;
|
echo '-------------------------------------------------------------'. PHP_EOL . PHP_EOL;
|
||||||
|
@ -13,7 +13,7 @@ function expression($str)
|
|||||||
$operStack[] = NULL;
|
$operStack[] = NULL;
|
||||||
|
|
||||||
for ($i = 0; $i < count($arr); $i++){
|
for ($i = 0; $i < count($arr); $i++){
|
||||||
if (ord($arr[$i]) >= 48 && ord($arr[$i] <= 57)){
|
if (ord($arr[$i]) >= 48 && ord($arr[$i]) <= 57){
|
||||||
array_push($numStack, $arr[$i]);
|
array_push($numStack, $arr[$i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -85,4 +85,4 @@ function compute(&$numStack, &$operStack){
|
|||||||
}
|
}
|
||||||
expression('-1+2-(1+2*3)');
|
expression('-1+2-(1+2*3)');
|
||||||
echo PHP_EOL;
|
echo PHP_EOL;
|
||||||
eval('echo -1+2-(1+2*3);');
|
eval('echo -1+2-(1+2*3);');
|
||||||
|
@ -1,24 +1,67 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// 冒泡排序
|
||||||
function insertSort(&$arr)
|
function bubbleSort(&$arr)
|
||||||
{
|
{
|
||||||
$i = 0;
|
$length = count($arr);
|
||||||
$len = count($arr);
|
if ($length <= 1) return;
|
||||||
|
|
||||||
while($i < $len){
|
for ($i = 0; $i < $length; $i++) {
|
||||||
$data = $arr[$i+1];
|
$flag = false;
|
||||||
for ($j = $i;$j >=0 ;$j-- ){
|
for ($j = 0; $j < $length - $i - 1; $j++) {
|
||||||
if ($data >= $arr[$j]){
|
if ($arr[$i] > $arr[$j + 1]) {
|
||||||
array_splice($arr, $i+1, 1);
|
$tmp = $arr[$j];
|
||||||
array_splice($arr, ++$j, 0, $data);
|
$arr[$j] = $arr[$j + 1];
|
||||||
|
$arr[$j + 1] = $tmp;
|
||||||
|
$flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$flag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入排序
|
||||||
|
function insertionSort(&$arr)
|
||||||
|
{
|
||||||
|
$n = count($arr);
|
||||||
|
if ($n <= 1) return;
|
||||||
|
|
||||||
|
for ($i = 1; $i < $n; ++$i) {
|
||||||
|
$value = $arr[$i];
|
||||||
|
$j = $i - 1;
|
||||||
|
// 查找插入的位置
|
||||||
|
for (; $j >= 0; --$j) {
|
||||||
|
if ($arr[$j] > $value) {
|
||||||
|
$arr[$j + 1] = $arr[$j]; // 数据移动
|
||||||
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$arr[$j + 1] = $value; // 插入数据
|
||||||
$i++;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择排序
|
||||||
|
function selectionSort(&$arr)
|
||||||
|
{
|
||||||
|
$length = count($arr);
|
||||||
|
if ($length <= 1) return;
|
||||||
|
|
||||||
|
for ($i = 0; $i < $length - 1; $i++) {
|
||||||
|
//先假设最小的值的位置
|
||||||
|
$p = $i;
|
||||||
|
for ($j = $i + 1; $j < $length; $j++) {
|
||||||
|
if ($arr[$p] > $arr[$j]) {
|
||||||
|
$p = $j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tmp = $arr[$p];
|
||||||
|
$arr[$p] = $arr[$i];
|
||||||
|
$arr[$i] = $tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$arr = [1,4,6,2,3,5,4];
|
$arr = [1,4,6,2,3,5,4];
|
||||||
insertSort($arr);
|
insertionSort($arr);
|
||||||
var_dump($arr);
|
var_dump($arr);
|
||||||
|
@ -1,40 +1,48 @@
|
|||||||
<?php
|
<?php
|
||||||
|
/*
|
||||||
|
* 归并排序
|
||||||
|
*/
|
||||||
|
|
||||||
$arr = [4, 5, 6, 1, 3, 2];
|
$arr = [4, 5, 6, 1, 3, 2];
|
||||||
$length = count($arr);
|
$length = count($arr);
|
||||||
|
|
||||||
$p = 0;
|
$p = 0;
|
||||||
$r = $length - 1;
|
$r = $length - 1;
|
||||||
|
|
||||||
$result = $this->mergeSort($arr, $p, $r);
|
$result = mergeSort($arr, $p, $r);
|
||||||
|
|
||||||
var_dump($result);
|
var_dump($result);
|
||||||
|
|
||||||
|
|
||||||
//递归调用,分解数组
|
|
||||||
function mergeSort(array $arr, $p, $r)
|
function mergeSort(array $arr, $p, $r)
|
||||||
{
|
{
|
||||||
|
return mergeSortRecursive($arr, $p, $r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归调用函数
|
||||||
|
function mergeSortRecursive(array $arr, $p, $r)
|
||||||
|
{
|
||||||
|
// 递归终止条件
|
||||||
if ($p >= $r) {
|
if ($p >= $r) {
|
||||||
return [$arr[$r]];
|
return [$arr[$r]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 取 p 到 r 之间的中间位置 q
|
||||||
$q = (int)(($p + $r) / 2);
|
$q = (int)(($p + $r) / 2);
|
||||||
|
|
||||||
$left = $this->mergeSort($arr, $p, $q);
|
// 分治递归
|
||||||
$right = $this->mergeSort($arr, $q + 1, $r);
|
$left = mergeSortRecursive($arr, $p, $q);
|
||||||
return $this->merge($left, $right);
|
$right = mergeSortRecursive($arr, $q + 1, $r);
|
||||||
|
return merge($left, $right);
|
||||||
}
|
}
|
||||||
|
|
||||||
//合并
|
// 合并
|
||||||
function merge(array $left, array $right)
|
function merge(array $left, array $right)
|
||||||
{
|
{
|
||||||
$tmp = [];
|
$tmp = [];
|
||||||
|
$i = $j = 0;
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
$j = 0;
|
|
||||||
|
|
||||||
$leftLength = count($left);
|
$leftLength = count($left);
|
||||||
|
|
||||||
$rightLength = count($right);
|
$rightLength = count($right);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -43,24 +51,23 @@ function merge(array $left, array $right)
|
|||||||
} else {
|
} else {
|
||||||
$tmp[] = $right[$j++];
|
$tmp[] = $right[$j++];
|
||||||
}
|
}
|
||||||
|
|
||||||
} while ($i < $leftLength && $j < $rightLength);
|
} while ($i < $leftLength && $j < $rightLength);
|
||||||
|
|
||||||
|
|
||||||
$start = $i;
|
$start = $i;
|
||||||
$end = $leftLength;
|
$end = $leftLength;
|
||||||
$copyArr = $left;
|
$copyArr = $left;
|
||||||
|
|
||||||
|
// 判断哪个子数组中有剩余的数据
|
||||||
if ($j < $rightLength) {
|
if ($j < $rightLength) {
|
||||||
$start = $j;
|
$start = $j;
|
||||||
$end = $rightLength;
|
$end = $rightLength;
|
||||||
$copyArr = $right;
|
$copyArr = $right;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; $start < $end; $start++) {
|
// 将剩余的数据拷贝到临时数组 tmp
|
||||||
$tmp[] = $copyArr[$start];
|
do {
|
||||||
}
|
$tmp[] = $copyArr[$start++];
|
||||||
|
} while ($start < $end);
|
||||||
|
|
||||||
return $tmp;
|
return $tmp;
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user