Merge pull request #4 from wangzheng0822/master

update
This commit is contained in:
Qiyuan Jiao 2019-04-29 10:33:14 +08:00 committed by GitHub
commit 9e8e091286
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 965 additions and 86 deletions

4
.gitignore vendored
View File

@ -45,3 +45,7 @@ bld/
# Visual Studio 2015/2017 cache/options directory
.vs/
**/*.idea
**/*.iml
**/*out

136
DynamicStackBaseArray.java Normal file
View 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());
}
}
}

View File

@ -1,5 +1,7 @@
# 数据结构和算法必知必会的50个代码实现
## (关注“小争哥”公众号,获取我的更多技术、非技术分享)
### 微信搜索我的公众号“小争哥”,或者微信扫描下面二维码, 获取更多压箱底的干货分享
![t2](https://github.com/wangzheng0822/markdownphotos/blob/master/pics/qrcode_for_gh_9b0e7afdff20_258.jpg)
## 数组
* 实现一个支持动态扩容的数组

64
StackBaseArray.java Normal file
View 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());
}
}

View File

@ -47,7 +47,7 @@ int delete(struct array *array, int idx)
return -1;
memmove(&array->arr[idx], &array->arr[idx+1],
(array->used - idx) * sizeof(int));
(array->used - idx - 1) * sizeof(int));
array->used--;
return 0;
}

View 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]
}
}

View 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)
}

View 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]
}

View 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)
// }

View File

@ -0,0 +1,3 @@
## TODO
- 该实现方式不能保证 相同优先级的元素在出队列时 和入队列的顺序是一致的

View 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
}

View File

@ -13,21 +13,14 @@ public class LinkedListAlgo {
// 单链表反转
public static Node reverse(Node list) {
Node headNode = null;
Node previousNode = null;
Node currentNode = list;
while (currentNode != null) {
Node nextNode = currentNode.next;
if (nextNode == null) {
headNode = currentNode;
Node curr = list, pre = null;
while (curr != null) {
Node next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
currentNode.next = previousNode;
previousNode = currentNode;
currentNode = nextNode;
}
return headNode;
return pre;
}
// 检测环

View File

@ -5,7 +5,7 @@ package stack;
*
* Author: Zheng
*/
public class StackBasedLinkedList {
public class StackBasedOnLinkedList {
private Node top = null;
public void push(int value) {

View File

@ -27,8 +27,9 @@ public class KthSmallest {
int pivot = arr[r];
int i = p;
for (int j = p; j <= r - 1; j++) {
if (arr[j] < pivot) {
for (int j = p; j < r; j++) {
// 这里要是 <= 不然会出现死循环比如查找数组 [1,1,2] 的第二小的元素
if (arr[j] <= pivot) {
swap(arr, i, j);
i++;
}

View 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));
}
}

View File

@ -86,7 +86,7 @@ LList.insert('curry', 'chen')
LList.insert('sang', 'head')
LList.insert('zhao', 'head')
console.log('-------------remove item------------')
LList.remove('curry', 'chen')
LList.remove('curry')
LList.display()
console.log('-------------find by item------------')
LList.findByValue('chen')

View 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;
}

View 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);

View 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();

View 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));
}

View File

@ -52,7 +52,7 @@ class MyArray
*/
private function checkOutOfRange($index)
{
if($index > $this->length+1) {
if($index >= $this->length) {
return true;
}
return false;
@ -71,12 +71,10 @@ class MyArray
if ($index < 0) {
return 1;
}
if ($this->checkIfFull()) {
return 2;
}
if($this->checkOutOfRange($index)) {
return 3;
}
for ($i = $this->length - 1; $i >= $index; $i--) {
$this->data[$i + 1] = $this->data[$i];
@ -98,20 +96,19 @@ class MyArray
$index = intval($index);
if ($index < 0) {
$code = 1;
return array($code, $value);
return [$code, $value];
}
if($index != $this->length+1 && $this->checkOutOfRange($index)) {
if ($this->checkOutOfRange($index)) {
$code = 2;
return array($code, $value);
return [$code, $value];
}
$value = $this->data[$index];
for ($i = $index; $i < $this->length - 1; $i++) {
$this->data[$i] = $this->data[$i + 1];
}
$this->length--;
return array(0, $value);
return [0, $value];
}
/**
@ -125,13 +122,13 @@ class MyArray
$index = intval($index);
if ($index < 0) {
$code = 1;
return array($code, $value);
return [$code, $value];
}
if ($this->checkOutOfRange($index)) {
$code = 2;
return array($code, $value);
return [$code, $value];
}
return array(0, $this->data[$index]);
return [0, $this->data[$index]];
}
public function printData()

View File

@ -191,7 +191,7 @@ Class SingleLinkedListAlgo
++$i;
}
if ($fast == null) {
if (null == $fast) {
return true;
}

View File

@ -13,7 +13,7 @@ function expression($str)
$operStack[] = NULL;
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]);
continue;
}

View File

@ -1,24 +1,67 @@
<?php
function insertSort(&$arr)
// 冒泡排序
function bubbleSort(&$arr)
{
$i = 0;
$len = count($arr);
$length = count($arr);
if ($length <= 1) return;
while($i < $len){
$data = $arr[$i+1];
for ($j = $i;$j >=0 ;$j-- ){
if ($data >= $arr[$j]){
array_splice($arr, $i+1, 1);
array_splice($arr, ++$j, 0, $data);
for ($i = 0; $i < $length; $i++) {
$flag = false;
for ($j = 0; $j < $length - $i - 1; $j++) {
if ($arr[$i] > $arr[$j + 1]) {
$tmp = $arr[$j];
$arr[$j] = $arr[$j + 1];
$arr[$j + 1] = $tmp;
$flag = true;
}
}
if (!$flag) {
break;
}
}
}
$i++;
// 插入排序
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;
}
}
$arr[$j + 1] = $value; // 插入数据
}
}
// 选择排序
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];
insertSort($arr);
insertionSort($arr);
var_dump($arr);

View File

@ -1,4 +1,7 @@
<?php
/*
* 归并排序
*/
$arr = [4, 5, 6, 1, 3, 2];
$length = count($arr);
@ -6,35 +9,40 @@
$p = 0;
$r = $length - 1;
$result = $this->mergeSort($arr, $p, $r);
$result = mergeSort($arr, $p, $r);
var_dump($result);
//递归调用,分解数组
function mergeSort(array $arr, $p, $r)
{
return mergeSortRecursive($arr, $p, $r);
}
// 递归调用函数
function mergeSortRecursive(array $arr, $p, $r)
{
// 递归终止条件
if ($p >= $r) {
return [$arr[$r]];
}
// 取 p 到 r 之间的中间位置 q
$q = (int)(($p + $r) / 2);
$left = $this->mergeSort($arr, $p, $q);
$right = $this->mergeSort($arr, $q + 1, $r);
return $this->merge($left, $right);
// 分治递归
$left = mergeSortRecursive($arr, $p, $q);
$right = mergeSortRecursive($arr, $q + 1, $r);
return merge($left, $right);
}
// 合并
function merge(array $left, array $right)
{
$tmp = [];
$i = 0;
$j = 0;
$i = $j = 0;
$leftLength = count($left);
$rightLength = count($right);
do {
@ -43,24 +51,23 @@ function merge(array $left, array $right)
} else {
$tmp[] = $right[$j++];
}
} while ($i < $leftLength && $j < $rightLength);
$start = $i;
$end = $leftLength;
$copyArr = $left;
// 判断哪个子数组中有剩余的数据
if ($j < $rightLength) {
$start = $j;
$end = $rightLength;
$copyArr = $right;
}
for (; $start < $end; $start++) {
$tmp[] = $copyArr[$start];
}
// 将剩余的数据拷贝到临时数组 tmp
do {
$tmp[] = $copyArr[$start++];
} while ($start < $end);
return $tmp;
}