diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..dd84ea7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,38 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Smartphone (please complete the following information):**
+ - Device: [e.g. iPhone6]
+ - OS: [e.g. iOS8.1]
+ - Browser [e.g. stock browser, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md
new file mode 100644
index 0000000..48d5f81
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/custom.md
@@ -0,0 +1,10 @@
+---
+name: Custom issue template
+about: Describe this issue template's purpose here.
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..bbcbbe7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8d6193c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.idea/
+.DS_Store
+composer.lock
+vendor
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 14d23d6..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-language: php
-sudo: false
-php:
- - 5.5
- - 5.6
- - 7.0
-
-services:
- - mysql
-
-before_install:
- - travis_retry composer self-update
-
-install:
- - travis_retry composer install
-
-script: vendor/bin/phpunit
-
-matrix:
- allow_failures:
- - php: 5.6
- fast_finish: true
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..cc8499a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,15 @@
+What does “open source” mean?
+
+When a project is open source, that means anybody can view, use, modify, and distribute your project for any purpose. These permissions are enforced through an open source license.
+
+Open source is powerful because it lowers the barriers to adoption, allowing ideas to spread quickly.
+
+To understand how it works, imagine your friend is having a potluck, and you bring a cherry pie.
+
+Everybody tries the pie (use)
+The pie is a hit! They ask you for the recipe, which you provide (view)
+One friend, Alex, who’s a pastry chef, suggests reducing the sugar (modify)
+Another friend, Lisa, asks to use it for a dinner next week (distribute)
+By comparison, a closed source process would be going to a restaurant and ordering a slice of cherry pie. You must pay a fee to eat the pie, and the restaurant probably won’t give you their recipe. If you copied their pie exactly and sold it under your own name, the restaurant could take action against you.
+
+Why do people open source their work?
diff --git a/README-EN.md b/README-EN.md
index 7cfdcce..8aeeaef 100644
--- a/README-EN.md
+++ b/README-EN.md
@@ -1,4 +1,4 @@
-
:whale:A collection of algorithms that are implemented in PHP:whale:
+:whale:A collection of algorithms that are implemented in PHP:whale:
@@ -17,102 +17,133 @@
- 中文版
+
中文版
## Simple structure,
-
- ├──Package
- │ ├── Sort
- │ │ ├── BubbleSort.php
- │ │ ├── QuickSort.php
- │ │ ├── ShellSort.php
- │ │ ├── MergeSort.php
- │ │ ├── InsertSort.php
- │ │ └── SelectSort.php
- │ │
- │ ├── Query 查找篇
- │ │ ├── BinaryQuery.php
- │ │ ├── InseertQuery.php
- │ │ ├── FibonacciQuery.php
- │ │ └── QulickQuery.php
- │ │
- │ └── Other 其他
- │ ├── MonkeyKing.php
- │ ├── DynamicProgramming.php
- │ ├── Fibonacci.php
- │ ├── StealingApples.php
- │ ├── HanoiGames.php
- │ ├── BidirectionalQueue.php
- │ ├── ColorBricks.php
- │ ├── GetCattle.php
- │ ├── OnlyNumbers.php
- │ └── BigSmallReplace.php
- │
- ├──LICENSE
- └──README.md
+
+```
+├──Package
+│ ├── Sort
+│ │ ├── BubbleSort.php
+│ │ ├── QuickSort.php
+│ │ ├── ShellSort.php
+│ │ ├── MergeSort.php
+│ │ ├── InsertSort.php
+│ │ └── SelectSort.php
+│ │
+│ ├── Query 查找篇
+│ │ ├── BinaryQuery.php
+│ │ ├── InseertQuery.php
+│ │ ├── FibonacciQuery.php
+│ │ ├── BFSQuery.php
+│ │ ├── Kmp.php
+│ │ ├── DijkstraQuery.php
+│ │ └── QulickQuery.php
+│ │
+│ └── Other 其他
+│ ├── MonkeyKing.php
+│ ├── DynamicProgramming.php
+│ ├── Fibonacci.php
+│ ├── StealingApples.php
+│ ├── HanoiGames.php
+│ ├── BidirectionalQueue.php
+│ ├── ColorBricks.php
+│ ├── GetCattle.php
+│ ├── OnlyNumbers.php
+│ ├── Interval.php
+│ ├── Maze.php
+│ ├── AntsClimb.php
+│ ├── Encryption.php
+│ ├── ElevatorDispatch.php
+│ ├── kmp.php
+│ ├── TraversalOfBinary.php
+│ ├── PointInTriangle.php
+│ └── BigSmallReplace.php
+│ └── Knapsack.php
+│ └── Solution.php
+│ └── RotationSort.php
+│ └── Square.php
+│ └── Prim.php
+│ └── CartesianProduct.php
+│ └── Square.php
+│ └── Judge.php
+│ └── Factorial.php
+| └── HashTable.php
+| └── RotateSort.php
+│
+├──LICENSE
+└──README.md
+```
## What to do?
- To record their understanding algorithms, data structure, the process of simple comprehensive and detailed as possible, let the learning algorithm using flexible, refueling(ง •̀_•́)ง
+
+```
+To record their understanding algorithms, data structure, the process of simple comprehensive and detailed as possible, let the learning algorithm using flexible, refueling(ง •̀_•́)ง
+```
## logarithmic
+
log10100 It's equivalent to saying, "how many tens do you multiply?" the answer is, of course, two
so log10100=2,The logarithmic operation is the inverse of the power operation
-left|right
----|---
-23 = 8 | log28 = 3
-24 = 16 | log216 = 4
-25 = 32 | log232 = 5
+| left | right |
+| ------------------ | --------------------- |
+| 23 = 8 | log28 = 3 |
+| 24 = 16 | log216 = 4 |
+| 25 = 32 | log232 = 5 |
If you don't, we won't wait for you
## The elapsed time
+
Take binary search for example, how much time can you save by using it? Simply look for the Numbers and if the list contains 100 Numbers, you need to guess 100 times.
In other words, the number of guesses is the same as the length of the list, which is called linear time, while binary search is different if the list contains 100 elements
It takes up to seven times, and if the list contains four billion digits, it should be guessed 32 times, while the running time of the subsearch is logarithmic time `O(log)`
## Big O notation
+
The big O notation is a special representation of how fast the algorithm can be. There's a diaosi. In fact, you often have to copy other people's code.
In this case, you know how fast these algorithms are
- The running time of the algorithm increases at different speeds
- For example, the difference between a simple find and a binary search
-
-element|Easy to find|Binary search
----|---|---
-100|100ms|7ms
-10000|10s|14ms
-1 000 000 000 |11day|30ms
-
- - ` O ` said hair is pointed out that how fast algorithms, such as list contains ` n ` element, a simple search need to check each element, so you need to perform ` n ` time operations
- Using large ` O ` said ` O (n) to make this operation `, binary search need to perform logn using large ` O ` said to`O(log n)`
-- Some common big O runtime
- - O(log n) ,It's also called log time, and this algorithm includes binary algorithms
- - O(n),Also known as linear time, this algorithm includes simple lookups.
- - O(n * log n) Quick sort
- - O(n2),Selection sort
- - O(n!) Factorial time
-- Here is the point
- - The speed of the algorithm is not the time, but the growth of operands
- - When we talk about the speed of the algorithm, what we're talking about is how fast will it run as the input increases
- - The running time of the algorithm is expressed in large O notation
- - O(log n) is faster than O (n), and the more elements that need to be searched, the more the former is faster than the latter
+| element | Easy to find | Binary search |
+| ------------- | ------------ | ------------- |
+| 100 | 100ms | 7ms |
+| 10000 | 10s | 14ms |
+| 1 000 000 000 | 11day | 30ms |
+
+- ` O ` said hair is pointed out that how fast algorithms, such as list contains ` n ` element, a simple search need to check each element, so you need to perform ` n ` time operations
+ Using large ` O ` said ` O (n) to make this operation `, binary search need to perform logn using large ` O ` said to`O(log n)`
+ - Some common big O runtime
+- O(log n) ,It's also called log time, and this algorithm includes binary algorithms
+- O(n),Also known as linear time, this algorithm includes simple lookups.
+- O(n * log n) Quick sort
+- O(n2),Selection sort
+- O(n!) Factorial time
+ - Here is the point
+- The speed of the algorithm is not the time, but the growth of operands
+- When we talk about the speed of the algorithm, what we're talking about is how fast will it run as the input increases
+- The running time of the algorithm is expressed in large O notation
+- O(log n) is faster than O (n), and the more elements that need to be searched, the more the former is faster than the latter
## A simple comparison of recursion and loops:
1. From a procedural point of view, the recursion manifests itself as calling itself, and the loop does not have this form.
2. Recursive proceed from the ultimate goal of the problem, and gradually to a complex problem into a simple problem, and simple question solution and complicated problem, at the same time the presence of the benchmark, can eventually get a problem, is the reverse. And the circulation is from the simple question, step by step forward development, finally get the question, is positive.
3. Any cycle can be represented by recursion, but it is necessary to use the loop to achieve recursion (except for one-way recursion and tail recursion), and the stack structure must be introduced to stack the stack.
-4.In general, non-recursive efficiency is higher than recursion. And recursive function calls are expensive and recursive times are limited by stack size.
+ 4.In general, non-recursive efficiency is higher than recursion. And recursive function calls are expensive and recursive times are limited by stack size.
## Progressive learning
+
1. Fork 我的项目并提交你的 `idea`
2. Pull Request
3. Merge
-## 纠错
+## 纠错
+
If you find something wrong, you can initiate a [issue](https://github.com/PuShaoWei/designPatterns-go/issues)or [pull request](https://github.com/PuShaoWei/designPatterns-go/pulls),I will correct it in time
> 补充:发起pull request的commit message请参考文章[Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html)
@@ -122,9 +153,15 @@ If you find something wrong, you can initiate a [issue](https://github.com/PuSha
Thanks for the issue or pull request of the following friends:
- [hailwood ](https://github.com/hailwood)
+
- [zhangxuanru](https://github.com/zhangxuanru)
+
- [ifreesec](https://github.com/ifreesec)
+
- [openset](https://github.com/openset)
-## License
-MIT
\ No newline at end of file
+- [Neroxiezi](https://github.com/Neroxiezi)
+
+ ## License
+
+MIT
diff --git a/README.md b/README.md
index 7a41029..5217772 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
:whale: 用 PHP 的方式实现的各类算法合集 :whale:
+:whale: 用 PHP 的方式实现的各类算法合集 :whale:
@@ -17,89 +17,214 @@
+
English
+> 每周最少一更,求出题,求虐待 At least once a week, ask for problems and abuse
## 简易结构
- ├──Package
- │ ├── Sort 排序篇
- │ │ ├── BubbleSort.php 冒泡排序
- │ │ ├── QuickSort.php 快速排序
- │ │ ├── ShellSort.php 希尔排序
- │ │ ├── MergeSort.php 归并排序
- │ │ ├── InsertSort.php 插入排序
- │ │ └── SelectSort.php 选择排序
- │ │
- │ ├── Query 查找篇
- │ │ ├── BinaryQuery.php 二分查找
- │ │ ├── InseertQuery.php 插入查找
- │ │ ├── FibonacciQuery.php 斐波那契查找
- │ │ └── QulickQuery.php 快速查找
- │ │
- │ └── Other 其他
- │ ├── MonkeyKing.php 猴子选大王
- │ ├── DynamicProgramming.php 动态规划
- │ ├── Fibonacci.php 斐波那契数列
- │ ├── StealingApples.php 偷苹果求余
- │ ├── HanoiGames.php 汉诺塔游戏
- │ ├── BidirectionalQueue.php 双向队列
- │ ├── ColorBricks.php 彩色砖块
- │ ├── GetCattle.php 牛年求牛
- │ ├── OnlyNumbers.php 求唯一数
- │ ├── PokerGames.php 洗扑克牌
- │ └── BigSmallReplace.php Hello World 输出 Olleh Dlrow
- │
- ├──LICENSE
- └──README.md
+```
+├──Package
+│ ├── Sort 排序篇
+│ │ ├── BubbleSort.php 冒泡排序
+│ │ ├── HeapSort.php 堆排序 大根堆
+│ │ ├── MBaseSort.php 基数排序 MSD
+│ │ ├── LBaseSort.php 基数排序 LSD
+│ │ ├── QuickSort.php 快速排序
+│ │ ├── ShuttleSort.php 飞梭排序
+│ │ ├── ShellSort.php 希尔排序
+│ │ ├── MergeSort.php 归并排序
+│ │ ├── InsertSort.php 插入排序
+│ │ └── SelectSort.php 选择排序
+│ │
+│ ├── Query 查找篇
+│ │ ├── BinaryQuery.php 二分查找
+│ │ ├── InseertQuery.php 插入查找
+│ │ ├── FibonacciQuery.php 斐波那契查找
+│ │ ├── BFSQuery.php 广度优先查找
+│ ├── Kmp.php 算法导论-KMP算法
+│ ├── DijkstraQuery.php 迪克斯特拉算法
+│ │ └── QulickQuery.php 快速查找
+│ │
+│ ├── Structure 数据结构
+│ │ ├── StackExample.php 堆栈 先进后出 LIFO (Last In First Out)
+│ │ ├── LinearChain.php 线性表 单链存储
+│ │ └── LinearOrder.php 线性表 顺序存储
+│ │ └── BinarySearchTree.php 二叉搜索树
+│ │
+│ ├── Tools 小工具集
+│ │ └── SystemSwitch.php 堆栈实现进制转换
+│ │
+│ └── Other 其他
+│ ├── MonkeyKing.php 约瑟夫环
+│ ├── DynamicProgramming.php 动态规划
+│ ├── Fibonacci.php 斐波那契数列
+│ ├── StealingApples.php 偷苹果求余
+│ ├── HanoiGames.php 汉诺塔游戏
+│ ├── BidirectionalQueue.php 双向队列
+│ ├── ColorBricks.php 彩色砖块
+│ ├── GetCattle.php 牛年求牛
+│ ├── OnlyNumbers.php 求唯一数
+│ ├── PokerGames.php 洗扑克牌
+│ ├── Interval.php 抽奖区间算法
+│ ├── Maze.php 迷宫寻址算法
+│ ├── AntsClimb.php 蚂蚁爬杆算法
+│ ├── Encryption.php 对称加密算法
+│ ├── ElevatorDispatch.php 编程之美-电梯调度算法
+│ ├── PointInTriangle.php 向量叉集计算点是否在三角形中
+│ ├── TraversalOfBinary.php 二叉树非递归遍历算法实现
+│ ├── Knapsack.php 贪心算法之背包问题实现
+│ └── BigSmallReplace.php Hello World 输出 Olleh Dlrow
+│ └── Solution.php Facebook面试题之岛屿周长算法
+│ └── RotationSort.php Facebook面试题之顺时针回旋算法
+│ └── Square.php Facebook面试题之判断四个点能否组成正方形算法
+│ └── Prim.php Prim算法(最小生成树算法)
+│ └── CartesianProduct.php 笛卡尔积算法
+│ └── Square.php 面试题之平面任意四点能否组成一个矩形
+│ └── Judge.php 面试题之扑克牌中任选五张判断是不是顺子
+│ └── Factorial.php 面试题之N的阶乘末尾有多少个0
+| └── HashTable.php HashTable
+| └── RotateSort.php 面试题之风车旋转排序算法
+│
+├──LICENSE
+└──README.md
+```
## 要做什么?
- 记录自己理解算法,数据结构的过程,尽可能的简单全面以及详细,让算法学习运用灵活自如,加油(ง •̀_•́)ง
+
+```
+记录自己理解算法,数据结构的过程,尽可能的简单全面以及详细,让算法学习运用灵活自如,加油(ง •̀_•́)ง
+```
+
+## 当然
+
+```
+用 PHP 实现算法并替代官方提供的函数是愚蠢的事情 .但这决不代表斟酌算法就是件无意义的事 , 每个算法都是一种思想的结晶 , 学习优秀的思想 , 开拓思维
+```
+
+## 什么是算法?
+
+直白地说,算法就是任何明确定义的计算过程,它接收一些值或集合作为输入,并产生一些值或集合作为输出。这样,算法就是将输入转换为输出的一系列计算过程。来源:Thomas H. Cormen, Chales E. Leiserson (2009), 《算法导论第三版》。
+
+简而言之,我们可以说算法就是用来解决一个特定任务的一系列步骤(是的,不止计算机在使用算法,人类也同样如此)。目前,一个有效的算法应该含有三个重要特性:
+
+- 它必须是有限的:如果你设计的算法永无休止地尝试解决问题,那么它是无用的。
+- 它必须具备明确定义的指令:算法的每一步都必须准确定义,在任何场景下指令都应当没有歧义。
+- 它必须是有效的:一个算法被设计用以解决某个问题,那么它就应当能解决这个问题,并且仅仅使用纸和笔就能证明该算法是收敛的。
## 对数
-log10100 相当于问"降多少个10相乘的结果为100",答案当然是2个了
-因此log10100=2,即对数运算是幂运算的逆运算
-left|right
----|---
-23 = 8 | log28 = 3
-24 = 16 | log216 = 4
-25 = 32 | log232 = 5
+log10100 相当于问"将多少个10相乘的结果为100",答案当然是2个了
+因此log10100=2,即对数运算是幂运算的逆运算
-就是酱紫,你要是没有学会,我们也不会等你
+| left | right |
+| ------------------ | --------------------- |
+| 23 = 8 | log28 = 3 |
+| 24 = 16 | log216 = 4 |
+| 25 = 32 | log232 = 5 |
## 运行时间
-以二分查找为例,使用它可节省多少时间呢?简单查找诸葛地检查数字,如果列表包含100个数字,最多需要猜100次。
+
+以二分查找为例,使用它可节省多少时间呢?简单查找逐个地检查数字,如果列表包含100个数字,最多需要猜100次。
换而言之最多需要猜测的次数与列表长度相同,这被称为线性时间(linear time),而二分查找则不同,如果列表包含100个元素
最多需要7次,如果列表包含40亿个数字,最多需猜32次,而分查找的运行时间为对数时间 `O(log)`
## 大O表示法
+
大O表示法是一种特殊的表示法 ,指出了算法的速度有多快。有个屌用啊,实际上,你经常要去复制别人的代码。
在这种情况下,知道这些算法的速度有快有慢
- 算法的运行时间以不同的速度增加
- 例如简单查找与二分查找的区别
-元素|简单查找|二分查找
----|---|---
-100个元素|100ms|7ms
-10000个元素|10s|14ms
-1 000 000 000 个元素|11天|30ms
-
- - 大`O`表示发指出了算法有多快,例如列表包含`n`个元素,简单查找需要检查每个元素,因此需要执行`n`次操作
- 使用大`O`表示发这个运行时间为`O(n)`,二分查找需要执行logn次操作,使用大`O`表示为`O(log n)`
-- 一些常见的大O运行时间
- - O(log n) ,也叫对数时间,这样的算法包括二分算法
- - O(n),也叫线性时间,这样的算法包括简单查找。
- - O(n * log n) 快速排序
- - O(n2),选择排序
- - O(n!) 即阶乘时间
-- 这里是重点
- - 算法的速度指的并非时间,而是操作数的增速
- - 谈论算法的速度时间时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加
- - 算法的运行时间用大O表示发表示
- - O(log n)比O(n)快,当需要搜索的元素越多时,前者比后者快的越多
+| 元素 | 简单查找 | 二分查找 |
+| ----------------- | ----- | ---- |
+| 100个元素 | 100ms | 7ms |
+| 10000个元素 | 10s | 14ms |
+| 1 000 000 000 个元素 | 11天 | 30ms |
+
+- 大`O`表示法指出了算法有多快,例如列表包含`n`个元素,简单查找需要检查每个元素,因此需要执行`n`次操作
+ 使用大`O`表示法这个运行时间为`O(n)`,二分查找需要执行logn次操作,使用大`O`表示为`O(log n)`
+ - 一些常见的大O运行时间
+- O(log n) ,也叫对数时间,这样的算法包括二分算法
+- O(n),也叫线性时间,这样的算法包括简单查找。
+- O(n * log n) 快速排序
+- O(n2),选择排序
+- O(n!) 即阶乘时间
+ - 这里是重点
+- 算法的速度指的并非时间,而是操作数的增速
+- 谈论算法的速度时间时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加
+- 算法的运行时间用大O表示法表示
+- O(log n)比O(n)快,当需要搜索的元素越多时,前者比后者快的越多
+
+## 编写解决实际问题的程序过程
+
+- 如何用数据形式描述问题,即将问题抽象为一个数学模型
+- 问题所涉及到的数据量的大小及数据之间的关系
+- 如何在计算机中储存数据及体现数据之间的关系
+- 处理数据时需要对数据执行的操作
+- 编写的程序的性能是否良好
+
+## 数据(Data)
+
+- 是客观事物的符号表示,在计算机科学中指的是所有能输入到计算机中并被计算机程序处理的符号的总称。
+- 数据元素(Data Element) :是数据的基本单位,在程序中通常作为一个整体来进行考虑和处理。一个数据元素可由若干个数据项(Data Item)组成。
+- 数据项(Data Item) : 是数据的不可分割的最小单位。数据项是对客观事物某一方面特性的数据描述。
+- 数据对象(Data Object) :是性质相同的数据元素的集合,是数据的一个子集。如字符集合C={‘A’,’B’,’C,…} 。
+- 数据结构 :相互之间具有一定联系的数据元素的集合。
+- 数据的逻辑结构 : 数据元素之间的相互关系称为逻辑结构。
+- 数据操作 : 对数据要进行的运算
+- 数据类型(Data Type):指的是一个值的集合和定义在该值集上的一组操作的总称。
+
+## 数据的逻辑结构有四种基本类型
+
+- 集合:结构中数据元素之间除了“属于同一个集合"外,再也没有其他的关系
+- 线性结构:结构中的数据元素存在一对一的关系
+- 树形结构:结构中的数据元素存在一对多的关系
+- 网状或者图状结构:结构中的数据元素存在多对多的关系
+
+## 数据结构的储存方式
+
+由数据元素之间的关系在计算机中有两种不同的表示方法——顺序表示和非顺序表示,从则导出两种储存方式,顺序储存结构和链式储存结构
+
+- 顺序存储结构:用数据元素在存储器中的相对位置来表示数据元素之间的逻辑结构(关系),数据元素存放的地址是连续的
+- 链式存储结构:在每一个数据元素中增加一个存放另一个元素地址的指针(pointer),用该指针来表示数据元素之间的逻辑结构(关系),数据元素存放的地址是否连续没有要求
+数据的逻辑结构和物理结构是密不可分的两个方面,一个算法的设计取决于所选定的逻辑结构,而算法的实现依赖于所采用的存储结构
+
+## 算法(Algorithm)
+
+是对特定问题求解方法(步骤)的一种描述,是指令的有限序列,其中每一条指令表示一个或多个操作。
+
+> 算法具有以下五个特性
+
+- 有穷性: 一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成
+- 确定性:算法中每一条指令必须有确切的含义,不存在二义性,且算法只有一个入口和一个出口
+- 可行性: 一个算法是能行的,即算法描述的操作都可以通过已经实现的基本运算执行有限次来实现
+- 输入: 一个算法有零个或多个输入,这些输入取自于某个特定的对象集合
+- 输出: 一个算法有一个或多个输出,这些输出是同输入有着某些特定关系的量
+
+> 算法和程序是两个不同的概念
+
+一个计算机程序是对一个算法使用某种程序设计语言的具体实现。算法必须可终止意味着不是所有的计算机程序都是算法。
+
+> 评价一个好的算法有以下几个标准
+
+- 正确性(Correctness ): 算法应满足具体问题的需
+- 可读性(Readability): 算法应容易供人阅读和交流,可读性好的算法有助于对算法的理解和修改
+- 健壮性(Robustness): 算法应具有容错处理,当输入非法或错误数据时,算法应能适当地作出反应或进行处理,而不会产生莫名其妙的输出结果
+- 通用性(Generality): 算法应具有一般性 ,即算法的处理结果对于一般的数据集合都成立
+
+> 效率与存储量需求: 效率指的是算法执行的时间;存储量需求指算法执行过程中所需要的最大存储空间,一般地,这两者与问题的规模有关
+
+## 算法的时间复杂度
+
+算法中基本操作重复执行的次数是问题规模n的某个函数,其时间量度记作T(n)=O(f(n)),称作算法的渐近时间复杂度(Asymptotic Time complexity),简称时间复杂度
+
+## 算法的空间复杂度
+
+是指算法编写成程序后,在计算机中运行时所需存储空间大小的度量,记作:S(n)=O(f(n)),其中n为问题规模
## 递归和循环的简单比较:
@@ -109,6 +234,7 @@ left|right
4. 一般来说,非递归的效率高于递归。而且递归函数调用是有开销的,递归的次数受堆栈大小的限制。
## 一起进步学习
+
1. Fork 我的项目并提交你的 `idea`
2. Pull Request
3. Merge
@@ -116,15 +242,23 @@ left|right
## 纠错
如果大家发现有什么不对的地方,可以发起一个[issue](https://github.com/PuShaoWei/arithmetic-php/issues)或者[pull request](https://github.com/PuShaoWei/arithmetic-php/pulls),我会及时纠正
+
> 补充:发起pull request的commit message请参考文章[Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html)
## 致谢
+
感谢以下朋友的issue或pull request:
- [hailwood ](https://github.com/hailwood)
+
- [zhangxuanru](https://github.com/zhangxuanru)
+
- [ifreesec](https://github.com/ifreesec)
+
- [openset](https://github.com/openset)
-## License
+- [Neroxiezi](https://github.com/Neroxiezi)
+
+ ## License
+
MIT
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..ac1360d
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,17 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported |
+| ------- | ------------------ |
+| 5.1.x | :white_check_mark: |
+| 5.0.x | :x: |
+| 4.0.x | :white_check_mark: |
+| < 4.0 | :x: |
+
+## Reporting a Vulnerability
+
+Please report security issues to
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..c419263
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-cayman
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..05a3a26
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,44 @@
+{
+ "name": "algorithm-php",
+ "description": "algorithm-php",
+ "minimum-stability": "stable",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "pushaowei"
+ }
+ ],
+ "require-dev": {
+ "phpunit/phpunit": "~6.0",
+ "mockery/mockery": "~0.9"
+ },
+ "autoload": {
+ "classmap": [
+ "./src"
+ ]
+ },
+ "autoload-dev": {
+ "classmap": [
+ "tests/"
+ ]
+ },
+ "prefer-stable": true,
+ "config": {
+ "optimize-autoloader": true
+ },
+ "repositories": {
+ "packagist": {
+ "type": "composer",
+ "url": "https://packagist.phpcomposer.com"
+ }
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-ctype": "*",
+ "ext-openssl": "*",
+ "php": ">=5.6.4",
+ "ext-curl": "*",
+ "stojg/recommend": "^1.0",
+ "ext-iconv": "*"
+ }
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..4cf0e34
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,9 @@
+version: '2.0'
+services:
+ php71-dev:
+ image: "m9rco/php:7.1-dev"
+ ports:
+ - "2222:22"
+ - "29000:9000"
+ volumes:
+ - $PWD:/app:rw
\ No newline at end of file
diff --git a/package/Other/BigSmallReplace.php b/package/Other/BigSmallReplace.php
deleted file mode 100644
index c5277ff..0000000
--- a/package/Other/BigSmallReplace.php
+++ /dev/null
@@ -1,48 +0,0 @@
-
- * @date 2017/8/12
- * @license Mozilla
- *
- * segmentFault: https://segmentfault.com/q/1010000010627229
- *
- * @param $str
- * @return string
- */
-function BigSmallReplace( $str )
-{
- // Cutting words
- $first = preg_split("/[\s]+/", $str);
- $result = [];
-
- // Start
- foreach ( $first as $f_value ) {
- $str_len = strlen($f_value) - 1; $i = 0; $temp = '';
- while ( $str_len >= 0 ) {
- if ( ord($f_value[$str_len]) > 64 && ord($f_value[$str_len]) < 91 ) {
- $temp .= strtoupper($f_value[$i]);
- }else if ( ord($f_value[$str_len]) > 96 && ord($f_value[$str_len]) < 123 ) {
- $temp .= strtolower($f_value[$i]);
- }
- $i++; $str_len--;
- }
- array_push($result, strrev($temp));
- }
- return implode(' ',$result);
-}
-
-var_dump(BigSmallReplace('Hello World'));
-// Olleh Dlrow
-
-
-/*
-Hello World 输出 Olleh Dlrow
-
-SWAT 输出 TAWS
-
-I am A sTudent 输出 I ma A tNeduts
-*/
-
diff --git a/package/Other/GetCattle.php b/package/Other/GetCattle.php
deleted file mode 100644
index 9cc19dc..0000000
--- a/package/Other/GetCattle.php
+++ /dev/null
@@ -1,47 +0,0 @@
-
- * @date 2017/8/24
- * @license Mozilla
- * -------------------------------------------------------------
- * 思路分析:见下方注释
- * -------------------------------------------------------------
- *
- * 牛年求牛:
- * 有一母牛,到4岁可生育,每年一头,所生均是一样的母牛
- * 15岁绝育,不再能生,
- * 20岁死亡,问n年后有多少头牛。
- *
- * @param $n
- * @return int
- */
-function getCattle($n)
-{
- static $num = 1;
- for ($i =1; $i<=$n;$i++){
- if( $i == 20) break;
- if($i >= 4 && $i <15){
- if($i % 4 == 0 ){
- getCattle($n - $i);
- $num++;
- }
- $num++;
- }
- }
- return $num;
-}
-echo '牛年共有:'.getCattle(10);
-
-/*
-123456789
- 123456
- 123
- 12
-9 - 11
-
----
-
- */
\ No newline at end of file
diff --git a/package/Query/BinaryQuery.php b/package/Query/BinaryQuery.php
deleted file mode 100644
index 4994862..0000000
--- a/package/Query/BinaryQuery.php
+++ /dev/null
@@ -1,76 +0,0 @@
-
- * @date 2017/6/17
- * @license Mozilla
- * -------------------------------------------------------------
- * 思路分析:数组中间的值floor((low+top)/2)
- * -------------------------------------------------------------
- * 先取数组中间的值floor((low+top)/2)然后通过与所需查找的数字进行比较,
- * 若比中间值大则将首值替换为中间位置下一个位置,继续第一步的操作;
- * 若比中间值小,则将尾值替换为中间位置上一个位置,继续第一步操作
- * 重复第二步操作直至找出目标数字
- *
- * 非递归版 二分查找
- * @param array $container
- * @param $search
- * @return int|string
- */
-function BinaryQuery( array $container,$search){
- $top = count($container);
- $low = 0;
- while ( $low <= $top){
- $mid = intval( floor( ($low + $top ) / 2) );
- if( !isset($container[$mid]) ) return '没找着哦';
- if( $container[$mid] == $search) return $mid;
- $container[$mid] < $search && $low = $mid+1;
- $container[$mid] > $search && $top = $mid-1;
- }
-}
-// var_dump( BinaryQuery([0,1,2,3,4,5,6,7,8,9],9) );
-/*
- * double(8)
- */
-
-/**
- * 递归版 二分查找
- * @param array $container
- * @param $search
- * @param int $low
- * @param string $top
- * @return int|string
- */
-function BinaryQueryRecursive(array $container,$search,$low = 0,$top = 'default'){
- $top == 'default' && $top = count($container );
- if( $low <= $top ){
- $mid = intval( floor( $low + $top ) /2 );
- if( !isset($container[$mid]) ) return '没找着哦';
- if( $container[$mid] == $search) return $mid;
- if( $container[$mid] < $search ){
- return BinaryQueryRecursive($container,$search,$mid+1,$top);
- }else{
- return BinaryQueryRecursive($container,$search,$low,$mid-1);
- }
- }
-}
-
- var_dump( BinaryQueryRecursive([0,1,2,3,4,5,6,7,8,9],9) );
-/*
-array(7) {
- [0] =>
- int(3)
- [1] =>
- int(4)
- [2] =>
- int(5)
- [3] =>
- int(6)
- [4] =>
- int(7)
- [5] =>
- int(8)
- [6] =>
- int(9)
-}
-*/
\ No newline at end of file
diff --git a/package/Query/BinaryTree.php b/package/Query/BinaryTree.php
deleted file mode 100644
index 05ac1ba..0000000
--- a/package/Query/BinaryTree.php
+++ /dev/null
@@ -1,13 +0,0 @@
-
- * @date 2017/8/25
- * @license Mozilla
- * -------------------------------------------------------------
- * 思路分析:
- * -------------------------------------------------------------
- *
- */
diff --git a/package/Sort/QuickSort.php b/package/Sort/QuickSort.php
deleted file mode 100644
index 057effc..0000000
--- a/package/Sort/QuickSort.php
+++ /dev/null
@@ -1,35 +0,0 @@
-
- * @date 2017/6/17
- * @license Mozilla
- * -------------------------------------------------------------
- * 思路分析:从数列中挑出一个元素,称为 “基准”(pivot)
- * -------------------------------------------------------------
- * 重新排序数列,所有元素比基准值小的摆放在基准前面
- * 所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
- * 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序
- *
- * @param array $container
- * @return mixed
- */
-function QulickSort( array $container ){
- $count = count( $container );
- if( $count <= 1 ) {
- return $container;
- }
- $left = $right = [];
- for ($i = 1; $i < $count; $i++) {
- if ($container[$i] < $container[0]) {
- $left[] = $container[$i];
- } else {
- $right[] = $container[$i];
- }
- }
- $left = QulickSort($left);
- $right = QulickSort($right);
- return array_merge($left,[$container[0]],$right);
-}
-
-var_dump( QulickSort([4,21,41,2,53,1,213,31,21,423]) );
\ No newline at end of file
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..5dd071d
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+ ./tests
+
+
+
\ No newline at end of file
diff --git a/src/Features/SystemSwitch.php b/src/Features/SystemSwitch.php
new file mode 100644
index 0000000..598983b
--- /dev/null
+++ b/src/Features/SystemSwitch.php
@@ -0,0 +1,99 @@
+
+ * @date 2017/10/16
+ * @license MIT
+ * -------------------------------------------------------------
+ * 十进制整数转换为二、八、十六进制整数 n = (n div d) * d + n mod d
+ * -------------------------------------------------------------
+ */
+class SystemSwitch
+{
+ /**
+ * @var array
+ */
+ protected $systemGather;
+
+ /**
+ * @var int
+ */
+ protected $input;
+
+ /**
+ * @var mixed
+ */
+ protected $output;
+
+ /**
+ * SystemSwitch constructor.
+ *
+ * @param $input
+ * @param $output
+ */
+ public function __construct($input, $output)
+ {
+ $this->systemGather = array (2, 8, 16);
+ $this->input = $input;
+ $this->output = $output;
+ }
+
+ public function run()
+ {
+ $before = $this->input;
+ $stack = new StackExample();
+ while ($this->input != 0) {
+ $mod = $this->input % $this->output;
+ $stack->setPushStack($mod);
+ $this->input = (int)($this->input - $mod) / $this->output;
+ }
+ $output = '';
+ if ($this->output == 16) {
+ $output .= '0x';
+ } else if ($this->output == 8) {
+ $output .= '0';
+ }
+
+ foreach ($stack->getAllPopStack() as $value) {
+ if ($this->output == 16) {
+ switch ($value) {
+ case 10:
+ $value = 'A';
+ break;
+ case 11:
+ $value = 'B';
+ break;
+ case 12:
+ $value = 'C';
+ break;
+ case 13:
+ $value = 'D';
+ break;
+ case 14:
+ $value = 'E';
+ break;
+ case 15:
+ $value = 'F';
+ break;
+ }
+ }
+ $output .= $value;
+ }
+ // 因为输出语句会自动将整型的数转换为10进制输出
+ // 也即如果转换后的结果为0xff,直接将0xff输出会得到255,所以返回一数组
+ return array (
+ 'before' => $before, // 转换之前
+ 'after' => intval($output, $this->output), // 转换后的整型数(整型)
+ 'string' => $output // 转换后的整型数的字符串表示(字符串型)
+ );
+ }
+}
+
+// load the stack
+define("DS", DIRECTORY_SEPARATOR);
+require_once dirname(__DIR__) . DS . 'Structure' . DS . 'StackExample.php';
+$systemObj = new SystemSwitch(6, 16);
+$result = $systemObj->run();
+var_dump($result);
\ No newline at end of file
diff --git a/package/Query/YieldExample.php b/src/Features/YieldExample.php
similarity index 100%
rename from package/Query/YieldExample.php
rename to src/Features/YieldExample.php
diff --git a/src/Other/AntsClimb.php b/src/Other/AntsClimb.php
new file mode 100644
index 0000000..448c839
--- /dev/null
+++ b/src/Other/AntsClimb.php
@@ -0,0 +1,159 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。
+ * 木杆很细,不能同时通过一只蚂蚁。开始 时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,
+ * 但不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。
+ * -------------------------------------------------------------
+ * 编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
+class AntsClimb
+{
+ /**
+ * @var array 蚂蚁位置集合
+ */
+ protected $position;
+
+ /**
+ * AntsClimb constructor.
+ *
+ * @param array $position
+ */
+ public function __construct(array $position)
+ {
+ $this->position = $position;
+ }
+
+ /**
+ * run
+ *
+ * @return void
+ */
+ public function run()
+ {
+ $pathCalculate = $this->path($this->position);
+ echo '计算-';
+ print_r($pathCalculate);
+ echo '排序-';
+ asort($pathCalculate);
+ print_r($pathCalculate);
+ }
+
+ /**
+ * add2
+ *
+ * @param $directionArr
+ * @param $count
+ * @param $i
+ * @return mixed
+ */
+ protected function add2($directionArr, $count, $i)
+ {
+ if (0 > $i) {
+ return $directionArr;
+ }
+ if (0 === $directionArr[$i]) {
+ $directionArr[$i] = 1;
+ return $directionArr;
+ }
+ $directionArr[$i] = 0;
+ return $this->add2($directionArr, $count, $i - 1);
+ }
+
+ /**
+ * path
+ *
+ * @param $positionArr
+ * @return array
+ */
+ protected function path($positionArr)
+ {
+ // 生成测试路径
+ $pathCalculate = array ();
+ $count = count($positionArr);
+ $directionArr = array_fill(0, $count, 0);
+
+ // 朝向
+ $end = str_repeat('1', $count);
+ while (true) {
+ $path = implode('', $directionArr);
+ $total = $this->calculate($positionArr, $directionArr);
+ $pathCalculate['路径:' . $path] = $total;
+ if ($end == $path) { // 遍历完成
+ break;
+ }
+ $directionArr = $this->add2($directionArr, $count, $count - 1);
+ }
+ return $pathCalculate;
+ }
+
+ /**
+ * calculate
+ *
+ * @param $positionArr
+ * @param $directionArr
+ * @return int
+ */
+ protected function calculate($positionArr, $directionArr)
+ {
+ $total = 0;
+ // 总用时
+ $length = 27;
+ // 木杆长度
+ while ($positionArr) {
+ $total++; // 步增耗时
+ $nextArr = array (); // 下一步位置
+ foreach ($positionArr as $key => $value) {
+ if (0 == $directionArr[$key]) {
+ $next = $value - 1; // 向0方向走一步
+ } else {
+ $next = $value + 1; // 向1方向走一步
+ }
+ if (0 == $next) { // 在0方向走出
+ continue;
+ }
+ if ($length == $next) { // 在1方向走出
+ continue;
+ }
+ $nextArr[$key] = $next;
+ }
+ $positionArr = $nextArr;// 将$positionArr置为临时被查找数组
+
+ foreach ($nextArr as $key => $value) {
+ $findArr = array_keys($positionArr, $value);
+ if (count($findArr) < 2) {
+ // 没有重合的位置
+ continue;
+ }
+ foreach ($findArr as $findIndex) {
+ $directionArr[$findIndex] = $directionArr[$findIndex] ? 0 : 1;
+ // 反向处理
+ unset($positionArr[$findIndex]);
+ // 防止重复查找计算
+ }
+ }
+ $positionArr = $nextArr;
+ // 将$positionArr置为下一步结果数组
+ }
+ return $total;
+ }
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+// 蚂蚁位置
+$position = array (3, 7, 11, 17, 23);
+// 测试用例
+(new AntsClimb($position))->run();
\ No newline at end of file
diff --git a/package/Other/BidirectionalQueue.php b/src/Other/BidirectionalQueue.php
similarity index 83%
rename from package/Other/BidirectionalQueue.php
rename to src/Other/BidirectionalQueue.php
index 4bbd921..099d705 100644
--- a/package/Other/BidirectionalQueue.php
+++ b/src/Other/BidirectionalQueue.php
@@ -1,18 +1,22 @@
- * @date 2017/9/13
+ * @date 2018/1/11
* @license MIT
* -------------------------------------------------------------
- * 思路分析: 考察PHP几个内置数组的函数
+ * 双向队列的实现及应用
* -------------------------------------------------------------
- *双向队列是一种双向开口的连续线性空间,可以高效的在头尾两端插入和删除元素
- * @param $n
- * @return int
+ * 思路分析: 考察PHP几个内置数组的函数
+ * 双向队列是一种双向开口的连续线性空间,可以高效的在头尾两端插入和删除元素
*/
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
class BidirectionalQueue
{
/**
@@ -34,8 +38,7 @@ class BidirectionalQueue
/**
* BidirectionalQueue 初始化.
*
- * @param int $type
-
+ * @param int $type
* @param int $maxLength
*/
public function __construct($type = self::C_AT_BOTH_ENDS, $maxLength = 0)
@@ -127,7 +130,6 @@ public function getLength()
/**
* 获取配置常量
- *
*/
protected function getConfig()
{
@@ -141,4 +143,10 @@ protected function getConfig()
];
}
}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
new BidirectionalQueue();
\ No newline at end of file
diff --git a/src/Other/BigSmallReplace.php b/src/Other/BigSmallReplace.php
new file mode 100644
index 0000000..547a7b8
--- /dev/null
+++ b/src/Other/BigSmallReplace.php
@@ -0,0 +1,55 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * Hello World 输出 Olleh Dlrow
+ * -------------------------------------------------------------
+ * SWAT 输出 TAWS
+ * I am A sTudent 输出 I ma A tNeduts
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * BigSmallReplace
+ *
+ * @param $str
+ * @return string
+ */
+function BigSmallReplace($str)
+{
+ // Cutting words
+ $first = preg_split("/[\s]+/", $str);
+ $result = [];
+
+ // Start
+ foreach ($first as $f_value) {
+ $str_len = strlen($f_value) - 1;
+ $i = 0;
+ $temp = '';
+ while ($str_len >= 0) {
+ if (ord($f_value[$str_len]) > 64 && ord($f_value[$str_len]) < 91) {
+ $temp .= strtoupper($f_value[$i]);
+ } else if (ord($f_value[$str_len]) > 96 && ord($f_value[$str_len]) < 123) {
+ $temp .= strtolower($f_value[$i]);
+ }
+ $i++;
+ $str_len--;
+ }
+ array_push($result, strrev($temp));
+ }
+ return implode(' ', $result);
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+var_dump(BigSmallReplace('Hello World'));
diff --git a/src/Other/CartesianProduct.php b/src/Other/CartesianProduct.php
new file mode 100644
index 0000000..63f027d
--- /dev/null
+++ b/src/Other/CartesianProduct.php
@@ -0,0 +1,61 @@
+params = func_get_args();
+ }
+ public function combineDika()
+ {
+ $result = [];
+ if(count($this->params[0])!=count($this->params[0], 1)){
+ $this->params = $this->params[0];
+ }
+ $cnt = count($this->params);
+ foreach($this->params[0] as $item) {
+ $result[] = [$item];
+ }
+ for($i = 1; $i < $cnt; $i++) {
+ $result = $this->combineArray($result,$this->params[$i]);
+ }
+ return $result;
+ }
+
+ private function combineArray($arr_a, $arr_b)
+ {
+ $result = [];
+ foreach ($arr_a as $item) {
+ foreach ($arr_b as $item2) {
+ $temp = $item;
+ $temp[] = $item2;
+ $result[] = $temp;
+ }
+ }
+ return $result;
+ }
+}
+
+$color = array('白色','黑色','红色');
+$size = array('透气','防滑');
+$local = array('37码','38码','39码');
+
+$obj = new CartesianProduct($color,$size,$local);
+print_r($obj->combineDika());
+
+$sets = array(
+ array('白色','黑色','红色'),
+ array('透气','防滑'),
+ array('37码','38码','39码'),
+ array('男款','女款')
+);
+
+$obj1 = new CartesianProduct($sets);
+print_r($obj1->combineDika());
\ No newline at end of file
diff --git a/package/Other/ColorBricks.php b/src/Other/ColorBricks.php
similarity index 84%
rename from package/Other/ColorBricks.php
rename to src/Other/ColorBricks.php
index 79fd236..d3a498d 100644
--- a/package/Other/ColorBricks.php
+++ b/src/Other/ColorBricks.php
@@ -1,6 +1,7 @@
* @date 2017/9/1
@@ -36,8 +37,17 @@
* ABAB
* 输出例子1:
* 2
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * ColorBricks
+ *
* @param $inputting
- * @return mixed
+ * @return bool|int
*/
function ColorBricks($inputting)
{
@@ -80,4 +90,9 @@ function ColorBricks($inputting)
return $counter;
}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
echo ColorBricks("AABB");
\ No newline at end of file
diff --git a/package/Other/DynamicProgramming.php b/src/Other/DynamicProgramming.php
similarity index 69%
rename from package/Other/DynamicProgramming.php
rename to src/Other/DynamicProgramming.php
index 2e71008..53b6ad3 100644
--- a/package/Other/DynamicProgramming.php
+++ b/src/Other/DynamicProgramming.php
@@ -1,17 +1,29 @@
* @date 2017/8/28
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:动态规划原理思想,max(opt(i-1,w),wi+opt(i-1,w-wi)) 当中最大值,opt(i-1,w-wi)指上一个最优解
* -------------------------------------------------------------
* 一个承受最大重量为W的背包,现在有n个物品,每个物品重量为t, 每个物品的价值为v。
* 要使得这个背包重量最大(但不能超过W),同时又需要背包的价值最大
- * @return int
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * DynamicProgramming
+ *
+ * @param $maxSize
+ * @param $goods
+ * @param $cost
+ * @return mixed
*/
function DynamicProgramming($maxSize, $goods, $cost)
{
@@ -42,7 +54,11 @@ function DynamicProgramming($maxSize, $goods, $cost)
}
}
}
- var_dump($container[$j - 1][$i - 1]);
+ return $container[$j - 1][$i - 1];
}
-echo DynamicProgramming(15, [3, 4, 5, 6], [8, 7, 4, 9]);
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+echo DynamicProgramming(15, array (3, 4, 5, 6), array (8, 7, 4, 9));
diff --git a/src/Other/ElevatorDispatch.php b/src/Other/ElevatorDispatch.php
new file mode 100644
index 0000000..d1811ba
--- /dev/null
+++ b/src/Other/ElevatorDispatch.php
@@ -0,0 +1,111 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 解决方案:
+ * (1)使用简单的方法,直接将楼层从1到n开始遍历
+ * sum(person[i] * |i - j| ) 此表达式为一个双重循环,i与j均为1-n的循环。
+ * j下标表示电梯停靠的楼层。
+ * person数组表示,对应i层的下电梯的人数。此算法负责度为o(n*n)
+ * 对应的j是上述和为最小的一层即为所求。 上面的算法复杂度为o(n)
+ *
+ * (2)下面考虑一个简单的算法,使其复杂度达到o(n)
+ * 考虑假如电梯停靠在某一楼层i处,假设在i处下楼的客人为$first_layer,
+ * 在i以上楼层的客人数目为$first_layer_above ,在i一下楼层的客人数目为$first_layer_below。
+ * 且将电梯在i层停止时,全部人员的路程之和记为T。
+ *
+ * 那么加入电梯在i-1层停的话,则原来i层之上的人需要多爬一层,即增加了$first_layer_above
+ * 第i层的人需要多爬一层,则结果增加了$first_layer, i层之下的人则少爬了一层,结果减去$first_layer_below
+ * 所以第i-1层的结果为$time- $first_layer_below + $first_layer + $first_layer_above 。即结果可以即为$time-($first_layer_below - $first_layer - $first_layer_above)
+ *
+ *
+ * 下面考虑在i+1层的结果,若电梯在i+1层停止的话,原来i层之上的客户都会少爬一层,
+ * 则结果减少$first_layer_above ,而i层之下的人员则都会多爬一层即增加了$first_layer_below ,第i层的人员都会多爬一层
+ * 即为增加了$first_layer 。则结果为$time+ $first_layer_below + $first_layer - $first_layer_above
+ *
+ * 综上我们得出,
+ * (1)若$first_layer_below > $first_layer + $first_layer_above的时候, 我们在第i-1层 选择电梯停止最好。
+ * (2)若$first_layer_below + $first_layer < $first_layer_above的时候, 我们选择在第i+1层停止电梯最好。
+ *
+ * 下面我们可以先计算出来当i=1时候的T ,然后判断是否需要在i+1层停止,若是i+1层的花费
+ * 大于i层,则我们可以继续计算,否则退出。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+class ElevatorDispatch
+{
+ protected $n = 10;
+ protected $person;
+ protected $time = 0; //先计算出在第一层停止的时候 所需要的花费
+ protected $first_layer_below = 0; //在第一层以下下的人数
+ protected $first_layer;
+ protected $first_layer_above = 0;//在第一层之上下电梯的人数
+ public $floor = 1;//存储停靠的楼层
+
+ public function __construct($person = [])
+ {
+ if (empty($person)) {
+ $this->person = [0, 2, 5, 7, 3, 5, 2, 6, 2, 6, 3];
+ }
+ $this->first_layer = $this->person[1]; //在第一层处下的人数
+
+ }
+
+ public function compute()
+ {
+
+ //先计算出第1层停止需要爬取的楼层数目
+ for ($i = 2; $i <= $this->n; $i++) {
+ $this->time += $this->person[$i] * ($i - 1);
+ $this->first_layer_above += $this->person[$i];
+ }
+ for ($j = 2; $j <= $this->n; $j++) {
+ if ($this->first_layer_below + $this->first_layer <= $this->first_layer_above) { //说明第i+1层的结果会大于第i层
+ $this->time += $this->first_layer_below + $this->first_layer - $this->first_layer_above;
+ $this->first_layer_below += $this->first_layer;
+ $this->first_layer = $this->person[$j];
+ $this->first_layer_above -= $this->person[$j];
+ $this->floor = $j;
+ } else {
+ //否则第i层的结果已经最小,故不需要计算第i+1层
+ break;
+ }
+ }
+ return $this->floor;
+ }
+
+ public function computeTwo()
+ {
+ $min = 6553;//存储最小值 ;
+ for ($i = 1; $i <= $this->n; $i++) { //表示第i楼层电梯停靠
+ $this->time = 0;
+ for ($j = 1; $j < $this->n; $j++) {
+ $this->time += abs(($i - $j)) * $this->person[$j];
+ }
+ if ($min > $this->time) {
+ $min = $this->time;
+ $this->floor = $i;
+ }
+ }
+ return $this->floor;
+ }
+
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+$obj = new ElevatorDispatch();
+var_dump($obj->compute());
+var_dump($obj->computeTwo());
\ No newline at end of file
diff --git a/src/Other/Encryption.php b/src/Other/Encryption.php
new file mode 100644
index 0000000..22e5eee
--- /dev/null
+++ b/src/Other/Encryption.php
@@ -0,0 +1,78 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 位运算进行加密
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * 加密函数
+ *
+ * @param $txt
+ * @param $key
+ * @return string
+ */
+function passport_encrypt($txt, $key)
+{
+ $encrypt_key = md5(rand(0, 32000));
+ $ctr = 0;
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
+ $tmp .= $encrypt_key[$ctr] . ($txt[$i] ^ $encrypt_key[$ctr++]);
+ }
+ return base64_encode(passport_key($tmp, $key));
+}
+
+/**
+ * 解密函数
+ *
+ * @param $txt
+ * @param $key
+ * @return string
+ */
+function passport_decrypt($txt, $key)
+{
+ $txt = passport_key(base64_decode($txt), $key);
+
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $md5 = $txt[$i];
+ $tmp .= $txt[++$i] ^ $md5;
+ }
+ return $tmp;
+}
+
+/**
+ * passport_key
+ *
+ * @param $txt
+ * @param $encrypt_key
+ * @return string
+ */
+function passport_key($txt, $encrypt_key)
+{
+ $encrypt_key = md5($encrypt_key);
+ $ctr = 0;
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
+ $tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
+ }
+ return $tmp;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
diff --git a/src/Other/Factorial.php b/src/Other/Factorial.php
new file mode 100644
index 0000000..ccd2869
--- /dev/null
+++ b/src/Other/Factorial.php
@@ -0,0 +1,44 @@
+
* @date 2017/8/25
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:
* -------------------------------------------------------------
* 斐波那契数列(Fibonacci Sequence)又称黄金分割数列 兔子数列
* 指的是这样一个数列:1、1、2、3、5、8、13、21
* 在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+/**
+ * 递归方式
*
* @param $n
- * @return int
+ * @return mixed
*/
-
-// recursion
-/*
-function Fibonacci($n)
+function FibonacciRecursive($n)
{
- if ($n <= 1 ) {
+ if ($n <= 1) {
return $n;
}
return Fibonacci($n - 1) + Fibonacci($n - 2);
}
-*/
-// 55
-// not recursion
+/**
+ * 非递归方式
+ *
+ * @param $n
+ * @return mixed
+ */
function Fibonacci($n)
{
if ($n <= 1) {
@@ -40,5 +51,11 @@ function Fibonacci($n)
return $fib[$n];
}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
echo Fibonacci(10);
-// 55
+echo FibonacciRecursive(10);
diff --git a/src/Other/GetCattle.php b/src/Other/GetCattle.php
new file mode 100644
index 0000000..0997ac0
--- /dev/null
+++ b/src/Other/GetCattle.php
@@ -0,0 +1,60 @@
+
+ * @date 2017/8/24
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:见下方注释
+ * -------------------------------------------------------------
+ *
+ * 牛年求牛:
+ * 有一母牛,到4岁可生育,每年一头,所生均是一样的母牛
+ * 15岁绝育,不再能生,
+ * 20岁死亡,问n年后有多少头牛。
+ *
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * getCattle
+ *
+ * @param $n
+ * @return int
+ */
+function getCattle($n)
+{
+ static $num = 1;
+ for ($i = 1; $i <= $n; $i++) {
+ if ($i == 20) {
+ $num--; //死亡需减一
+ } else if ($i >= 4 && $i < 15) {
+ $num++; //生小母牛(这里有小母牛)
+ getCattle($n - $i); //小母牛生小母牛(这里不包含小母牛)
+ }
+ }
+ return $num;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+echo '牛年共有:' . getCattle(10);
+
+/*
+123456789
+ 123456
+ 123
+ 12
+9 - 11
+
+---
+
+ */
\ No newline at end of file
diff --git a/package/Other/HanoiGames.php b/src/Other/HanoiGames.php
similarity index 79%
rename from package/Other/HanoiGames.php
rename to src/Other/HanoiGames.php
index 10e54e1..83b1b51 100644
--- a/package/Other/HanoiGames.php
+++ b/src/Other/HanoiGames.php
@@ -5,7 +5,7 @@
*
* @author Pu ShaoWei
* @date 2017/8/26
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:
* -------------------------------------------------------------
@@ -14,9 +14,7 @@
* 第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,
* 庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,
* 但每次只能搬一个,而且大的不能放在小的上面。
- *
* 面对庞大的数字(移动圆片的次数)18446744073709551615,看来,众僧们耗尽毕生精力也不可能完成金片的移动。
- *
* 后来,这个传说就演变为汉诺塔游戏:
* 1.有三根杆子A,B,C。A杆上有若干碟子
* 2.每次移动一块碟子,小的只能叠在大的上面
@@ -24,6 +22,14 @@
* 经过研究发现,汉诺塔的破解很简单,就是按照移动规则向一个方向移动金片:
* 如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
* 此外,汉诺塔问题也是程序设计中的经典递归问题。
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * HanoiGames
*
* @param $n
* @param $x
@@ -41,6 +47,11 @@ function HanoiGames($n, $x, $y, $z)
}
}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
HanoiGames(3, 'A', 'B', 'C');
// move disk 1 from A to C
diff --git a/src/Other/HashTable.php b/src/Other/HashTable.php
new file mode 100644
index 0000000..cdd6b10
--- /dev/null
+++ b/src/Other/HashTable.php
@@ -0,0 +1,130 @@
+
+ * @date 2019/5/9
+ * @license MIT
+ * -------------------------------------------------------------
+ * HashTable
+ */
+
+
+define('TABLE_SIZE', 100);
+
+class KeyValue
+{
+ public $key;
+ public $value;
+
+ public function __construct($key, $value)
+ {
+ $this->key = $key;
+ $this->value = $value;
+ }
+}
+
+class HashTable
+{
+ public $size = 0;
+ public $data = [];
+}
+
+function create_table($size = TABLE_SIZE)
+{
+ $table = new HashTable();
+ for ($i = 0; $i < $size; ++$i) {
+ $table->data[$i] = null;
+ }
+ $table->size = 100;
+
+ return $table;
+}
+
+function destroy_table(&$table)
+{
+ unset($table);
+}
+
+function hash_key($key, $size = TABLE_SIZE)
+{
+ $len = strlen($key);
+ $hash = 0;
+ for ($i = 0; $i < $len; ++$i) {
+ $hash = $hash * 31 + ord($key[$i]);
+ }
+
+ return abs($hash % $size);
+}
+
+function print_debug($table)
+{
+ for ($i = 0; $i < $table->size; ++$i) {
+ if (null === $table->data[$i]) {
+ echo $i, "\n";
+ } else {
+ echo $i, ' key=', $table->data[$i]->key, ', value=', $table->data[$i]->value , "\n";
+ }
+ }
+}
+
+function exists(&$table, $key)
+{
+ $index = hash_key($key);
+ if (null === $table->data[$index]) {
+ return false;
+ }
+
+ if (0 === strcmp($key, $table->data[$index]->key)) {
+ return true;
+ }
+
+ return false;
+}
+
+function add(&$table, $key, KeyValue $object)
+{
+ $index = hash_key($key);
+ $table->data[$index] = $object;
+}
+
+function get(&$table, $key)
+{
+ $index = hash_key($key);
+ if (0 === strcmp($key, $table->data[$index]->key)) {
+ return $table->data[$index]->value;
+ }
+}
+
+function delete(&$table, $key)
+{
+ $index = hash_key($key);
+ if (null === $table->data[$index]) {
+ return;
+ }
+ if (0 === strcmp($key, $table->data[$index]->key)) {
+ return $table->data[$index] = null;
+ }
+}
+
+$hash_table = create_table();
+print_debug($hash_table);
+
+add($hash_table, 'Wang', new KeyValue('Wang', '50'));
+add($hash_table, 'Li', new KeyValue('Li', '20'));
+add($hash_table, 'Chow', new KeyValue('Chow', '23'));
+print_debug($hash_table);
+
+//get
+echo "----------get-------------- \n";
+var_dump(get($hash_table, 'Wang'));
+
+//delete
+echo "----------delete-------------- \n";
+delete($hash_table, 'Wang');
+var_dump(delete($hash_table, 'Wang'));
+
+//exists
+echo "----------exists-------------- \n";
+var_dump(exists($hash_table, 'Wang'));
+var_dump(exists($hash_table, 'Li'));
\ No newline at end of file
diff --git a/src/Other/Interval.php b/src/Other/Interval.php
new file mode 100644
index 0000000..0b840c2
--- /dev/null
+++ b/src/Other/Interval.php
@@ -0,0 +1,95 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ *
+ * 不同概率的抽奖原理就是把0到*(比重总数)的区间分块
+ * 分块的依据是物品占整个的比重,再根据随机数种子来产生0-* 中的某个数
+ * 判断这个数是落在哪个区间上,区间对应的就是抽到的那个物品。
+ * 随机数理论上是概率均等的,那么相应的区间所含数的多少就体现了抽奖物品概率的不同。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * get_rand
+ *
+ * @param $proArr
+ * @return array
+ */
+function get_rand($proArr)
+{
+ $result = array();
+ foreach ($proArr as $key => $val) {
+ $arr[$key] = $val['v'];
+ }
+ $proSum = array_sum($arr); // 计算总权重
+ $randNum = mt_rand(1, $proSum);
+ $d1 = 0;
+ $d2 = 0;
+ for ($i = 0; $i < count($arr); $i++) {
+ $d2 += $arr[$i];
+ if ($i == 0) {
+ $d1 = 0;
+ } else {
+ $d1 += $arr[$i - 1];
+ }
+ if ($randNum >= $d1 && $randNum <= $d2) {
+ $result = $proArr[$i];
+ }
+ }
+ unset ($arr);
+ return $result;
+}
+
+/**
+ * 使用较多的为这个方法
+ *
+ * @param $proArr
+ * @return array
+ */
+function get_rand1($proArr)
+{
+ $result = array();
+ foreach ($proArr as $key => $val) {
+ $arr[$key] = $val['v'];
+ }
+ // 概率数组的总概率
+ $proSum = array_sum($arr);
+ asort($arr);
+ // 概率数组循环
+ foreach ($arr as $k => $v) {
+ $randNum = mt_rand(1, $proSum);
+ if ($randNum <= $v) {
+ $result = $proArr[$k];
+ break;
+ } else {
+ $proSum -= $v;
+ }
+ }
+ return $result;
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+$arr = array(
+ array('id' => 1, 'name' => '特等奖', 'v' => 1),
+ array('id' => 2, 'name' => '一等奖', 'v' => 5),
+ array('id' => 3, 'name' => '二等奖', 'v' => 10),
+ array('id' => 4, 'name' => '三等奖', 'v' => 12),
+ array('id' => 5, 'name' => '四等奖', 'v' => 22),
+ array('id' => 6, 'name' => '没中奖', 'v' => 50)
+);
+
+var_dump(get_rand($arr));
+
diff --git a/src/Other/Judge.php b/src/Other/Judge.php
new file mode 100644
index 0000000..a69ef43
--- /dev/null
+++ b/src/Other/Judge.php
@@ -0,0 +1,69 @@
+weight = $weight;
+ $this->value = $value;
+ $this->total_weight = $total_weight;
+ }
+
+ # 贪心算法去算最佳的物品
+ public function bag()
+ {
+ $product = [];
+ foreach ($this->weight as $k => $v) {
+ $product[] = ['weight' => $v, 'value' => $this->value[$k], 'pj_value' => ($this->value[$k] / $v)];
+ }
+
+ $total_value = 0;
+ //按价值比去排序
+ $sorted_product = $this->sortByPj_value($product);
+ //print_r($sorted_product);
+ $total = 0;
+ foreach ($sorted_product as $k => $v) {
+ if ($total + $v['weight'] <= $this->total_weight) {
+
+ $total_value += $v['value'];
+
+ $total += $v['weight'];
+ } elseif ($total < $this->total_weight) {
+
+ for ($j = $k + 1; $j < count($sorted_product); $j++) {
+ if (($sorted_product[$j]['weight'] + $total) <= 150) {
+ $total_value += $sorted_product[$j]['value'];
+ $total += $sorted_product[$j]['weight'];
+ }
+ }
+
+ break;
+
+ }else{
+
+ break;
+ }
+ }
+
+ return [$total ,$total_value ];
+
+ }
+
+ private function sortByPj_value($product)
+ {
+ for ($i = 0; $i < count($product); $i++) {
+ for ($j = $i + 1; $j < count($product); $j++) {
+ if ($product[$i]['pj_value'] < $product[$j]['pj_value']) {
+ $temp = $product[$i];
+ $product[$i] = $product[$j];
+ $product[$j] = $temp;
+ }
+ }
+
+ }
+ return $product;
+ }
+}
+
+$obj = new Knapsack([35, 30, 60, 50, 40, 15, 10],[10, 40, 30, 50, 35, 40, 30],150);
+var_dump($obj->bag());
+
+
+
diff --git a/src/Other/Maze.php b/src/Other/Maze.php
new file mode 100644
index 0000000..1efd0a0
--- /dev/null
+++ b/src/Other/Maze.php
@@ -0,0 +1,288 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 构造迷宫二维数组
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+//迷宫一
+for ($l = 0; $l <= 5; $l++) {
+ for ($m = 0; $m <= 5; $m++) {
+ if ($l == 1 && $m <= 3)
+ $arr[$l][$m] = 0;
+ elseif ($l == 2 && ($m == 1 || $m == 3 || $m == 4))
+ $arr[$l][$m] = 0;
+ elseif ($l == 3 && $m <= 4 && $m != 0 && $m != 3)
+ $arr[$l][$m] = 0;
+ elseif ($l == 4 && ($m == 1 || $m >= 4))
+ $arr[$l][$m] = 0;
+ else
+ $arr[$l][$m] = 1;
+
+ echo $arr[$l][$m] . ' ';
+ }
+ echo '
';
+}
+echo '
寻地址算法的实现:
';
+
+/**
+ * findPath
+ *
+ * @param $i
+ * @param $j
+ * @param $dir
+ * @param $arr
+ * @param $iline
+ * @param $jline
+ * @param $dirline
+ * @return int
+ */
+function findPath($i, $j, $dir, $arr, $iline, $jline, $dirline)
+{
+
+ //判断是否结束
+ if ($i == 4 && $j == 5) return 1;
+ $ifdirs = 0;
+ $newdir = $dir;
+ $lastdir = $dir;
+
+
+ //如果该点为0,则前进
+ if ($arr[$i][$j] == 0) {
+ //判断方向增量
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+
+ //判断是否路口
+ for ($n = 1; $n <= 4; $n++) {
+ switch ($newdir) {
+ case 0:
+ $aa = 0;
+ $bb = 1;
+ break;
+ case 1:
+ $aa = 1;
+ $bb = 0;
+ break;
+ case 2:
+ $aa = 0;
+ $bb = -1;
+ break;
+ case 3:
+ $aa = -1;
+ $bb = 0;
+ break;
+ }
+ if ($arr[($i + $aa)][($j + $bb)] == 0) {
+ $ifdirs++;
+ }
+ $newdir = ($newdir + 1) % 4;
+ }
+
+ //判断是否路口,是则记录位置和方向
+ if ($ifdirs > 2) {
+
+ if (in_array($i, $iline) && in_array($j, $jline)) {
+ } else {
+ echo "该点是路口:|$i,$j,$dir|
";
+ $iline[] = $i;
+ $jline[] = $j;
+ $dirline[] = $dir;
+ }
+ }
+
+ if ($ifdirs > 1) {
+ //不是死路,前进
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ //方向不变,可以前进
+ $i += $ii;
+ $j += $jj;
+ echo "方向不变,可以前进:|$i,$j,$dir|
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ } else {
+ //方向改变,试探
+ if ($ifdirs > 2) {
+ //该点是路口,取来时方向为路口记录方向
+ $lastdir = $dirline[(count($dirline) - 1)];
+ } else {
+ //不是路口,则在改变方向前记录方向
+ $lastdir = $dir;
+ }
+
+ //判断来时方向,不能走回头路
+ switch ($lastdir) {
+ case 0:
+ $errdir = 2;
+ break;
+ case 1:
+ $errdir = 3;
+ break;
+ case 2:
+ $errdir = 0;
+ break;
+ case 3:
+ $errdir = 1;
+ break;
+ }
+ //改变方向
+ $dir = ($dir + 1) % 4;
+
+ //判断改变后方向是否为来时方向
+ echo "不能走回头路:err:$errdir,dir:$dir
";
+ if ($dir != $errdir) {
+ echo "turn:($i,$j,$dir)
";
+ switch ($dir) {
+ case 0:
+ $mm = 0;
+ $nn = 1;
+ break;
+ case 1:
+ $mm = 1;
+ $nn = 0;
+ break;
+ case 2:
+ $mm = 0;
+ $nn = -1;
+ break;
+ case 3:
+ $mm = -1;
+ $nn = 0;
+ break;
+ }
+ if ($arr[($i + $mm)][($j + $nn)] == 0) {
+ $i += $mm;
+ $j += $nn;
+ echo "可以前进:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ } else {
+ $dir = ($dir + 1) % 4;
+ echo "再改变方向,试探:$i,$j,$dir
";
+ if ($dir != $errdir) {
+ echo "turn:($i,$j,$dir)
";
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ $i += $ii;
+ $j += $jj;
+ echo "可以前进:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ }
+ } else {
+ $dir = ($dir + 1) % 4;
+ echo "再改变方向,试探:$i,$j,$dir
";
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ $i += $ii;
+ $j += $jj;
+ echo "OK:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ }
+
+ }
+ }
+
+ } else {
+ $dir = ($dir + 1) % 4;
+ echo "不能回头,再改变方向,试探:$i,$j,$dir
";
+ switch ($dir) {
+ case 0:
+ $ii = 0;
+ $jj = 1;
+ break;
+ case 1:
+ $ii = 1;
+ $jj = 0;
+ break;
+ case 2:
+ $ii = 0;
+ $jj = -1;
+ break;
+ case 3:
+ $ii = -1;
+ $jj = 0;
+ break;
+ }
+ if ($arr[($i + $ii)][($j + $jj)] == 0) {
+ $i += $ii;
+ $j += $jj;
+ echo "可以前进:$i,$j,$dir
";
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+ }
+ }
+ }
+ } else {
+ //是死路,需要返回到上个路口,改变方向,试探
+ $dir = $dirline[(count($dirline) - 1)];
+ $i = $iline[(count($iline) - 1)];
+ $j = $jline[(count($jline) - 1)];
+ echo "是死路,返回到上个路口,记录为:#$i,$j,$dir#
";
+ $dir = ($dir + 1) % 4;
+ findPath($i, $j, $dir, $arr, $iline, $jline, $dirline);
+
+ }
+
+ }
+}
+
+$a[] = $b[] = $c[] = 0;
+echo '初始值=>节点:($i=1,$j=1),方向:($dir=0).
';
+findPath(1, 1, 0, $arr, $a, $b, $c);
\ No newline at end of file
diff --git a/package/Other/MonkeyKing.php b/src/Other/MonkeyKing.php
similarity index 64%
rename from package/Other/MonkeyKing.php
rename to src/Other/MonkeyKing.php
index c1fca9f..8e25abd 100644
--- a/package/Other/MonkeyKing.php
+++ b/src/Other/MonkeyKing.php
@@ -5,12 +5,18 @@
*
* @author Pu ShaoWei
* @date 2017/8/23
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:约瑟夫环问题
* -------------------------------------------------------------
* 有M个monkey ,转成一圈,第一个开始数数,数到第N个出圈,下一个再从1开始数,再数到第N个出圈,直到圈里只剩最后一个就是大王
*/
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
class MonkeyKing
{
protected $next;
@@ -38,7 +44,7 @@ public static function whoIsKing($count, $num)
{
// 构造单向循环链表
$current = $first = new MonkeyKing(1);
- for ($i = 2; $i <= $count; $i++){
+ for ($i = 2; $i <= $count; $i++) {
$current->next = new MonkeyKing($i);
$current = $current->next;
}
@@ -48,7 +54,7 @@ public static function whoIsKing($count, $num)
$current = $first;
// 定义一个数字
$cn = 1;
- while ($current !== $current->next){
+ while ($current !== $current->next) {
$cn++;
if ($cn == $num) {
$current->next = $current->next->next;
@@ -61,33 +67,59 @@ public static function whoIsKing($count, $num)
}
}
-// 共10个猴子每3个出圈
-var_dump(MonkeyKing::whoIsKing(10, 3));
-
-function whoIsKing($n,$m){
+/**
+ * whoIsKing
+ *
+ * @param $n
+ * @param $m
+ * @return int
+ */
+function whoIsKing($n, $m)
+{
$r = 0;
- for ($i=2; $i <= $n ; $i++) {
+ for ($i = 2; $i <= $n; $i++) {
$r = ($r + $m) % $i;
}
- return $r+1;
+ return $r + 1;
}
-var_dump(whoIsKing(10,3));
-
-function king($n, $m){
+/**
+ * king
+ *
+ * @param $n
+ * @param $m
+ * @return mixed
+ */
+function king($n, $m)
+{
$monkeys = range(1, $n);
- $i=0;
- $k=$n;
- while (count($monkeys)>1) {
- if(($i+1)%$m==0) {
+ $i = 0;
+ $k = $n;
+ while (count($monkeys) > 1) {
+ if (($i + 1) % $m == 0) {
unset($monkeys[$i]);
} else {
- array_push($monkeys,$monkeys[$i]);
+ array_push($monkeys, $monkeys[$i]);
unset($monkeys[$i]);
}
$i++;
}
return current($monkeys);
}
+
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+// 共10个猴子每3个出圈
+var_dump(MonkeyKing::whoIsKing(10, 3));
+
+
+var_dump(whoIsKing(10, 3));
+
+
$a = king(10, 3);
var_dump($a);
\ No newline at end of file
diff --git a/src/Other/NQueen.php b/src/Other/NQueen.php
new file mode 100644
index 0000000..5b16798
--- /dev/null
+++ b/src/Other/NQueen.php
@@ -0,0 +1,89 @@
+
+ * @date 2023/12/06
+ * @license MIT
+ */
+/*
+|--------------------------------------------------------------------------
+| NQueen Algorithm
+|--------------------------------------------------------------------------
+|
+| Arrange N queens on an NxN chessboard without attacking each other diagonally,
+| horizontally, or vertically—a classic problem in combinatorial optimization and
+| recursion.
+|
+*/
+
+class NQueen
+{
+
+ //Variable to store the dimensions of the chessboard
+ protected int $n;
+
+ //Chessboard represented as an array
+ protected array $board;
+
+ //Constructor to initialize the chessboard dimensions and fill it with zeros
+ public function __construct(int $n)
+ {
+ $this->n = $n;
+ $this->board = array_fill(0, $this->n, array_fill(0, $this->n, 0));
+ }
+
+ public function solve_n_queen($col = 0): void
+ {
+ if ($col >= $this->n) {
+ $this->print_result();
+ }
+
+ //Iterating through each row in the current column
+ for ($row = 0; $row < $this->n; $row++) {
+ if ($this->move_is_promising($row, $col)) {
+ //Placing the queen at the current position
+ $this->board[$row][$col] = 1;
+ //Recursively solving for the next column
+ $this->solve_n_queen($col + 1);
+ //Backtracking by removing the queen from the current position
+ $this->board[$row][$col] = 0;
+ }
+ }
+ }
+
+ public function move_is_promising($row, $col): bool
+ {
+ //Checking if there is no queen in the same row
+ for ($index = 0; $index < $col; $index++)
+ if ($this->board[$row][$index])
+ return false;
+
+ //Checking if there is no queen on the upper-left diagonal
+ for ($i = $row, $j = $col; $i >= 0 && $j >= 0; $i--, $j--)
+ if ($this->board[$i][$j])
+ return false;
+
+ //Checking if there is no queen on the lower-left diagonal
+ for ($i = $row, $j = $col; $i < $this->n && $j >= 0; $i++, $j--)
+ if ($this->board[$i][$j])
+ return false;
+
+ //If no conflicts are found, the move is promising
+ return true;
+ }
+
+ public function print_result(): void
+ {
+ for ($i = 0; $i < $this->n; $i++) {
+ for ($j = 0; $j < $this->n; $j++)
+ echo $this->board[$i][$j];
+ echo "\n";
+ }
+ echo "\n";
+ }
+}
+
+$dimensions = 4;
+(new NQueen($dimensions))->solve_n_queen();
diff --git a/package/Other/OnlyNumbers.php b/src/Other/OnlyNumbers.php
similarity index 58%
rename from package/Other/OnlyNumbers.php
rename to src/Other/OnlyNumbers.php
index e211a4a..f076a9d 100644
--- a/package/Other/OnlyNumbers.php
+++ b/src/Other/OnlyNumbers.php
@@ -5,14 +5,23 @@
*
* @author Pu ShaoWei
* @date 2017/8/30
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:快排同时做唯一标示
* -------------------------------------------------------------
* 一个数组里只有唯一一个元素是不同于别的元素,其余元素是两两相等如何得到这个元素
*
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
+/**
+ * OnlyNumbers
+ *
* @param array $container
- * @return mixed
+ * @return array|bool
*/
function OnlyNumbers(array $container)
{
@@ -31,9 +40,6 @@ function OnlyNumbers(array $container)
return !empty($exist) ? array_keys($exist)[0] : false;
}
-var_dump(OnlyNumbers([11, 22, 22, 11, 5, 63, 13, 5, 63, 18, 89, 13, 89]));
-
-
// +----------------------------------------------------------------------
// | 方法二
// +----------------------------------------------------------------------
@@ -51,4 +57,30 @@ function OnlyNumbersV2(array $container)
return isset($res[1]) ? $res[1] : null;
}
+// +----------------------------------------------------------------------
+// | 方法三
+// +----------------------------------------------------------------------
+/**
+ * @author Openset
+ * @link https://github.com/openset
+ * @date 2018/2/24
+ * @param array $container
+ * @return null
+ */
+function OnlyNumbersV3(array $container)
+{
+ $num = 0;
+ foreach ($container as $v) {
+ $num ^= $v;
+ }
+
+ return $num;
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+var_dump(OnlyNumbers([11, 22, 22, 11, 5, 63, 13, 5, 63, 18, 89, 13, 89]));
var_dump(OnlyNumbersV2([11, 22, 22, 11, 5, 63, 13, 5, 63, 18, 89, 13, 89]));
+var_dump(OnlyNumbersV3([11, 22, 22, 11, 5, 63, 13, 5, 63, 18, 89, 13, 89]));
diff --git a/src/Other/PointInTriangle.php b/src/Other/PointInTriangle.php
new file mode 100644
index 0000000..60b1452
--- /dev/null
+++ b/src/Other/PointInTriangle.php
@@ -0,0 +1,113 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * 利用向量叉集判断一个点是否在三角形中
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+class PointInTriangle
+{
+ /**
+ * @var array
+ */
+ protected $point;
+ /**
+ * @var array
+ */
+ protected $triangle;
+
+ /**
+ * PointInTriangle constructor.
+ *
+ * @param array $point
+ * @param array $triangle
+ */
+ public function __construct(array $point, array $triangle)
+ {
+ $this->point = $point;
+ if (count($triangle) != 3) {
+ exit('这个不是三角形');
+ }
+ $this->triangle = $triangle;
+ }
+
+ /**
+ * 向量叉集计算
+ *
+ * @param $a
+ * @param $b
+ * @param $p
+ * @return mixed
+ */
+ private function cross($a, $b, $p)
+ {
+ return ($b['x'] - $a['x']) * ($p['y'] - $a['y']) - ($b['y'] - $a['y']) * ($p['x'] - $a['x']);
+ }
+
+ /**
+ * 判断是否在左边
+ *
+ * @param $a
+ * @param $b
+ * @param $p
+ * @return bool
+ */
+ private function toLeft($a, $b, $p)
+ {
+ return $this->cross($a, $b, $p) > 0;
+ }
+
+ /**
+ * 开始构造三角形
+ *
+ * @return string
+ */
+ public function inTriangle()
+ {
+ $res = $this->toLeft($this->triangle[0], $this->triangle[1], $this->point);
+
+ if ($res != $this->toLeft($this->triangle[1], $this->triangle[2], $this->point)) {
+ return '不在三角形中';
+ }
+ if ($res != $this->toLeft($this->triangle[2], $this->triangle[0], $this->point)) {
+ return '不在三角形中';
+ }
+
+ if ($this->cross($this->triangle[0], $this->triangle[1], $this->triangle[2]) == 0) {
+ return '不在三角形中';
+ }
+ return '点' . json_encode($this->point) . '在三角形中';
+ }
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+$point = [
+ 'x' => 4,
+ 'y' => 1
+];
+$point1 = [
+ 'x' => 4,
+ 'y' => 5
+];
+$triangle = [
+ ['x' => 1, 'y' => 1],
+ ['x' => 6, 'y' => 3],
+ ['x' => 4, 'y' => 7],
+];
+
+$obj = new PointInTriangle($point1, $triangle);
+var_dump($obj->inTriangle());
+exit;
\ No newline at end of file
diff --git a/package/Other/PokerGames.php b/src/Other/PokerGames.php
similarity index 78%
rename from package/Other/PokerGames.php
rename to src/Other/PokerGames.php
index 850f55d..da0aa9b 100644
--- a/package/Other/PokerGames.php
+++ b/src/Other/PokerGames.php
@@ -6,44 +6,74 @@
* @author Pu ShaoWei
* @date 2017/9/18
* @license MIT
+ * -------------------------------------------------------------
+ * 随机玩法
*/
-$card_num = 54;//牌数
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * washCard
+ *
+ * @param $card_num
+ * @return array
+ */
function washCard($card_num)
{
- $cards = $tmp = array ();
- $tmp = range(0, $card_num);
- for ($i = 0; $i < $card_num; $i++) {
- $index = rand(0, $card_num - $i - 1);
- $cards[$i] = $tmp[$index];
- unset($tmp[$index]);
- $tmp = array_values($tmp);
+ $cards = range(1, $card_num);
+ for ($i = $card_num - 1; $i > 0; $i--) {
+ $rnd = rand(0, $i - 1);
+ list($cards[$rnd], $cards[$i]) = array ($cards[$i], $cards[$rnd]);
}
return $cards;
}
-// 测试:
-//var_dump(washCard($card_num));die;
/**
* PokerGames 纯属娱乐,有空再优化, 这样够随机吧
- *
- * @uses description
- * @version 1.0
- * @author Pu ShaoWei
*/
class PokerGames
{
+ /**
+ *
+ */
const RANDOM = "https://www.random.org/integers/?num=%d&min=1&max=%d&col=1&base=10&format=plain&rnd=new";
- const LIMIT = 10;
+ /**
+ *
+ */
+ const LIMIT = 10;
+ /**
+ * @var
+ */
protected $resources;
+ /**
+ * @var
+ */
protected $tally;
+ /**
+ * @var float
+ */
protected $i;
+ /**
+ * @var
+ */
protected $count;
+ /**
+ * @var bool
+ */
protected $clear;
+ /**
+ * @var array
+ */
protected $container = array ();
- protected $poker = array ();
+ /**
+ * @var array
+ */
+ protected $poker = array ();
/**
* PokerGames constructor.
@@ -167,4 +197,10 @@ public function makeRand($max)
}
}
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+$card_num = 54;//牌数
+var_dump(washCard($card_num));
new PokerGames();
diff --git a/src/Other/Prim.php b/src/Other/Prim.php
new file mode 100644
index 0000000..0640ae9
--- /dev/null
+++ b/src/Other/Prim.php
@@ -0,0 +1,78 @@
+lowcost[$i] = $graph[0][$i];
+ $mst[$i] = 0;
+ }
+ for ($i = 1; $i < $n; $i++) {
+ $min = 65535;
+ $minid = 0;
+ for ($j = 1; $j < $n; $j++) {
+ if ($this->lowcost[$j] < $min && $this->lowcost[$j] != 0) {
+ $min = $this->lowcost[$j];
+ $minid = $j;
+ }
+ }
+ echo '';
+ print_r($this->c[$mst[$minid]] ."到" . $this->c[$minid] . " 权值:" . $min);
+ echo '
';
+
+ $sum += $min;
+ $this->lowcost[$minid] = 0;
+
+ for ($j = 1; $j < $n; $j++) {
+ if ($graph[$minid][$j] < $this->lowcost[$j]) {
+ $this->lowcost[$j] = $graph[$minid][$j];
+ $mst[$j] = $minid;
+ }
+ }
+ }
+ print_r("sum:" . $sum);
+ }
+
+ public function main()
+ {
+ $map = [
+ [0, 10, 65535, 65535, 65535, 11, 65535, 65535, 65535],
+ [10, 0, 18, 65535, 65535, 65535, 16, 65535, 12],
+ [65535, 65535, 0, 22, 65535, 65535, 65535, 65535, 8],
+ [65535, 65535, 22, 0, 20, 65535, 65535, 16, 21],
+ [65535, 65535, 65535, 20, 0, 26, 65535, 7, 65535],
+ [11, 65535, 65535, 65535, 26, 0, 17, 65535, 65535],
+ [65535, 16, 65535, 65535, 65535, 17, 0, 19, 65535],
+ [65535, 65535, 65535, 16, 7, 65535, 19, 0, 65535],
+ [65535, 12, 8, 21, 65535, 65535, 65535, 65535, 0]
+ ];
+ $this->prim_main($map, count($map));
+ }
+}
+
+$obj = new Prim();
+$obj->main();
diff --git a/src/Other/Rectangle.php b/src/Other/Rectangle.php
new file mode 100644
index 0000000..725a951
--- /dev/null
+++ b/src/Other/Rectangle.php
@@ -0,0 +1,88 @@
+$value) {
+ $x = abs($value[0]-$one[0]);
+ $y = abs($value[1]-$one[1]);
+ $data[$key] = sqrt(pow($x,2)+pow($y,2));
+ }
+
+ asort($data);
+ $keys = array_keys($data);
+ $maxKey = array_pop($keys);//对焦点
+ $length0 = $data[$maxKey];//对角线长度
+
+ //左右两点 key
+ $left = $keys[0];
+ $right = $keys[1];
+
+ //算第二条对角线长度
+ $x = abs($array[$left][0]-$array[$right][0]);
+ $y = abs($array[$left][1]-$array[$right][1]);
+ $length = sqrt(pow($x,2)+pow($y,2));
+
+ if(!floatEq($length,$length0)) {
+ return false;
+ }
+
+ //算直角
+ $vertical = sqrt(pow($data[$left],2)+pow($data[$right],2));
+
+ if(!floatEq($length,$vertical)) {
+ return false;
+ }
+
+ return true;
+
+}
+
+var_dump(rectangle([0,0],[0,1],[1,1],[1,0])); //true
+var_dump(rectangle([1,2],[0,1],[1,1],[1,0])); //false
+
+/**
+ * 判断两个浮点数是不是相等
+ *
+ * @param $a float
+ * @param $b float
+ * @return bool
+ */
+function floatEq($floatNumber1,$floatNumber2)
+{
+ if(!$floatNumber1 || !$floatNumber2) {
+ return false;
+ }
+ //精度
+ $epsilon = 0.00001;
+
+ if(abs($floatNumber1-$floatNumber2) < $epsilon) {
+ return true;
+ }
+ return false;
+}
diff --git a/src/Other/RotateSort.php b/src/Other/RotateSort.php
new file mode 100644
index 0000000..2fefd3c
--- /dev/null
+++ b/src/Other/RotateSort.php
@@ -0,0 +1,166 @@
+ |
+ * | Date: 2019/10/11 |
+ * | Time: 下午2:56 |
+ * ----------------------------------------
+ * | _____ ______ _ _ |
+ * | | __ \| ____(_) | | |
+ * | | |__) | |__ _ _ __ __ _| | |
+ * | | ___/| __| | | '_ \ / _` | | |
+ * | | | | | | | | | | (_| | | |
+ * | |_| |_| |_|_| |_|\__,_|_| |
+ * ----------------------------------------
+ * 说明: 面试遇到一个写一个函数 让输出效果 如风车一样旋转 如下
+ * foo(4) 逆时针
+ * 16,15,14,13
+ * 5, 4, 3, 12
+ * 6, 1, 2, 11
+ * 7, 8, 9, 10
+ * foo(4) 顺顺时针
+ * 7, 8, 9, 10
+ * 6, 1, 2, 11
+ * 5, 4, 3, 12
+ * 16,15, 14,13
+ *
+ */
+
+ $num = 4;
+ $arr = foo($num);
+ for ($i = 0; $i < $num; $i++) {
+ echo implode(',', $arr[$i])."
";
+ }
+
+ /**
+ * @param $num
+ * @param int $direction 方向 1 为 顺时针旋转 2 为逆时针旋转
+ * @return mixed
+ */
+ function foo($num, $direction = 1)
+ {
+ //填充map
+ $data = new stdClass();
+ $data->x = 1;
+ if ($direction == 1) {
+ $data->y = $num;
+ } elseif ($direction == 2) {
+ $data->y = 1;
+ }
+ $data->num = $num;
+ $data->len = $num * $num;
+ $data->tmp_data = [];
+ $data->rate = 1;//方向
+ $data->struct = create_struct($num);
+ for ($i = $data->len; $i >= 1; $i--) {
+ $data->i = $i;
+ $key = change_key($data, $direction);
+ $data->tmp_data[$key] = $i;
+ unset($data->struct[$key]);
+ }
+
+ //根据y坐标分组
+ $data->struct = create_struct($num);
+ foreach ($data->tmp_data as $key => $value) {
+ $data->struct[$key] = $value;
+ }
+ for ($i = 1; $i <= $data->num; $i++) {
+ $start = ($i - 1) * $data->num;
+ $end = $data->num;
+ $slice = array_slice($data->struct, $start, $end);
+ $data->slice[] = $slice;
+ }
+
+ return $data->slice;
+ }
+
+ function create_struct($num)
+ {
+ $struct = [];
+ for ($i = 1; $i <= $num; $i++) {
+ //嵌套
+ for ($m = 1; $m <= $num; $m++) {
+ $key = $m.','.$i;
+ $struct[$key] = '';
+ }
+ }
+
+ return $struct;
+ }
+
+ function change_key($data, $direction)
+ {
+ $key = $data->x.','.$data->y;
+ if (isset($data->struct[$key])) {
+ return $key;
+ }
+ switch ($data->rate) {
+ // LEFT 方向
+ case 1:
+ $data->tmp_x = $data->x + 1;
+ $key = $data->tmp_x.','.$data->y;
+ if (isset($data->struct[$key])) {
+ $data->x = $data->tmp_x;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 4;
+ } elseif ($direction = 2) {
+ $data->rate = 2;
+ }
+ }
+ break;
+ // DOWN 方向
+ case 2:
+ $data->tmp_y = $data->y + 1;
+ $key = $data->x.','.$data->tmp_y;
+ if (isset($data->struct[$key])) {
+ $data->y = $data->tmp_y;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 1;
+ } elseif ($direction = 2) {
+ $data->rate = 3;
+ }
+ }
+ break;
+ // RIGHT 方向
+ case 3:
+ $data->tmp_x = $data->x - 1;
+ $key = $data->tmp_x.','.$data->y;
+ if (isset($data->struct[$key])) {
+ $data->x = $data->tmp_x;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 2;
+ } elseif ($direction = 2) {
+ $data->rate = 4;
+ }
+ }
+ break;
+ // UP 方向
+ case 4:
+ $data->tmp_y = $data->y - 1;
+ $key = $data->x.','.$data->tmp_y;
+ if (isset($data->struct[$key])) {
+ $data->y = $data->tmp_y;
+
+ return $key;
+ } else {
+ if ($direction = 1) {
+ $data->rate = 3;
+ } elseif ($direction = 2) {
+ $data->rate = 1;
+ }
+ }
+ break;
+ }
+
+ return change_key($data, $direction);
+ }
\ No newline at end of file
diff --git a/src/Other/RotationSort.php b/src/Other/RotationSort.php
new file mode 100644
index 0000000..48d538a
--- /dev/null
+++ b/src/Other/RotationSort.php
@@ -0,0 +1,76 @@
+row = $row;
+ $this->col =$col;
+ $this->start = $start;
+ $this->print_matrix();
+ }
+
+ private function print_matrix()
+ {
+ //当前遍历层数
+ $small =$this->col < $this->row ?$this->col : $this->row;
+
+ $count = ceil($small / 2);
+
+ for($i=0; $i < $count; $i++)
+ {
+ $maxRight = $this->col -1 - $i; //右边最大坐标
+ $maxBottom = $this->row -1 - $i; //下面最大坐标
+
+ for($j=$i; $j<=$maxRight; $j++)
+ {
+ $this->res[$i][$j] = $this->start++;
+ }
+ for($j=$i; $j<$maxBottom; $j++)
+ {
+ $this->res[$j+1][$maxRight] = $this->start++;
+ }
+ for($j=$maxRight-1;$j>=$i; $j--)
+ {
+ if(isset($this->res[$maxBottom][$j])) break;
+ $this->res[$maxBottom][$j] = $this->start++;
+ }
+ for($j=$maxBottom-1;$j>$i;$j--)
+ {
+ if(isset($this->res[$j][$i])) break;
+ $this->res[$j][$i] = $this->start++;
+ }
+ }
+ }
+
+ /**
+ * @return string
+ * 输出回旋形状
+ */
+ public function print_table()
+ {
+ $str = '';
+ for ($i = 0; $i < $this->row; $i++) {
+ $str .='';
+ for ($j = 0; $j < $this->col; $j++) {
+ $str .='| '.$this->res[$i][$j] . " | ";
+ }
+ $str .="
";
+ }
+ $str .='
';
+ return $str;
+ }
+}
+
+$obj = new RotationSort(7, 8);
+echo $obj->print_table();
\ No newline at end of file
diff --git a/src/Other/Solution.php b/src/Other/Solution.php
new file mode 100644
index 0000000..27aca0c
--- /dev/null
+++ b/src/Other/Solution.php
@@ -0,0 +1,63 @@
+grid = $grid;
+ $this->islandPerimeter();
+ }
+
+ public function islandPerimeter()
+ {
+ if (empty($this->grid) || empty($this->grid[0])) return 0;
+
+ foreach ($this->grid as $key => $val) {
+
+ foreach ($this->grid[0] as $k => $v) {
+ if ($this->grid[$key][$k] == 0) continue;
+ $this->result += 4;
+
+ if ($key > 0 && $this->grid[$key - 1][$k] == 1) {
+ $this->result -= 2;
+ }
+ if ($k > 0 && $this->grid[$key][$k - 1] == 1) {
+ $this->result -= 2;
+ }
+ }
+ }
+ }
+}
+
+$arr = [
+ [0,1,0,0],
+ [1,1,1,0],
+ [0,1,0,0],
+ [1,1,0,0]
+];
+
+$result = new Solution($arr);
+var_dump($result->result);
\ No newline at end of file
diff --git a/src/Other/Square.php b/src/Other/Square.php
new file mode 100644
index 0000000..0566953
--- /dev/null
+++ b/src/Other/Square.php
@@ -0,0 +1,43 @@
+point = $point;
+ }
+
+ public function check()
+ {
+ $result = [];
+ if (count($this->point) != 4) return false;
+ for ($i = 0; $i < 4; $i++) {
+ for ($j = $i + 1; $j < 4; $j++) {
+ $result[]=$this->_calculation($i,$j);
+ }
+ }
+ sort($result);
+ if ($result[0] == $result[1] && $result[4] == $result[5] && $result[4] > $result[1]) {
+ return true;
+ }
+ return false;
+
+ }
+
+ private function _calculation($i, $j)
+ {
+ return pow($this->point[$i][0] - $this->point[$j][0],2) + pow($this->point[$i][1] - $this->point[$j][1] ,2);
+ }
+}
+
+$obj = new Square([[0, 0], [1, 0], [1, 1], [0, 1]]);
+var_dump($obj->check());
diff --git a/package/Other/StealingApples.php b/src/Other/StealingApples.php
similarity index 80%
rename from package/Other/StealingApples.php
rename to src/Other/StealingApples.php
index 3bd223d..5d821a3 100644
--- a/package/Other/StealingApples.php
+++ b/src/Other/StealingApples.php
@@ -5,7 +5,7 @@
*
* @author Pu ShaoWei
* @date 2017/8/26
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:
* -------------------------------------------------------------
@@ -14,8 +14,13 @@
* 没想到其他四人也都是这么想的,都如第一个人一样分成5份把多的那一个扔给了猴,偷走了1/5。
* 第二天,大家分赃,也是分成5份多一个扔给猴了。最后一人分了一份。
* 问:共有多少苹果?N 个人呢?
+ * -------------------------------------------------------------
*/
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
$i = 1;
while (true) {
if ($i % 5 == 1) {
@@ -69,3 +74,8 @@
}
//15621
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
diff --git a/src/Query/BFSQuery.php b/src/Query/BFSQuery.php
new file mode 100644
index 0000000..cd7c142
--- /dev/null
+++ b/src/Query/BFSQuery.php
@@ -0,0 +1,174 @@
+
+ * @date 2017/6/17
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析: BFS并不使用经验法则算法。从算法的观点,所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中
+ * 时间复杂度:O(n)
+ * -------------------------------------------------------------
+ * 宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。
+ * Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。
+ * 其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。
+ * 换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
+ */
+class BFSQuery
+{
+ /**
+ * @var array 关系网络
+ */
+ protected $relationship;
+ /**
+ * @var \SplQueue 处理队列
+ */
+ protected $queue;
+
+ /**
+ * @var string 搜索结果
+ */
+ protected $target;
+
+ /**
+ * BFSQuery constructor.
+ *
+ * @param array $relationship
+ * @param string $target
+ */
+ public function __construct(array $relationship, $target)
+ {
+
+ $this->relationship = $relationship;
+ $this->queue = new SplQueue();
+ $this->target = $target;
+ $this->generator($this->relationship);
+ }
+
+ /**
+ * 开始入列
+ *
+ * @param array $relation
+ * @return \Generator
+ */
+ public function generator($relation)
+ {
+ foreach ($relation as $value) {
+ $this->schedule($value);
+ }
+ }
+
+
+ /**
+ * 队列入队
+ *
+ * @param $item
+ * @return int
+ */
+ public function schedule($item)
+ {
+ $this->queue->enqueue($item);
+ }
+
+ /**
+ * 队列中查找符合条件
+ *
+ * @return string
+ */
+ public function run()
+ {
+ $result = $this->target . '没有人有~!';
+ while (!$this->queue->isEmpty()) {
+ // 出队列
+ $item = $this->queue->dequeue();
+ if (!isset($item['friend'])) {
+ continue;
+ }
+ if (!isset($item['fruit'])) {
+ continue;
+ }
+ $totalFruit = count($item['fruit']);
+ $mark = 0;
+ while ($totalFruit > $mark) {
+ if ($item['fruit'][$mark] === $this->target) {
+ $result = '找到了~!';
+ break 2;
+ }
+ $mark++;
+ }
+ $this->generator($item['friend']);
+ }
+ return $result;
+ }
+}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试
+// +--------------------------------------------------------------------------
+// 你现在需要一个 `mango` ,所以你需要在你的朋友圈里搜刮,你可以先从Jack 与 tom 身上找,
+// 然后再从他们的朋友身上找,然后再从他们朋友的朋友哪里找
+
+$me = array (
+ 'jack' => array (
+ 'fruit' => array ('apple', 'banana', 'dragon'),
+ 'friend' => array (
+ 'lucy' => array (
+ 'fruit' => array ('bear', 'watermelon'),
+ 'friend' => array (
+ 'marco' => array (
+ 'fruit' => array ('mango', 'cherry'), // Mango 在这儿
+ 'friend' => array (
+ '...',
+ )
+ ),
+ ),
+ ),
+ 'bob' => array (
+ 'fruit' => array ('orange', 'mangosteen', 'peach'),
+ 'friend' => array (
+ '',
+ ),
+ ),
+
+ ),
+ ),
+ 'tom' => array (
+ 'fruit' => array (
+ 'apple',
+ 'banana',
+ ),
+ 'friend' => array (
+ 'lucy' => array (
+ 'fruit' => array (),
+ 'friend' => array (
+ 'lucy' => array (
+ 'fruit' => array ('bear', 'watermelon'),
+ 'friend' => array (
+ 'marco' => array (
+ 'fruit' => array ('mango', 'cherry'), // Mango 在这儿也有
+ 'friend' => array (
+ '...',
+ )
+ ),
+ ),
+ ),
+ ),
+ ),
+ 'bob' => array (
+ 'fruit' => array ('apple', 'peach'),
+ 'friend' => array (
+ 'marco' => array (
+ 'fruit' => array ('mango', 'cherry'), // Mango 在这儿也有
+ 'friend' => array (
+ 'Marco 有无数多的盆友...',
+ )
+ ),
+ )
+ ),
+ ),
+ )
+);
+
+echo (new BFSQuery($me, 'mango'))->run();
\ No newline at end of file
diff --git a/src/Query/BinaryQuery.php b/src/Query/BinaryQuery.php
new file mode 100644
index 0000000..167da6b
--- /dev/null
+++ b/src/Query/BinaryQuery.php
@@ -0,0 +1,101 @@
+
+ * @date 2017/6/17
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:数组中间的值floor((low+top)/2)
+ * -------------------------------------------------------------
+ * 先取数组中间的值floor((low+top)/2)然后通过与所需查找的数字进行比较,
+ * 若比中间值大则将首值替换为中间位置下一个位置,继续第一步的操作;
+ * 若比中间值小,则将尾值替换为中间位置上一个位置,继续第一步操作
+ * 重复第二步操作直至找出目标数字
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * 非递归版 二分查找
+ *
+ * @param array $container
+ * @param $search
+ * @return int|string
+ */
+function BinaryQuery(array $container, $search)
+{
+ $top = count($container);
+ $low = 0;
+ while ($low <= $top) {
+ $mid = intval(floor(($low + $top) / 2));
+ if (!isset($container[$mid])) {
+ return '没找着哦';
+ }
+ if ($container[$mid] == $search) {
+ return $mid;
+ }
+ $container[$mid] < $search && $low = $mid + 1;
+ $container[$mid] > $search && $top = $mid - 1;
+ }
+}
+
+
+/**
+ * 递归版 二分查找
+ *
+ * @param array $container
+ * @param $search
+ * @param int $low
+ * @param string $top
+ * @return int|string
+ */
+function BinaryQueryRecursive(array $container, $search, $low = 0, $top = 'default')
+{
+ $top === 'default' && $top = count($container);
+ if ($low <= $top) {
+ $mid = intval(floor($low + $top) / 2);
+ if (!isset($container[$mid])) {
+ return '没找着哦';
+ }
+ if ($container[$mid] == $search) {
+ return $mid;
+ }
+ if ($container[$mid] < $search) {
+ return BinaryQueryRecursive($container, $search, $mid + 1, $top);
+ } else {
+ return BinaryQueryRecursive($container, $search, $low, $mid - 1);
+ }
+ }
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+var_dump(BinaryQuery([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9));
+/*
+ * double(8)
+ */
+var_dump(BinaryQueryRecursive([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9));
+/*
+array(7) {
+ [0] =>
+ int(3)
+ [1] =>
+ int(4)
+ [2] =>
+ int(5)
+ [3] =>
+ int(6)
+ [4] =>
+ int(7)
+ [5] =>
+ int(8)
+ [6] =>
+ int(9)
+}
+*/
diff --git a/src/Query/DijkstraQuery.php b/src/Query/DijkstraQuery.php
new file mode 100644
index 0000000..cf54ce9
--- /dev/null
+++ b/src/Query/DijkstraQuery.php
@@ -0,0 +1,134 @@
+
+ * @date 2017/8/23
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:单源最短路径问题
+ * -------------------------------------------------------------
+ * Dijkstra 算法一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,
+ * 这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。
+ * 因此,在包含负边全的图中要找出最短路径,可以使用另一种算法 -- 贝克曼-福德算法
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
+/**
+ * DijkstraQuery
+ *
+ * @uses PHPStorm
+ * @version 1.0
+ * @author Pu ShaoWei
+ */
+class DijkstraQuery
+{
+ /**
+ * @var array
+ */
+ protected $graph;
+ /**
+ * @var array
+ */
+ protected $processed;
+ /**
+ * @var int
+ */
+ protected $infinity;
+ /**
+ * @var string
+ */
+ protected $start;
+ /**
+ * @var string
+ */
+ protected $end;
+
+ /**
+ * DijkstraQuery constructor.
+ *
+ * @param array $graph
+ * @param $start
+ * @param $end
+ */
+ public function __construct(array $graph, $start, $end)
+ {
+ $this->graph = $graph;
+ $this->start = $start;
+ $this->end = $end;
+ $this->processed = array ();
+ $this->infinity = mt_getrandmax();
+ }
+
+ /**
+ * 最短路径
+ *
+ * @return string
+ */
+ public function calculate()
+ {
+ $costs = $this->graph[$this->start];
+ $costs[$this->end] = $this->infinity;
+ $node = $this->findLowestCostNode($costs);
+
+ while (null !== $node) {
+ $cost = $costs[$node];
+ $neighbors = $this->graph[$node] ?? array ();
+ foreach ($neighbors as $neighbor => $distance) {
+ $newCost = $cost + $distance;
+ if ($costs[$neighbor] > $newCost) {
+ $costs[$neighbor] = $newCost;
+ }
+ }
+ array_push($this->processed, $node);
+ $node = $this->findLowestCostNode($costs);
+ }
+
+ return 'The shortest distance for:' . $costs[$this->end];
+ }
+
+ /**
+ * findLowestCostNode
+ *
+ * @param $costs
+ * @return null
+ */
+ protected function findLowestCostNode($costs)
+ {
+ $lowestCost = $this->infinity;
+ $lowestCostNode = null;
+ foreach ($costs as $node => $cost) {
+ if ($cost < $lowestCost && !in_array($node, $this->processed)) {
+ $lowestCost = $cost;
+ $lowestCostNode = $node;
+ }
+ }
+ return $lowestCostNode;
+ }
+}
+
+// +--------------------------------------------------------------------------
+// | 验证 me --> claire
+// +--------------------------------------------------------------------------
+// ∞
+$graph = array (
+ 'me' => array (
+ 'alice' => 6,
+ 'bob' => 2,
+ ),
+ 'alice' => array (
+ 'claire' => 1,
+ ),
+ 'bob' => array (
+ 'alice' => 3,
+ 'claire' => 5,
+ ),
+ 'claire' => array (// 没有任何邻居
+
+ ),
+);
+echo (new DijkstraQuery($graph, 'me', 'claire'))->calculate();
\ No newline at end of file
diff --git a/package/Query/FibonacciQuery.php b/src/Query/FibonacciQuery.php
similarity index 63%
rename from package/Query/FibonacciQuery.php
rename to src/Query/FibonacciQuery.php
index 4e1b3d0..1c57fc2 100644
--- a/package/Query/FibonacciQuery.php
+++ b/src/Query/FibonacciQuery.php
@@ -1,27 +1,33 @@
* @date 2017/8/23
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:斐波那契查找 利用黄金分割原理
* -------------------------------------------------------------
- *
* $num == $container[$mid],直接返回
* $num < $container[$mid],新范围是第 $low 个到 $mid-1 个,此时范围个数为 produced($key-1)-1 个
* $num > $container[$mid],新范围是第 $mid+1 个到 $high 个,此时范围个数为 produced($key-2)-1 个
*/
-class FibonacciQuery{
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
+class FibonacciQuery
+{
/**
* FibonacciQuery constructor.
*
* @param array $container
* @param $num
*/
- public function __construct(array $container,$num)
+ public function __construct(array $container, $num)
{
$count = count($container);
$lower = $key = $result = 0;
@@ -32,26 +38,28 @@ public function __construct(array $container,$num)
}
//将不满的数值补全,补的数值为数组的最后一位
for ($j = $count; $j < $this->produced($key) - 1; $j++) {
- $container[ $j ] = $container[ $count - 1 ];
+ $container[$j] = $container[$count - 1];
}
//查找开始
while ($lower <= $high) {
//计算当前分隔的下标
$mid = $lower + $this->produced($key - 1) - 1;
- if ($num < $container[ $mid ]) {
- $high = $mid - 1;
- $key -= 1; //斐波那契数列数列下标减一位
- }else if ($num > $container[ $mid ]) {
- $lower = $mid + 1;
- $key -= 2; //斐波那契数列数列下标减两位
+ if ($num < $container[$mid]) {
+ $high = $mid - 1;
+ $key -= 1; //斐波那契数列数列下标减一位
+ } else if ($num > $container[$mid]) {
+ $lower = $mid + 1;
+ $key -= 2; //斐波那契数列数列下标减两位
}
if ($mid <= $count - 1) {
- $result = $mid; break;
+ $result = $mid;
+ break;
} else { //这里$mid大于$count-1说明是补全数值,返回$count-1
- $result = $count - 1; break;
+ $result = $count - 1;
+ break;
}
}
- var_dump( $result );
+ var_dump($result);
}
/**
@@ -62,11 +70,15 @@ public function __construct(array $container,$num)
*/
public function produced($length)
{
- if($length < 2){
+ if ($length < 2) {
return ($length == 0 ? 0 : 1);
}
return $this->produced($length - 1) + $this->produced($length - 2);
}
}
+// +--------------------------------------------------------------------------
+// | 方案测试
+// +--------------------------------------------------------------------------
+
new FibonacciQuery([4, 5, 7, 8, 9, 10, 8], 8);
\ No newline at end of file
diff --git a/package/Query/InsertQuery.php b/src/Query/InsertQuery.php
similarity index 71%
rename from package/Query/InsertQuery.php
rename to src/Query/InsertQuery.php
index f331409..27c0800 100644
--- a/package/Query/InsertQuery.php
+++ b/src/Query/InsertQuery.php
@@ -1,10 +1,10 @@
* @date 2017/8/25
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:对于数组长度比较大,关键字分布又是比较均匀的来说,插值查找的效率比折半查找的效率高
* -------------------------------------------------------------
@@ -12,9 +12,17 @@
* 在英文词典里查找“apple”,你下意识里翻开词典是翻前面的书页还是后面的书页呢?如果再查“zoo”,你又会怎么查?
* 显然你不会从词典中间开始查起,而是有一定目的地往前或往后翻。
*
- * @param $container
- * @param $num
- * @return int
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+/**
+ * insertQuery
+ *
+ * @param array $container
+ * @param $num
+ * @return bool|float|int
*/
function insertQuery(array $container, $num)
{
@@ -46,4 +54,9 @@ function insertQuery(array $container, $num)
return false;
}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
echo insertQuery([4, 5, 7, 8, 9, 10, 8], 8);
+// 6
\ No newline at end of file
diff --git a/src/Query/Kmp.php b/src/Query/Kmp.php
new file mode 100644
index 0000000..09238ae
--- /dev/null
+++ b/src/Query/Kmp.php
@@ -0,0 +1,157 @@
+
+ * @date 2018/1/11
+ * @license MIT
+ * -------------------------------------------------------------
+ * KMP算法是一种改进的字符串匹配算法
+ * KMP精要:KMP在进行朴素匹配时,如果发现不匹配字符时,通过对已经匹配的那部分字符串的最大前缀来快速找到下一个模式串需要匹配的位置。
+ * KMP对模式进行预处理时间复杂度O(m),匹配时间复杂度O(n),总的KMP时间复杂度为O(m+n)。
+ * 参考 字符串匹配的KMP算法 — 阮一峰
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+class KMP
+{
+ public $haystack;
+ public $needle;
+ private $_haystackLen;
+ private $_needleLen;
+ private $_matchTable;
+ private $_isMatch;
+
+ //构造函数
+ function __construct($haystack, $needle)
+ {
+ $this->haystack = $haystack;
+ $this->needle = $needle;
+ //初始化一些参数
+ $this->_haystackLen = $this->getLen($this->haystack);
+ $this->_needleLen = $this->getLen($this->needle);
+ $this->_matchTable = $this->getMatchTable();
+ $this->_isMatch = false;
+ }
+
+
+ //类似strpos函数功能
+ public function strpos()
+ {
+ //haystack
+ $haystackIdx = $matchNum = 0;
+ while ($haystackIdx <= $this->_haystackLen - $this->_needleLen) {
+ //needle
+ $needIdx = 0;
+ for (; $needIdx < $this->_needleLen; $needIdx++) {
+ if (strcmp($this->haystack[$haystackIdx], $this->needle[$needIdx]) <> 0) {
+ if ($matchNum > 0) {
+ $lastMatchValue = $this->getLastMatchValue($needIdx - 1);
+ $haystackIdx += $this->getStep($matchNum, $lastMatchValue);
+ $matchNum = 0;
+ } else {
+ $haystackIdx++;
+ }
+ break;
+ } else {
+ $haystackIdx++;
+ $matchNum++;
+ if ($matchNum == $this->_needleLen) {
+ $this->_isMatch = true;
+ break;
+ }
+ }
+ }
+ if ($this->_isMatch == true) {
+ break;
+ }
+ }
+ return $this->_isMatch ? $haystackIdx - $this->_needleLen : false;
+ }
+
+ //获取字符长度
+ private function getLen($str)
+ {
+ return mb_strlen($str, 'utf-8');
+ }
+
+ //获取部分匹配表
+ private function getMatchTable()
+ {
+ $matchTable = [];
+ for ($i = 0; $i < $this->_needleLen; $i++) {
+ $intersectLen = 0;
+ $nowStr = mb_substr($this->needle, 0, $i + 1, 'utf-8');
+ $preFixArr = $this->getPreFix($nowStr);
+ $sufFixArr = $this->getSufFix($nowStr);
+ if ($preFixArr && $sufFixArr) {
+ $intersectArr = array_intersect($preFixArr, $sufFixArr);
+ if (!empty($intersectArr)) {
+ $intersect = array_pop($intersectArr);
+ $intersectLen = mb_strlen($intersect, 'utf-8');
+ }
+ }
+ $matchTable[$i] = $intersectLen;
+ }
+ return $matchTable;
+ }
+
+ //获取前缀数组
+ private function getPreFix($str)
+ {
+ $outArr = [];
+ $strLen = $this->getLen($str);
+ if ($strLen > 1) {
+ for ($i = 1; $i < $strLen; $i++) {
+ $outArr[] = mb_substr($str, 0, $i, 'utf-8');
+ }
+ }
+ return $outArr;
+ }
+
+ //获取后缀数组
+ private function getSufFix($str)
+ {
+ $outArr = [];
+ $strLen = $this->getLen($str);
+ if ($strLen > 1) {
+ for ($i = 1; $i < $strLen; $i++) {
+ $outArr[] = mb_substr($str, $i, null, 'utf-8');
+ }
+ }
+ return $outArr;
+ }
+
+ //计算步长
+ private function getStep($matchNum, $lastMatchValue)
+ {
+ return $matchNum - $lastMatchValue;
+ }
+
+ //获取最后匹配值
+ private function getLastMatchValue($index)
+ {
+ return isset($this->_matchTable[$index]) ? $this->_matchTable[$index] : 0;
+ }
+
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+$str = 'a b a c a a b a c a b a c a b a a b b';
+$subStr = 'a b a c a b';
+$kmp = new KMP($str, $subStr);
+var_dump($kmp->strpos());
+$kmp->haystack = 'pull requests';
+$kmp->needle = 'sts';
+var_dump($kmp->strpos());
+$kmp->haystack = 'i love you';
+$kmp->needle = 'hate';
+var_dump($kmp->strpos());
\ No newline at end of file
diff --git a/package/Query/QulickQuery.php b/src/Query/QuickQuery.php
similarity index 67%
rename from package/Query/QulickQuery.php
rename to src/Query/QuickQuery.php
index 6c8fb4c..05e3fcf 100644
--- a/package/Query/QulickQuery.php
+++ b/src/Query/QuickQuery.php
@@ -1,15 +1,19 @@
* @date 2017/8/23
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:数组中间的值floor((low+top)/2)
* -------------------------------------------------------------
* 重复第二步操作直至找出目标数字
+ */
+
+/**
+ * QuickQuery
*
* @param $array
* @param $k
@@ -17,7 +21,7 @@
* @param int $high
* @return int
*/
-function QulickQuery($array, $k, $low = 0, $high = 0)
+function QuickQuery($array, $k, $low = 0, $high = 0)
{
//判断是否为第一次调用
if (count($array) != 0 and $high == 0) {
@@ -28,15 +32,15 @@ function QulickQuery($array, $k, $low = 0, $high = 0)
//取$low和$high的中间值
$mid = intval(($low + $high) / 2);
//如果找到则返回
- if ($array[ $mid ] == $k) {
+ if ($array[$mid] == $k) {
return $mid;
- }else if ($k < $array[ $mid ]) {//如果没有找到,则继续查找
- return QulickQuery($array, $k, $low, $mid - 1);
+ } else if ($k < $array[$mid]) {//如果没有找到,则继续查找
+ return QuickQuery($array, $k, $low, $mid - 1);
} else {
- return QulickQuery($array, $k, $mid + 1, $high);
+ return QuickQuery($array, $k, $mid + 1, $high);
}
}
return -1;
}
-echo QulickQuery([4, 5, 7, 8, 9, 10, 8], 8);
\ No newline at end of file
+echo QuickQuery([4, 5, 7, 8, 9, 10, 8], 8);
\ No newline at end of file
diff --git a/package/Sort/BubbleSort.php b/src/Sort/BubbleSort.php
similarity index 67%
rename from package/Sort/BubbleSort.php
rename to src/Sort/BubbleSort.php
index 66c0133..b93a0ca 100644
--- a/package/Sort/BubbleSort.php
+++ b/src/Sort/BubbleSort.php
@@ -1,9 +1,11 @@
* @date 2017/6/16
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:就是像冒泡一样,每次从数组当中 冒一个最大的数出来。
* -------------------------------------------------------------
@@ -12,7 +14,16 @@
* 然后再从底至上地这样升,循环直至十个气泡大小有序。
* 在冒泡排序中,最重要的思想是两两比较,将两者较少的升上去
*
- * @param array $container
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * BubbleSort
+ *
+ * @param array $container
* @return array
*/
function BubbleSort(array $container)
@@ -30,6 +41,10 @@ function BubbleSort(array $container)
return $container;
}
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
var_dump(BubbleSort([4, 21, 41, 2, 53, 1, 213, 31, 21, 423]));
/*
@@ -55,39 +70,4 @@ function BubbleSort(array $container)
[9] =>
int(423)
}
- */
-
-// +----------------------------------------------------------------------
-// | 方法二
-// +----------------------------------------------------------------------
-function BubbleSortV2(array $container)
-{
- $len = count($container);
- // 也可以用foreach
- for ($i = 0; $i < $len; $i++) {
- for ($j = $i + 1; $j < $len; $j++) {
- if ($container[$i] > $container[$j]) {
- list($container[$i], $container[$j]) = array($container[$j], $container[$i]);
- }
- }
- }
-
- return $container;
-}
-
-print_r(BubbleSort([4, 21, 41, 2, 53, 1, 213, 31, 21, 423]));
-/*
-Array
-(
- [0] => 1
- [1] => 2
- [2] => 4
- [3] => 21
- [4] => 21
- [5] => 31
- [6] => 41
- [7] => 53
- [8] => 213
- [9] => 423
-)
- */
+ */
\ No newline at end of file
diff --git a/src/Sort/ChineseTextNumberSort.php b/src/Sort/ChineseTextNumberSort.php
new file mode 100644
index 0000000..e795395
--- /dev/null
+++ b/src/Sort/ChineseTextNumberSort.php
@@ -0,0 +1,219 @@
+ $matchNum) {
+ if ($matchNum === '十') {
+ if ($plane === 0) {
+ $currentNum += 10;
+ continue;
+ }
+ if ($plane === 1) {
+ $index = array_search($structure[0][0], $mapping);
+ $currentNum -= $index;
+ $currentNum += $index * 10;
+ continue;
+ }
+ }
+ $index = array_search($matchNum, $mapping);
+ $currentNum += $index;
+ }
+ return $currentNum;
+ }
+
+ /**
+ * isChinese
+ *
+ * @param $text
+ * @return bool
+ */
+ public function isCompletelyChinese($text)
+ {
+ return boolval(preg_match('/^[\x7f-\xff]+$/', $text));
+ }
+
+ /**
+ * regularModel
+ *
+ * @param $regularModel
+ * @param $text
+ * @return bool
+ */
+ public function regularModel($regularModel, $text)
+ {
+ return boolval(preg_match($regularModel, $text));
+ }
+
+ /**
+ * extractModel
+ *
+ * @param $regularModel
+ * @param $text
+ * @return string
+ * @throws \Exception
+ */
+ public function extractModel($regularModel, $text)
+ {
+ $result = '';
+ if (preg_match($regularModel, $text, $result)) {
+ return trim($result[$this->modelMappingIndex($regularModel)]);
+ }
+ throw new Exception('The matching error');
+ }
+
+ /**
+ * modelMappingIndex
+ *
+ * @param $regularModel
+ * @return int|mixed
+ */
+ protected function modelMappingIndex($regularModel)
+ {
+ return array (
+ static::MODEL_REGULAR_A => 1,
+ static::MODEL_REGULAR_B => 0,
+ static::MODEL_REGULAR_C => 0,
+ static::MODEL_REGULAR_D => 1,
+ static::MODEL_REGULAR_E => 1,
+ static::MODEL_REGULAR_F => 1,
+ static::MODEL_REGULAR_G => 1,
+ static::MODEL_REGULAR_H => 1,
+ static::MODEL_REGULAR_I => 2
+ )[$regularModel] ?? 1;
+ }
+
+ /**
+ * chineseConversionNum
+ *
+ * @param $text
+ * @return mixed
+ */
+ public function chineseConversionNum($text)
+ {
+ if ($this->regularModel(static::CHINESE_DIGITAL_MATCHING, $text)) {
+ $mapping = array ('零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
+ return array_search($text, $mapping);
+ }
+ return ltrim($text, 0);
+ }
+
+ /**
+ * getAllModelRegular
+ *
+ * @return array
+ * @throws \ReflectionException
+ */
+ public function getAllModelRegular()
+ {
+ $constants = (new \ReflectionClass(__CLASS__))->getConstants();
+ $collection = array ();
+ foreach ($constants as $key => $value) {
+ if (strpos($key, 'MODEL_REGULAR_') !== false) {
+ $collection[$key] = $value;
+ }
+ }
+ return $collection;
+ }
+
+ /**
+ * modelAnalysis
+ *
+ * @param $text
+ * @return int|string
+ * @throws \ReflectionException
+ */
+ public function modelAnalysis($text)
+ {
+ foreach ($this->getAllModelRegular() as $item) {
+ if ($this->regularModel($item, $text)) {
+ return $item;
+ }
+ }
+ throw new Exception('Model Analysis of the failure !');
+ }
+
+ /**
+ * textAnalysis
+ *
+ * @param $text
+ * @return int
+ */
+ public function textAnalysis($text)
+ {
+ try {
+ return (int)$this->chineseConversionNum($this->extractModel(
+ $this->modelAnalysis($text),
+ $text
+ )
+ );
+ } catch (Exception $e) {
+ return 0;
+ }
+ }
+
+ /**
+ * chineseTextList
+ *
+ * @param array $list
+ * @return array
+ */
+ public function chineseTextListSorter(array $list)
+ {
+ $container = $generate = array ();
+ foreach ($list as $item) {
+ $container[] = $this->textAnalysis($item);
+ }
+ if (count($container) !== count($list)) {
+ return $list;
+ }
+ uksort($list, function ($left, $right) use ($container) {
+ if ($left == $right) {
+ return 0;
+ }
+ return $container[$left] < $container[$right] ? -1 : 1;
+ });
+ return array_values($list);
+ }
+}
\ No newline at end of file
diff --git a/src/Sort/HeapSort.php b/src/Sort/HeapSort.php
new file mode 100644
index 0000000..acafa03
--- /dev/null
+++ b/src/Sort/HeapSort.php
@@ -0,0 +1,123 @@
+
+ * @date 2017/10/9
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:堆排序利用了大根堆堆顶记录的关键字最大(或最小)这一特征
+ * -------------------------------------------------------------
+ * 堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。
+ * 可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。
+ * 大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,
+ * 因为根据大根堆的要求可知,最大的值一定在堆顶。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+class HeapSort
+{
+ /**
+ * @var int
+ */
+ protected $count;
+
+ /**
+ * @var array
+ */
+ protected $data;
+
+ /**
+ * HeapSort constructor.
+ *
+ * @param array $data
+ */
+ public function __construct(array $data)
+ {
+ $this->count = count($data);
+ $this->data = $data;
+ }
+
+ /**
+ * Action
+ *
+ * @return array
+ */
+ public function run()
+ {
+ $this->createHeap();
+ while ($this->count > 0) {
+ /* 这是一个大顶堆 , 所以堆顶的节点必须是最大的
+ 根据此特点 , 每次都将堆顶数据移到最后一位
+ 然后对剩余数据节点再次建造堆就可以 */
+ $this->swap($this->data[0], $this->data[--$this->count]);
+ $this->buildHeap($this->data, 0, $this->count);
+ }
+ return $this->data;
+ }
+
+ /**
+ * 创建一个堆
+ */
+ public function createHeap()
+ {
+ $i = floor($this->count / 2) + 1;
+ while ($i--) {
+ $this->buildHeap($this->data, $i, $this->count);
+ }
+ }
+
+ /**
+ * 从 数组 的第 $i 个节点开始至 数组长度为0 结束 , 递归的将其 ( 包括其子节点 ) 转化为一个小顶堆
+ *
+ * @param $data
+ * @param $i
+ * @param $count
+ */
+ public function buildHeap(array &$data, $i, $count)
+ {
+ if (false === $i < $count) {
+ return;
+ }
+ // 获取左 / 右节点
+ $right = ($left = 2 * $i + 1) + 1;
+ $max = $i;
+ // 如果左子节点大于当前节点 , 那么记录左节点键名
+ if ($left < $count && $data[$i] < $data[$left]) {
+ $max = $left;
+ }
+ // 如果右节点大于刚刚记录的 $max , 那么再次交换
+ if ($right < $count && $data[$max] < $data[$right]) {
+ $max = $right;
+ }
+ if ($max !== $i && $max < $count) {
+ $this->swap($data[$i], $data[$max]);
+ $this->buildHeap($data, $max, $count);
+ }
+ }
+
+ /**
+ * 交换空间
+ *
+ * @param $left
+ * @param $right
+ */
+ public function swap(&$left, &$right)
+ {
+ list($left, $right) = array ($right, $left);
+ }
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+$array = array (4, 21, 41, 2, 53, 1, 213, 31, 21, 423, 56);
+$result = (new HeapSort($array))->run();
+var_dump($result);
diff --git a/package/Sort/InsertSort.php b/src/Sort/InsertSort.php
similarity index 66%
rename from package/Sort/InsertSort.php
rename to src/Sort/InsertSort.php
index 58b8ff1..e0a3489 100644
--- a/package/Sort/InsertSort.php
+++ b/src/Sort/InsertSort.php
@@ -1,10 +1,10 @@
* @date 2017/6/17
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
* -------------------------------------------------------------
@@ -14,10 +14,19 @@
* 但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。
* 在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
*
- * @param $container
- * @return mixed
*/
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+/**
+ * InsertSort
+ *
+ * @param array $container
+ * @return array
+ */
function InsertSort(array $container)
{
$count = count($container);
@@ -25,15 +34,20 @@ function InsertSort(array $container)
$temp = $container[$i];
$j = $i - 1;
// Init
- while ($container[$j] > $temp){
+ while($j >= 0 && $container[$j] > $temp){
$container[$j+1] = $container[$j];
- $container[$j] = $temp;
$j--;
- if ($j < 0) break;
}
+ if($i != $j+1)
+ $container[$j+1] = $temp;
}
return $container;
}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
var_dump(InsertSort([3, 12, 42, 1, 24, 5, 346, 7]));
/*
@@ -46,4 +60,4 @@ function InsertSort(array $container)
5 => int 24
6 => int 42
7 => int 346
- */
\ No newline at end of file
+ */
diff --git a/package/Sort/MergeSort.php b/src/Sort/MergeSort.php
similarity index 90%
rename from package/Sort/MergeSort.php
rename to src/Sort/MergeSort.php
index 88beb0c..86bf647 100644
--- a/package/Sort/MergeSort.php
+++ b/src/Sort/MergeSort.php
@@ -1,12 +1,14 @@
* @date 2017/7/22
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:
+ * 大O表示: O(n log n)
* -------------------------------------------------------------
* 比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,
* 并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,
@@ -14,6 +16,12 @@
* 归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,
* 最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]
*/
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
class MergeSort
{
/**
@@ -90,6 +98,12 @@ public function mergeArray(&$arr, $left, $center, $right)
}
}
+
+
+// +--------------------------------------------------------------------------
+// | 方案测试
+// +--------------------------------------------------------------------------
+
//do some test:
new mergeSort([4, 7, 6, 3, 9, 5, 8]);
diff --git a/src/Sort/QuickSort.php b/src/Sort/QuickSort.php
new file mode 100644
index 0000000..f2a6688
--- /dev/null
+++ b/src/Sort/QuickSort.php
@@ -0,0 +1,84 @@
+
+ * @date 2017/6/17
+ * @license MIT
+ * -------------------------------------------------------------
+ * 思路分析:从数列中挑出一个元素,称为 “基准”(pivot)
+ * 大O表示: O(n log n) 最糟 O(n 2)
+ * -------------------------------------------------------------
+ * 重新排序数列,所有元素比基准值小的摆放在基准前面,C 语言中的 qsort就是快速排序
+ * 所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
+ * 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序
+ */
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+
+/**
+ * QuickSort
+ *
+ * @param array $container
+ * @return array
+ */
+function QuickSort(array $container)
+{
+ $count = count($container);
+ if ($count <= 1) { // 基线条件为空或者只包含一个元素,只需要原样返回数组
+ return $container;
+ }
+ $pivot = $container[0]; // 基准值 pivot
+ $left = $right = [];
+
+ for ($i = 1; $i < $count; $i++) {
+ if ($container[$i] < $pivot) {
+ $left[] = $container[$i];
+ } else {
+ $right[] = $container[$i];
+ }
+ }
+ $left = QuickSort($left);
+ $right = QuickSort($right);
+ return array_merge($left, [$container[0]], $right);
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试
+// +--------------------------------------------------------------------------
+
+
+var_dump(QuickSort([4, 21, 41, 2, 53, 1, 213, 31, 21, 423]));
+/**
+ * array(10) {
+ * [0] =>
+ * int(1)
+ * [1] =>
+ * int(2)
+ * [2] =>
+ * int(4)
+ * [3] =>
+ * int(21)
+ * [4] =>
+ * int(21)
+ * [5] =>
+ * int(31)
+ * [6] =>
+ * int(41)
+ * [7] =>
+ * int(53)
+ * [8] =>
+ * int(213)
+ * [9] =>
+ * int(423)
+ * }
+ */
+/**
+ * PS & EX:
+ * 快速排序使用分而治之【 divide and conquer,D&C 】的策略,D&C 解决问题的过程包括两个步骤
+ * 1. 找出基线条件,这种条件必须尽可能简单
+ * 2. 不断将问题分解(或者说缩小规模),直到符合基线条件
+ * (D&C 并非解决问题的算法,而是一种解决问题的思路)
+ */
\ No newline at end of file
diff --git a/package/Sort/SelectSort.php b/src/Sort/SelectSort.php
similarity index 73%
rename from package/Sort/SelectSort.php
rename to src/Sort/SelectSort.php
index 0c8fedf..832861c 100644
--- a/package/Sort/SelectSort.php
+++ b/src/Sort/SelectSort.php
@@ -1,18 +1,28 @@
* @date 2017/6/17
- * @license Mozilla
+ * @license MIT
* -------------------------------------------------------------
* 思路分析:选择排序是不稳定的排序方法
+ * 大O表示: O(n 2)
* -------------------------------------------------------------
* 它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
* 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式
+// +--------------------------------------------------------------------------
+/**
+ * SelectSort
*
- * @param $container
- * @return mixed
+ * @param array $container
+ * @return array
*/
function SelectSort(array $container)
{
@@ -33,6 +43,11 @@ function SelectSort(array $container)
return $container;
}
+// +--------------------------------------------------------------------------
+// | 方案测试
+// +--------------------------------------------------------------------------
+
+
var_dump(SelectSort([3, 12, 42, 1, 24, 5, 346, 7]));
/*
diff --git a/package/Sort/ShellSort.php b/src/Sort/ShellSort.php
similarity index 55%
rename from package/Sort/ShellSort.php
rename to src/Sort/ShellSort.php
index 809c8cd..7b7aad5 100644
--- a/package/Sort/ShellSort.php
+++ b/src/Sort/ShellSort.php
@@ -1,6 +1,7 @@
* @date 2017/7/22
* @license Mozilla
@@ -9,18 +10,28 @@
* -------------------------------------------------------------
* 希尔排序中一个常数因子n,原数组被分成各个小组,每个小组由h个元素组成,很可能会有多余的元素。
* 当然每次循环的时候,h也是递减的(h=h/n)。第一次循环就是从下标为h开始。希尔排序的一个思想就是,分成小组去排序。
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+/**
+ * ShellSort
*
* @param array $container
* @return array
*/
-function ShellSort( array $container )
+function ShellSort(array $container)
{
$count = count($container);
- for ( $increment = intval($count / 2); $increment > 0; $increment = intval($increment / 2) ) {
- for ( $i = $increment; $i < $count; $i++ ) {
+ for ($increment = intval($count / 2); $increment > 0; $increment = intval($increment / 2)) {
+ for ($i = $increment; $i < $count; $i++) {
$temp = $container[$i];
- for ( $j = $i; $j >= $increment; $j -= $increment ) {
- if ( $temp < $container[$j - $increment] ) {
+ for ($j = $i; $j >= $increment; $j -= $increment) {
+ if ($temp < $container[$j - $increment]) {
$container[$j] = $container[$j - $increment];
} else {
break;
@@ -32,5 +43,12 @@ function ShellSort( array $container )
return $container;
}
-var_dump( ShellSort([6,13,21,99,18,2,25,33,19,84]));
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+var_dump(ShellSort([6, 13, 21, 99, 18, 2, 25, 33, 19, 84]));
+
diff --git a/src/Sort/ShuttleSort.php b/src/Sort/ShuttleSort.php
new file mode 100644
index 0000000..3afdf47
--- /dev/null
+++ b/src/Sort/ShuttleSort.php
@@ -0,0 +1,78 @@
+
+ * @date 2017/12/19
+ * @version 1.0
+ * -------------------------------------------------------------
+ * 思路分析:飞梭排序是冒泡排序的轻微变形。不同的地方在于,飞梭排序是从低到高然后从高到低来回排序,而冒泡排序则仅从低到高去比较序列里的每个元素。
+ * -------------------------------------------------------------
+ * 先对数组从左到右进行冒泡排序(升序),则最大的元素去到最右端
+ * 再对数组从右到左进行冒泡排序(降序),则最小的元素去到最左端
+ * 以此类推,依次改变冒泡的方向,并不断缩小未排序元素的范围,直到最后一个元素结束
+ */
+
+
+// +--------------------------------------------------------------------------
+// | 解题方式 | 这儿,可能有用的解决方案
+// +--------------------------------------------------------------------------
+
+
+/**
+ * ShuttleSort
+ *
+ * @param array $data
+ * @return array
+ */
+function ShuttleSort(array $data)
+{
+ /**
+ * 替换方法
+ *
+ * @param array $data
+ * @param $i
+ * @param $j
+ * @return array
+ */
+ $swap = function (array &$data, $i, $j) {
+ $temp = $data[$i];
+ $data[$i] = $data[$j];
+ $data[$j] = $temp;
+ return $data;
+ };
+
+ $count = count($data);
+ $left = 0;
+ $right = $count - 1;
+
+ while ($left < $right) {
+ // 从左到右
+ $lastRight = 0;
+ for ($i = $left; $i < $right; $i++) {
+ if ($data[$i] > $data[$i + 1]) {
+ $swap($data, $i, 1 + $i);
+ $lastRight = $i;
+ }
+ }
+ $right = $lastRight;
+ // 从右到左
+ $lastLeft = 0;
+ for ($j = $right; $left < $j; $j--) {
+ if ($data[$j - 1] > $data[$j]) {
+ $swap($data, $j - 1, $j);
+ $lastLeft = $j;
+ }
+ }
+ $left = $lastLeft;
+ }
+ return $data;
+}
+
+// +--------------------------------------------------------------------------
+// | 方案测试 | php `this.php` || PHPStorm -> 右键 -> Run `this.php`
+// +--------------------------------------------------------------------------
+
+
+var_dump(ShuttleSort([6, 13, 21, 99, 18, 2, 25, 33, 19, 84]));
diff --git a/src/Structure/BinarySearchTree.php b/src/Structure/BinarySearchTree.php
new file mode 100644
index 0000000..cc3fea2
--- /dev/null
+++ b/src/Structure/BinarySearchTree.php
@@ -0,0 +1,129 @@
+value = $data;
+ $node->left = null;
+ $node->right = null;
+ return $node;
+ }
+
+
+ /**
+ * 插入节点
+ * @param $node 根节点
+ * @param $value 关键值
+ */
+ public function insert(&$node, $value)
+ {
+ if(empty($value) && $value !== 0) {
+ return ;
+ }
+
+ if ($node == null) {
+ $node = $this->createNode($value);
+ } else if ($value < $node->value) {
+ $this->insert($node->left, $value);
+ } else {
+ $this->insert($node->right, $value);
+ }
+ }
+
+ /**
+ * 先序遍历
+ * @param $node 根节点
+ */
+ public function preOrder(&$node)
+ {
+ if ($node != null) {
+ echo $node->value . PHP_EOL ;
+ $this->preOrder($node->left);
+ $this->preOrder($node->right);
+ }
+
+ }
+ /**
+ * 中序遍历
+ * @param $node 根节点
+ */
+ public function middleOrder(&$node)
+ {
+ if ($node != null) {
+ $this->middleOrder($node->left);
+ echo $node->value . PHP_EOL ;
+ $this->middleOrder($node->right);
+ }
+
+ }
+
+ /**
+ * 后序遍历
+ * @param $node 根节点
+ */
+ public function afterOrder(&$node)
+ {
+ if ($node != null) {
+ $this->afterOrder($node->left);
+ $this->afterOrder($node->right);
+ echo $node->value . PHP_EOL;
+ }
+ }
+
+ /**
+ * 获取最大值
+ * @param $node 根节点
+ */
+ public function findMax(&$node)
+ {
+ while($node->right != null) {
+ $node = $node->right;
+ }
+ return $node->value;
+ }
+
+}
+
+$tree = new BinarySearchTree();
+$tree->insert($tree->root, 3);
+$tree->insert($tree->root, 9);
+$tree->insert($tree->root, 2);
+$tree->insert($tree->root, 20);
+
+echo "先序遍历".PHP_EOL;
+$tree->preOrder($tree->root); //324
+echo "中序遍历" . PHP_EOL;
+
+$tree->middleOrder($tree->root); //324
+echo "后序遍历" . PHP_EOL;
+
+$tree->afterOrder($tree->root); //234
+
+$max = $tree->findMax($tree->root);
+
+var_dump($max);
\ No newline at end of file
diff --git a/src/Structure/KitchenQueue.php b/src/Structure/KitchenQueue.php
new file mode 100644
index 0000000..80e87fd
--- /dev/null
+++ b/src/Structure/KitchenQueue.php
@@ -0,0 +1,53 @@
+
+ * @date 2017/12/3
+ * @version 1.0
+ * @license MIT
+ */
+
+class KitchenQueue
+{
+ /**
+ * @var \stdClass $cooking
+ */
+ protected $cooking;
+
+ /**
+ * 服务员
+ *
+ * @param $dishes
+ */
+ public function waiter($dishes)
+ {
+ $node = new \stdClass();
+ $node->element = $dishes;
+ $node->next = $this->cooking;
+ $this->cooking = $node;
+ }
+
+ /**
+ * 厨师
+ *
+ * @return \stdClass
+ */
+ public function kitchen()
+ {
+ return $this->cooking;
+ }
+}
+
+$kitchen = new KitchenQueue();
+$kitchen->waiter("Qin Jiao Rou Si");
+$kitchen->waiter("Ma Po Dou Fu");
+$kitchen->waiter("Fu Qi Fei Pian");
+$kitchen->waiter("Kou Shui Ji");
+var_dump($kitchen->kichen());
diff --git a/src/Structure/LinearChain.php b/src/Structure/LinearChain.php
new file mode 100644
index 0000000..ef6b237
--- /dev/null
+++ b/src/Structure/LinearChain.php
@@ -0,0 +1,403 @@
+
+ * @date 2017/9/29
+ * @license MIT
+ * -------------------------------------------------------------
+ * [基本说明]
+ * =======
+ * 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的
+ * 注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储)
+ * 但是把最后一个数据元素的尾指针指向了首位结点)。
+ * [基本特点]
+ * =======
+ * - 存在一个唯一的被称为`第一个`的数据元素
+ * - 存在一个唯一的被称为`最后一个`的数据元素
+ * - 除第一个元素外,每个元素均有唯一一个直接前驱
+ * - 除最后一个元素外,每个元素均有唯一一个直接后继
+ * -------------------------------------------------------------
+ * [定义]
+ * =======
+ * 线性表(Linear List) :是由n(n≧0)个数据元素(结点) [a1,a2, …an] 组成的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。
+ * 该序列中的所有结点具有相同的数据类型。其中数据元素的个数n称为线性表的长度。
+ * 当n=0时,称为空表。
+ * 当n>0时,将非空的线性表记作: (a1,a2,…an) a1称为线性表的第一个(首)结点,an称为线性表的最后一个(尾)结点。
+ * -------------------------------------------------------------
+ * [线性表单链存储]
+ * =======
+ * 用一组任意的存储单元存储线性表中的数据元素,用这种方法存储的线性表简称线性链表。
+ * -------------------------------------------------------------
+ * [单链存储的线性表的特点]
+ * =======
+ * - 存储链表中结点的一组任意的存储单元可以是连续的,也可以是不连续的,甚至是零散分布在内存中的任意位置上
+ * - 链表中结点的逻辑顺序和物理顺序不一定相同
+ * -------------------------------------------------------------
+ */
+class LinearChain
+{
+ /**
+ * @var string 下一结点指针
+ */
+ public $next;
+
+ /**
+ * @var string 头结点数据
+ */
+ public $elem;
+
+ /**
+ * @var int 链表长度
+ */
+ public $length;
+
+ /**
+ * LinearChain constructor. 线性表初始化
+ */
+ public function __construct()
+ {
+ $this->next = $this->elem = $this->length = null;
+ }
+
+ /**
+ * 清空单链表
+ *
+ * @return mixed
+ */
+ public function clearChain()
+ {
+ if ($this->length <= 0) {
+ return false;
+ }
+ while ($this->next != null) {
+ $q = $this->next->next;
+ $this->next = null;
+ unset($this->next);
+ $this->next = $q;
+ }
+ $this->length = 0;
+ }
+
+ /**
+ * 返回单链表长度
+ *
+ * @return mixed
+ */
+ public function getLength()
+ {
+ return $this->length;
+ }
+
+ /**
+ * 判断单链表是否为空
+ *
+ * @return bool 为空返回true,不为空返回false
+ */
+ public function getIsEmpty()
+ {
+ return $this->length == 0 && $this->next == null;
+ }
+
+ /**
+ * 头插入法建表
+ *
+ * @param array $arr 建立单链表的数据
+ * @return mixed
+ */
+ protected function getHeadCreateChain(array $arr)
+ {
+ $this->clearChain();
+ $iterator = $this->generator($arr);
+ $iterator->rewind();
+ while ($iterator->valid()) {
+ $node = new stdClass();
+ $node->elem = $iterator->current();
+ $node->next = $this->next;
+ $this->next = $node;
+ $this->length++;
+ $iterator->next();
+ }
+ return $this->next;
+ }
+
+ /**
+ * 尾插入法建表
+ *
+ * @param array $arr 建立单链表的数据
+ * @return mixed
+ */
+ protected function getTailCreateChain(array $arr)
+ {
+ $this->clearChain();
+ $self = $this;
+ $iterator = $this->generator($arr);
+ $iterator->rewind();
+ while ($iterator->valid()) {
+ $node = new stdClass();
+ $node->elem = $iterator->current();
+ $node->next = $self->next;
+ $self->next = $node;
+ $self = $node;
+ $iterator->next();
+ $this->length++;
+ }
+ return $this->next;
+ }
+
+ /**
+ * 返回第$i个元素
+ *
+ * @param int $i 元素位序,从1开始
+ * @return mixed
+ */
+ protected function getElemForPos($i)
+ {
+ $i = (int)$i;
+ if ($i > $this->length || $i < 1) {
+ return null;
+ }
+ $mark = 1;
+ $self = $this->next;
+ while ($mark < $i) {
+ $box = $self->next;
+ $self = $box;
+ $mark++;
+ }
+ return $self;
+ }
+
+ /**
+ * 查找单链表中是否存在某个值的元素
+ * 如果有返回该元素结点,否则返回null
+ *
+ * @param mixed $value 查找的值
+ * @return mixed
+ */
+ protected function getElemIsExist($value)
+ {
+ $self = $this;
+ while ($self->next != null && strcmp($self->elem, $value) !== 0) {
+ $self = $self->next;
+ }
+ if (strcmp($self->elem, $value) === 0) {
+ return $self;
+ }
+ return null;
+ }
+
+ /**
+ * 查找单链表中是否存在某个值的元素
+ * 如果有返回该元素位序,否则返回-1
+ *
+ * @param mixed $value 查找的值
+ * @return mixed
+ */
+ protected function getElemPosition($value)
+ {
+ $self = $this;
+ $mark = 0;
+ while ($self->next != null && strcmp($self->elem, $value) !== 0) {
+ $self = $self->next;
+ $mark++;
+ }
+ if (strcmp($self->elem, $value) === 0) {
+ return $mark;
+ }
+ return -1;
+ }
+
+ /**
+ * 单链表的插入操作
+ *
+ * @param int $key 插入元素的位序,即在什么位置插入新的元素,从1开始
+ * @param mixed $value 插入的新的元素值
+ * @return boolean 插入成功返回true,失败返回false
+ */
+ protected function getInsertElem($key, $value)
+ {
+ if ($key > $this->length || $key < 1) {
+ return false;
+ }
+ $mark = 1;
+ $self = $this;
+ while ($self->next != null && $mark < $key) {
+ $self = $self->next;
+ $mark++;
+ }
+ $node = new stdClass();
+ $node->elem = $value;
+ $node->next = $self->next;
+ $self->next = $node;
+ $this->length++;
+ return true;
+ }
+
+ /**
+ * 遍历单链表中的所有元素
+ *
+ * @return array 包括单链中的所有元素
+ */
+ protected function getAllElem()
+ {
+ $result = array ();
+ if ($this->getIsEmpty()) {
+ return $result;
+ }
+ $self = $this->next;
+ while ($self->next != null) {
+ array_push($result, $self->elem);
+ $self = $self->next;
+ }
+ array_push($result, $self->elem);
+ return $result;
+ }
+
+ /**
+ * 根据Key 删除单链中的元素
+ *
+ * @param int $key 元素位序
+ * @return boolean 删除成功返回true,失败返回false
+ */
+ protected function getDeleteElem($key)
+ {
+ $key = (int)$key;
+ if ($key > $this->length || $key < 1) {
+ return false;
+ }
+ $self = $this;
+ $mark = 1;
+ while ($mark < $key) {
+ $self = $self->next;
+ $mark++;
+ }
+ $node = $self->next;
+ $self->next = $node->next;
+ $this->length--;
+ return true;
+ }
+
+ /**
+ * 删除单链表中值为$value的前 $i($i>=1) 个结点
+ *
+ * @param mixed mixed 待查找的值
+ * @param $i mixed 删除的次数,即删除查找到的前$i个
+ * @return mixed
+ */
+ protected function getDeleteElemForValue($value, $i = 1)
+ {
+ if ($i > 1) {
+ $this->getDeleteElemForValue($value, $i - 1);
+ }
+ $vp = $this->getElemPosition($value);
+ $this->getDeleteElem($vp);
+ return $this->getAllElem();
+ }
+
+ /**
+ * 删除单链表所有重复的值
+ *
+ * @return mixed
+ */
+ protected function getElemUnique()
+ {
+ if ($this->getIsEmpty()) {
+ return $this->getAllElem();
+ }
+ $self = $this;
+ while ($self->next != null) {
+ $node = $self->next;
+ $ptr = $self;
+ while ($node->next != null) {
+ if (strcmp($self->elem, $node->elem) === 0) {
+ $ptr->next = $node->next;
+ unset($node->next);
+ $node = $ptr->next;
+ $this->length--;
+ } else {
+ $ptr = $node;
+ $node = $node->next;
+ }
+ }
+ $self = $self->next;
+ }
+ return $this->getAllElem();
+ }
+
+ /**
+ * 迭代器生产
+ *
+ * @param array $info
+ * @return \ArrayIterator
+ */
+ protected function generator(array $info)
+ {
+ return (new ArrayObject($info))->getIterator();
+ }
+
+ /**
+ * 调试用请无视
+ *
+ * @param $name
+ * @param $arguments
+ * @return mixed
+ */
+ public function __call($name, $arguments)
+ {
+ $this->preDispatch(); // 调试用,请无视
+ return call_user_func_array(array ($this, $name), $arguments);
+ }
+
+ /**
+ * 调试用请无视!
+ *
+ * @param bool $isDebug
+ * @return bool
+ */
+ protected function preDispatch($isDebug = true)
+ {
+ if (!$isDebug) {
+ return false;
+ }
+ $debug = debug_backtrace()[1];
+ $reflection = new ReflectionMethod($this, $debug['args'][0]);
+ $args = '';
+ if (isset($debug['args'][1])) {
+ foreach ($debug['args'][1] as &$value) {
+ if (is_array($value)) {
+ $args .= json_encode($debug['args'][1]) . ', ';
+ } else {
+ $args .= $value . ', ';
+ }
+ }
+ }
+ $args = trim($args, ', ');
+ echo "\t" . $reflection->getDocComment() . PHP_EOL;
+ echo "\t{$debug['args'][0]}({$args})\n" . PHP_EOL;
+ }
+}
+
+$echo = function ($str, $action) {
+ echo $str . "\t->\t" . var_export($action, true) . PHP_EOL;
+ echo "--------------------------- " . PHP_EOL;
+};
+$personal = array (
+ "One",
+ "Two",
+ "Three",
+ "Four",
+ "Five",
+);
+
+$oll = new LinearChain();
+$echo('头插入链表数据', $oll->getHeadCreateChain($personal));
+$echo('尾插入链表数据', $oll->getTailCreateChain($personal));
+$echo('返回第二个数据', $oll->getElemForPos(2));
+$echo('是否存在Tow呢?', $oll->getElemIsExist("Two"));
+$echo('One 的下标示是', $oll->getElemPosition("One"));
+$echo('从2号位插入一个Four', $oll->getInsertElem(2, "Four"));
+$echo('遍历整个单链表', $oll->getAllElem());
+$echo('删除第一个元素', $oll->getDeleteElem(1));
+$echo('删除Three 前一个', $oll->getDeleteElemForValue("Three", 1));
+$echo('去重链表中重复值', $oll->getElemUnique());
\ No newline at end of file
diff --git a/src/Structure/LinearOrder.php b/src/Structure/LinearOrder.php
new file mode 100644
index 0000000..926f749
--- /dev/null
+++ b/src/Structure/LinearOrder.php
@@ -0,0 +1,376 @@
+
+ * @date 2017/9/29
+ * @license MIT
+ * -------------------------------------------------------------
+ * [基本说明]
+ * =======
+ * 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的
+ * 注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储)
+ * 但是把最后一个数据元素的尾指针指向了首位结点)。
+ * [基本特点]
+ * =======
+ * - 存在一个唯一的被称为`第一个`的数据元素
+ * - 存在一个唯一的被称为`最后一个`的数据元素
+ * - 除第一个元素外,每个元素均有唯一一个直接前驱
+ * - 除最后一个元素外,每个元素均有唯一一个直接后继
+ * -------------------------------------------------------------
+ * [定义]
+ * =======
+ * 线性表(Linear List) :是由n(n≧0)个数据元素(结点) [a1,a2, …an] 组成的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。
+ * 该序列中的所有结点具有相同的数据类型。其中数据元素的个数n称为线性表的长度。
+ * 当n=0时,称为空表。
+ * 当n>0时,将非空的线性表记作: (a1,a2,…an) a1称为线性表的第一个(首)结点,an称为线性表的最后一个(尾)结点。
+ * -------------------------------------------------------------
+ * [线性表顺序存储]
+ * =======
+ * 把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里,用这种方法存储的线性表简称线性表。
+ * -------------------------------------------------------------
+ * [顺序存储的线性表的特点]
+ * =======
+ * - 线性表的逻辑顺序与物理顺序一致;
+ * - 数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。
+ * -------------------------------------------------------------
+ * @param array
+ */
+class LinearOrder extends ArrayObject
+{
+ const PRECURSOR_KEY = 0;
+ const PRECURSOR_VALUE = 1;
+
+ const SUBSEQUENT_KEY = 0;
+ const SUBSEQUENT_VALUE = 1;
+
+ const ASSIGN_KEY = 0;
+ const DEFAULT_KEY = 1;
+
+ const DELETE_KEY = 0;
+ const DELETE_VALUE = 1;
+
+ /**
+ * @var array|mixed 线性表
+ */
+ public $oll;
+
+ /**
+ * LinearList constructor. 线性表初始化
+ *
+ * @param array $oll
+ */
+ public function __construct($oll = array ())
+ {
+ echo '---------------------------'.PHP_EOL;
+ echo var_export($oll).PHP_EOL;
+ echo '---------------------------'.PHP_EOL;
+ parent::__construct($oll);
+ $this->oll = $this->getIterator();
+ }
+
+ /**
+ * @return void 清空线性表
+ */
+ public function __destruct()
+ {
+ unset($this->oll);
+ }
+
+ /**
+ * 调试用请无视
+ *
+ * @param $name
+ * @param $arguments
+ * @return mixed
+ */
+ public function __call($name, $arguments)
+ {
+ $this->preDispatch(); // 调试用,请无视
+ return call_user_func_array(array($this, $name), $arguments);
+ }
+
+ /**
+ * 判断线性表是否为空
+ *
+ * @return boolean 为空返回true,否则返回false
+ */
+ protected function isEmpty()
+ {
+ return $this->getLength() > 0 ? false : true;
+ }
+
+ /**
+ * 返回线性表的长度
+ *
+ * @return int
+ */
+ protected function getLength()
+ {
+ return $this->oll->count();
+ }
+
+ /**
+ * 返回线性表中下标为$key的元素
+ *
+ * @param mixed $key 线性表元素的下标
+ * @return mixed
+ */
+ protected function getElement($key)
+ {
+ return $this->oll->offsetGet($key);
+ }
+
+ /**
+ * 返回线性表中某个元素的位置
+ *
+ * @param mixed $value 线性表中某个元素的值
+ * @return int 从1开始,如果返回-1表示不存在该元素
+ */
+ protected function getElementPosition($value)
+ {
+ $i = 0;
+ $this->oll->rewind();
+ while ($this->oll->valid()) {
+ $i++;
+ if (strcmp($value, $this->oll->current()) === 0) {
+ return $i;
+ }
+ $this->oll-> next();
+ }
+ return -1;
+ }
+
+ /**
+ * 返回线性表中某个元素的直接前驱元素
+ *
+ * @param string $value 线性表中某个元素的值
+ * @param int $tag 如果$value为下标则为1, 如果$value为元素值则为0
+ * @return array|bool array('value'=>...)直接前驱元素值,array('key'=>...)直接前驱元素下标
+ */
+ protected function getElementPrecursor($value, $tag = self::PRECURSOR_VALUE)
+ {
+ $i = 0;
+ $prev = null;
+ $this->oll->rewind();
+ while ($this->oll->valid()) {
+ $key = $this->oll->key();
+ $current = $this->oll->current();
+ if (strcmp($key, $value) === 0) {
+ if ($i == 1) {
+ return false;
+ }
+ return array ('value' => $this->getElement($prev), 'key' => $prev);
+ }
+ if ($tag == self::PRECURSOR_VALUE) {
+ if (strcmp($current, $value) === 0) {
+ if ($i == 1) {
+ return false;
+ }
+ return array ('value' => $this->getElement($prev), 'key' => $prev);
+ }
+ }
+ $i++;
+ $prev = $this->oll->key();
+ $this->oll->next();
+ }
+ }
+
+ /**
+ * 返回某个元素的直接后继元素
+ *
+ * @param string $value $value线性表中某个元素的值
+ * @param int $tag 如果$value为下标则为1,如果$value为元素值则为0
+ * @return array|bool array('value'=>...)直接后继元素值,array('key'=>...)直接后继元素下标
+ */
+ protected function getElementSubsequent($value, $tag = self::SUBSEQUENT_KEY)
+ {
+ $i = 0;
+ $len = $this->getLength();
+ $this->oll->rewind();
+ while ($this->oll->valid()) {
+ $key = $this->oll->key();
+ $current = $this->oll->current();
+ if ($tag == self::SUBSEQUENT_KEY) {
+ if (strcmp($key, $value) == 0) {
+ if ($i == $len) {
+ return false;
+ }
+ $this->oll->next();
+ return array ('value' => $this->oll->current(), 'key' => $this->oll->key());
+ }
+ }
+ if ($tag == self::SUBSEQUENT_VALUE) {
+ if (strcmp($current, $value) == 0) {
+ if ($i == $len) {
+ return false;
+ }
+ $this->oll->next();
+ return array ('value' => $this->oll->current(), 'key' => $this->oll->key());
+ }
+ }
+ $i++;
+ $this->oll->next();
+ }
+ return false;
+ }
+
+ /**
+ * 在指定位置插入一个新的结点
+ *
+ * @param string $p 新结点插入位置,从0开始
+ * @param string $value 线性表新结点的值
+ * @param null $key 线性表新结点的下标
+ * @param int $tag 是否指定新结点的下标,1表示默认下标,0表示指定下标
+ * @return bool 插入成功返回true,失败返回false
+ */
+ protected function getInsertElement($p, $value, $key = null, $tag = self::DEFAULT_KEY)
+ {
+ $p = (int)$p;
+ $i = 0;
+ if ($p > $this->getLength() || $p < 1) {
+ return false;
+ }
+ $this->oll->rewind();
+ while ($this->oll->valid()) {
+ if ($i != $p) {
+ $i++;
+ $this->oll->next();
+ }
+ switch ($tag){
+ case self::DEFAULT_KEY:
+ $this->oll->append($value);
+ break 2;
+ case self::ASSIGN_KEY:
+ $this->oll->offsetSet($key, $value);
+ break 2;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 根据元素位置返回线性表中的某个元素
+ *
+ * @param mixed $position 元素位置从1开始
+ * @return array|bool array('value'=>...)元素值,array('key'=>...)元素下标
+ */
+ protected function getElemForPos($position)
+ {
+ $i = 0;
+ $len = $this->getLength();
+ $position = (int)$position;
+ if ($position > $len || $position < 1) {
+ return false;
+ }
+ $this->oll->rewind();
+ while ($this->oll->valid()) {
+ if ($i == $position) {
+ return array ('value' => $this->oll->current(), 'key' => $this->oll->key());
+ }
+ $i++;
+ $this->oll->next();
+ }
+ }
+
+ /**
+ * 根据下标或者元素值删除线性表中的某个元素
+ *
+ * @param mixed $value 元素下标或者值
+ * @param int $tag 0表示$value为下标,1表示$value为元素值
+ * @return bool 成功返回true,失败返回false
+ */
+ protected function getDeleteElement($value, $tag = self::DELETE_KEY)
+ {
+ $this->oll->rewind();
+ while ($this->oll->valid())
+ {
+ $key = $this->oll->key();
+ $current = $this->oll->current();
+ if ($tag == self::DELETE_KEY) {
+ if (strcmp($key, $value) === 0) {
+ $this->oll->offsetUnset($key);
+ }
+ }
+ if ($tag == self::DELETE_VALUE) {
+ if (strcmp($current, $value) === 0) {
+ $this->oll->offsetUnset($key);
+ }
+ }
+ $this->oll->next();
+ }
+ return true;
+ }
+
+ /**
+ * 根据元素位置删除线性表中的某个元素
+ *
+ * @param int $position 元素位置从1开始
+ * @return bool 成功返回true,失败返回false
+ */
+ protected function getDeleteEleForPos($position)
+ {
+ $len = $this->getLength();
+ $i = 0;
+ $position = (int)$position;
+ if ($position > $len || $position < 1) {
+ return false;
+ }
+ $this->oll->rewind();
+ while ($this->oll->valid()) {
+ $key = $this->oll->key();
+ if ($i == $position) {
+ $this->oll->offsetUnset($key);
+ }
+ $i++;
+ $this->oll->next();
+ }
+ return true;
+ }
+
+ /**
+ * 调试用
+ *
+ * @param bool $isDebug
+ * @return bool
+ */
+ protected function preDispatch($isDebug = true)
+ {
+ if (!$isDebug) {
+ return false;
+ }
+ $debug = debug_backtrace()[1];
+ $reflection = new ReflectionMethod($this, $debug['args'][0]);
+ $args = '';
+ if(isset($debug['args'][1])){
+ foreach ($debug['args'][1] as &$value){
+ if( is_array($value )){
+ $args .= json_encode($debug['args'][1]).', ';
+ }else{
+ $args .= $value.', ';
+ }
+ }
+ }
+ $args = trim($args,', ');
+ echo "\t".$reflection->getDocComment() . PHP_EOL;
+ echo "\t{$debug['args'][0]}({$args})\n" . PHP_EOL;
+ }
+}
+
+$echo = function ($str, $action) {
+ echo $str . "\t->\t" . var_export($action, true) . PHP_EOL;
+ echo "--------------------------- " . PHP_EOL;
+};
+
+$oll = new LinearOrder(array ('name' => 'Jack', 10, "age", 'msg' => 10, 666));
+$echo('判断线性表是否为空', $oll->isEmpty());
+$echo('返回线性表的长度', $oll->getLength());
+$echo('根据下标返回线性表中的某个元素', $oll->getElement(1));
+$echo('返回线性表中某个元素的位置', $oll->getElementPosition(666));
+$echo('返回线性表中某个元素的直接前驱元素', $oll->getElementPrecursor(666, LinearOrder::PRECURSOR_VALUE));
+$echo('返回线性表中某个元素的直接后继元素', $oll->getElementSubsequent(0, LinearOrder::SUBSEQUENT_KEY));
+$echo('根据元素位置返回线性表中的某个元素', $oll->getElemForPos(2));
+$echo('根据下标或者元素值删除线性表中的某个元素', $oll->getDeleteElement('name', LinearOrder::DELETE_KEY));
+$echo('在指定位置插入一个新的结点', $oll->getInsertElement(3, "插入新节点", "qzone", LinearOrder::ASSIGN_KEY));
+$echo('$oll->oll的内容 ', $oll->oll);
\ No newline at end of file
diff --git a/src/Structure/StackExample.php b/src/Structure/StackExample.php
new file mode 100644
index 0000000..a8b4f30
--- /dev/null
+++ b/src/Structure/StackExample.php
@@ -0,0 +1,224 @@
+
+ * @date 2017/10/16
+ * @license MIT
+ * -------------------------------------------------------------
+ * [栈的定义]
+ * =======
+ * 栈(Stack):是限制在表的一端进行插入和删除操作的线性表。又称为后进先出LIFO (Last In First Out)或先进后出FILO (First In Last Out)线性表。
+ * 栈顶(Top):允许进行插入、删除操作的一端,又称为表尾。用栈顶指针(top)来指示栈顶元素。
+ * 栈底(Bottom):是固定端,又称为表头。
+ * 空栈:当表中没有元素时称为空栈。
+ * [栈的实现方式]
+ * =======
+ * - 硬堆栈:利用CPU中的某些寄存器组或类似的硬件或使用内存的特殊区域来实现。这类堆栈容量有限,但速度很快;
+ * - 软堆栈:这类堆栈主要在内存中实现。堆栈容量可以达到很大。在实现方式上,又有动态方式和静态方式两种
+ * -------------------------------------------------------------
+ * [定义]
+ * =======
+ * 线性表(Linear List) :是由n(n≧0)个数据元素(结点) [a1,a2, …an] 组成的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。
+ * 该序列中的所有结点具有相同的数据类型。其中数据元素的个数n称为线性表的长度。
+ * 当n=0时,称为空表。
+ * 当n>0时,将非空的线性表记作: (a1,a2,…an) a1称为线性表的第一个(首)结点,an称为线性表的最后一个(尾)结点。
+ * -------------------------------------------------------------
+ * [线性表顺序存储]
+ * =======
+ * 把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里,用这种方法存储的线性表简称线性表。
+ * -------------------------------------------------------------
+ * [顺序存储的线性表的特点]
+ * =======
+ * - 线性表的逻辑顺序与物理顺序一致;
+ * - 数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。
+ * -------------------------------------------------------------
+ * @param array
+ */
+class StackExample
+{
+ /**
+ * @var null 栈元素
+ */
+ protected $elem;
+ /**
+ * @var null 下一个节点
+ */
+ protected $next;
+ /**
+ * @var int 栈长度
+ */
+ protected $length;
+
+ /**
+ * 初始化栈
+ * StackExample constructor.
+ */
+ public function __construct()
+ {
+ $this->elem = $this->next = null;
+ $this->length = 0;
+ }
+
+ /**
+ * 判断栈是否空栈
+ *
+ * @return boolean 如果为空栈返回true,否则返回false
+ */
+ protected function getIsEmpty()
+ {
+ return $this->elem ? false : true;
+ }
+
+ /**
+ * 将所有元素出栈
+ *
+ * @return array 返回所有栈内元素
+ */
+ protected function getAllPopStack()
+ {
+ $result = array ();
+ if ($this->getIsEmpty()) {
+ return $result;
+ }
+ while ($this->elem != null) {
+ $result[] = $this->elem->elem;
+ $this->elem = $this->elem->next;
+ }
+ $this->length = 0;
+ return $result;
+ }
+
+ /**
+ * 返回栈内元素个数
+ *
+ * @return int
+ */
+ protected function getLength()
+ {
+ return $this->length;
+ }
+
+ /**
+ * 元素进栈
+ *
+ * @param mixed $element 进栈元素值
+ * @return void
+ **/
+ protected function setPushStack($element)
+ {
+ $stack = new stdClass();
+ $stack->elem = $element;
+ $stack->next = $this->elem;
+ $this->elem = &$stack;
+ $this->length++;
+ }
+
+ /**
+ * 元素出栈
+ *
+ * @return boolean 出栈成功返回true,否则返回false
+ **/
+ protected function getPopStack()
+ {
+ if ($this->getIsEmpty()) {
+ return false;
+ }
+ $node = $this->elem;
+ $this->elem = $node->next;
+ $this->length--;
+ }
+
+ /**
+ * 仅返回栈内所有元素
+ *
+ * @return array 栈内所有元素组成的一个数组
+ */
+ protected function getAllElem()
+ {
+ $result = array ();
+ if ($this->getIsEmpty()) {
+ return $result;
+ }
+ $node = $this->elem;
+ while ($node != null) {
+ $result[] = $node->elem;
+ $node = $node->next;
+ }
+ return $result;
+ }
+
+ /**
+ * 返回栈内某个元素的个数
+ *
+ * @param mixed $elem 待查找的元素的值
+ * @return int
+ **/
+ protected function getCountForElem($elem)
+ {
+ $result = $this->getAllElem();
+ $count = 0;
+ foreach ($result as $value) {
+ if ($elem === $value) {
+ $count++;
+ }
+ }
+ return $count;
+ }
+
+ /**
+ * 调试用请无视
+ *
+ * @param $name
+ * @param $arguments
+ * @return mixed
+ */
+ public function __call($name, $arguments)
+ {
+ $this->preDispatch(); // 调试用,请无视
+ return call_user_func_array(array ($this, $name), $arguments);
+ }
+
+ /**
+ * 调试用
+ *
+ * @param bool $isDebug
+ * @return bool
+ */
+ protected function preDispatch($isDebug = true)
+ {
+ if (!$isDebug) {
+ return false;
+ }
+ $debug = debug_backtrace()[1];
+ $reflection = new ReflectionMethod($this, $debug['args'][0]);
+ $args = '';
+ if (isset($debug['args'][1])) {
+ foreach ($debug['args'][1] as &$value) {
+ if (is_array($value)) {
+ $args .= json_encode($debug['args'][1]) . ', ';
+ } else {
+ $args .= $value . ', ';
+ }
+ }
+ }
+ $args = trim($args, ', ');
+ echo "\t" . $reflection->getDocComment() . PHP_EOL;
+ echo "\t{$debug['args'][0]}({$args})\n" . PHP_EOL;
+ }
+}
+
+$echo = function ($str, $action) {
+ echo $str . "\t->\t" . var_export($action, true) . PHP_EOL;
+ echo "--------------------------- " . PHP_EOL;
+};
+
+//$stack = new StackExample();
+//$stack->setPushStack('First');
+//$stack->setPushStack('Second');
+//$echo('返回栈内所有元素', $stack->getAllElem());
+//$stack->setPushStack('Third');
+//$echo('返回栈内所有元素', $stack->getAllElem());
+//$stack->getPopStack();
+//$echo('返回栈内所有元素', $stack->getAllElem());
diff --git a/tests/BootStrapTest.php b/tests/BootStrapTest.php
new file mode 100644
index 0000000..a4abe2d
--- /dev/null
+++ b/tests/BootStrapTest.php
@@ -0,0 +1,2 @@
+chineseObj = new ChineseTextNumberSort();
+ }
+
+ /**
+ * testValidationModelA
+ *
+ * @test
+ * @throws \Exception
+ */
+ public function testValidationModelA()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第二章 我是Marco小哥哥'
+ ),
+ '二'
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第一节 我是Marco小哥哥'
+ ),
+ '一'
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第二单元 我是Marco小哥哥'
+ ),
+ '二'
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第一章 我是Marco小哥哥'
+ ),
+ '1'
+ );
+ }
+
+ /**
+ * testValidationModelB
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelB()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_B,
+ '01我是Marco小哥哥'
+ ),
+ '01'
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_B,
+ '12我是Marco小哥哥'
+ ),
+ '12'
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_B,
+ '10章我是Marco小哥哥'
+ ),
+ '1'
+ );
+ }
+
+ /**
+ * testValidationModelC
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelC()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_C,
+ '1 我是Marco小哥哥'
+ ),
+ 1
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_C,
+ '22 我是Marco小哥哥'
+ ),
+ 22
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_C,
+ '22 我是Marco小哥哥'
+ ),
+ 21
+ );
+ }
+
+ /**
+ * testValidationModelD
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelD()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_D,
+ '1页-我是Marco小哥哥'
+ ),
+ 1
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_D,
+ '22页-+我是Marco小哥哥'
+ ),
+ 22
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_D,
+ '2页-+我是Marco小哥哥'
+ ),
+ 22
+ );
+ }
+
+ /**
+ * testValidationModelE
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelE()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_E,
+ '1-'
+ ),
+ 1
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_E,
+ '2-+我是Marco小哥哥'
+ ),
+ 2
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_E,
+ '23-我是Marco小哥哥'
+ ),
+ 24
+ );
+ }
+
+ /**
+ * testValidationModelF
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelF()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_F,
+ '1 但是'
+ ),
+ 1
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_F,
+ '1 2对对对'
+ ),
+ 1
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_F,
+ '22 我是Marco小哥哥'
+ ),
+ 2
+ );
+ }
+
+ /**
+ * testValidationModelG
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelG()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_G,
+ '1、、'
+ ),
+ 1
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_G,
+ '01、2对对对'
+ ),
+ 01
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_G,
+ '23、我是Marco小哥哥'
+ ),
+ 24
+ );
+ }
+
+ /**
+ * testValidationModelH
+ *
+ * @throws \Exception
+ * @test
+ */
+ public function testValidationModelH()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_H,
+ '我爱Marco老师小册10 :'
+ ),
+ 10
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_H,
+ '我爱Marco老师小册1 : 阳光鱼'
+ ),
+ 1
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_H,
+ '我爱Marco老师小册1 : 阳光鱼'
+ ),
+ 122
+ );
+ }
+
+ /**
+ * testValidationModelI
+ *
+ * @throws \Exception
+ */
+ public function testValidationModelI()
+ {
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_I,
+ '识字一 01 十'
+ ),
+ '01'
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_I,
+ '狮子 03卧槽'
+ ),
+ '03'
+ );
+
+ $this->assertNotEquals(
+ $this->chineseObj->extractModel(
+ ChineseTextNumberSort::MODEL_REGULAR_I,
+ '狮子 03卧槽'
+ ),
+ '04'
+ );
+ }
+}
diff --git a/tests/Sort/ChineseTextNumberSortModelTest.php b/tests/Sort/ChineseTextNumberSortModelTest.php
new file mode 100644
index 0000000..6b18e90
--- /dev/null
+++ b/tests/Sort/ChineseTextNumberSortModelTest.php
@@ -0,0 +1,301 @@
+chineseObj = new ChineseTextNumberSort();
+ }
+
+ /**
+ * testValidationModelA
+ *
+ * @test
+ */
+ public function testValidationModelA()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第二章 我是Marco小哥哥'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第一节 我是Marco小哥哥'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第二单元 我是Marco小哥哥'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_A,
+ '第一章我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelB
+ *
+ * @test
+ */
+ public function testValidationModelB()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_B,
+ '01我是Marco小哥哥'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_B,
+ '12我是Marco小哥哥'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_B,
+ '第一章我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelC
+ *
+ * @test
+ */
+ public function testValidationModelC()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_C,
+ '1 我是Marco小哥哥'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_C,
+ '22 我是Marco小哥哥'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_C,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelD
+ *
+ * @test
+ */
+ public function testValidationModelD()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_D,
+ '1页-我是Marco小哥哥'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_D,
+ '1页-+我是Marco小哥哥'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_D,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelD
+ *
+ * @test
+ */
+ public function testValidationModelE()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_E,
+ '1-'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_E,
+ '1-+我是Marco小哥哥'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_E,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+
+
+ /**
+ * MODEL_REGULAR_F
+ *
+ * @test
+ */
+ public function testValidationModelF()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_F,
+ '1 但是'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_F,
+ '1 2对对对'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_F,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelG
+ *
+ * @test
+ */
+ public function testValidationModelG()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_G,
+ '1、、'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_G,
+ '01、2对对对'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_G,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelG
+ *
+ * @test
+ */
+ public function testValidationModelH()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_H,
+ '我爱Marco老师小册10 :'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_H,
+ '我爱Marco老师小册1 : 阳光鱼'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_H,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+
+ /**
+ * testValidationModelG
+ *
+ * @test
+ */
+ public function testValidationModelI()
+ {
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_I,
+ '识字一 01 十'
+ )
+ );
+
+ $this->assertTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_I,
+ '狮子 03卧槽'
+ )
+ );
+
+ $this->assertNotTrue(
+ $this->chineseObj->regularModel(
+ ChineseTextNumberSort::MODEL_REGULAR_I,
+ '22我是Marco小哥哥'
+ )
+ );
+ }
+}
diff --git a/tests/Sort/ChineseTextNumberSortTest.php b/tests/Sort/ChineseTextNumberSortTest.php
new file mode 100644
index 0000000..7a50ef7
--- /dev/null
+++ b/tests/Sort/ChineseTextNumberSortTest.php
@@ -0,0 +1,246 @@
+chineseObj = new ChineseTextNumberSort();
+ }
+
+ /**
+ * testChineseTextListSorter
+ */
+ public function testChineseTextListSorter()
+ {
+ $this->assertArraySubset(
+ $this->chineseObj->chineseTextListSorter(
+ array (
+ '第五章 我是Marco小哥哥',
+ '第一章 我是Marco小哥哥',
+ '第三章 我是Marco小哥哥',
+ '第三章 我是Marco小哥哥',
+ '第二章 我是Marco小哥哥',
+ )),
+ array (
+ '第一章 我是Marco小哥哥',
+ '第二章 我是Marco小哥哥',
+ '第三章 我是Marco小哥哥',
+ '第三章 我是Marco小哥哥',
+ '第五章 我是Marco小哥哥',
+ )
+ );
+
+ $this->assertArraySubset(
+ $this->chineseObj->chineseTextListSorter(
+ array (
+ '05我是Marco小哥哥',
+ '03我是Marco小哥哥',
+ '02我是Marco小哥哥',
+ '04我是Marco小哥哥',
+ '01我是Marco小哥哥',
+ )),
+ array (
+ '01我是Marco小哥哥',
+ '02我是Marco小哥哥',
+ '03我是Marco小哥哥',
+ '04我是Marco小哥哥',
+ '05我是Marco小哥哥',
+ )
+ );
+
+ $this->assertArraySubset(
+ $this->chineseObj->chineseTextListSorter(
+ array (
+ '6页-我是Marco小哥哥',
+ '2页-我是Marco小哥哥',
+ '3页-我是Marco小哥哥',
+ '4页-我是Marco小哥哥',
+ '5页-我是Marco小哥哥',
+ '1页-我是Marco小哥哥',
+ )),
+ array (
+ '1页-我是Marco小哥哥',
+ '2页-我是Marco小哥哥',
+ '3页-我是Marco小哥哥',
+ '4页-我是Marco小哥哥',
+ '5页-我是Marco小哥哥',
+ '6页-我是Marco小哥哥',
+ )
+ );
+
+ $this->assertArraySubset(
+ $this->chineseObj->chineseTextListSorter(
+ array (
+ '我爱Marco老师小册6 :',
+ '我爱Marco老师小册2 :',
+ '我爱Marco老师小册3 :',
+ '我爱Marco老师小册4 :',
+ '我爱Marco老师小册5 :',
+ '我爱Marco老师小册1 :',
+ '我爱Marco老师小册7 :',
+ )),
+ array (
+ '我爱Marco老师小册1 :',
+ '我爱Marco老师小册2 :',
+ '我爱Marco老师小册3 :',
+ '我爱Marco老师小册4 :',
+ '我爱Marco老师小册5 :',
+ '我爱Marco老师小册6 :',
+ '我爱Marco老师小册7 :',
+ )
+ );
+
+ $this->assertArraySubset(
+ $this->chineseObj->chineseTextListSorter(
+ array (
+ '6、2对对对',
+ '2、2对对对',
+ '4、2对对对',
+ '3、2对对对',
+ '5、2对对对',
+ '1、2对对对',
+ )),
+ array (
+ '1、2对对对',
+ '2、2对对对',
+ '3、2对对对',
+ '4、2对对对',
+ '5、2对对对',
+ '6、2对对对',
+ )
+ );
+ }
+
+
+ /**
+ * testTextAnalysis
+ */
+ public function testTextAnalysis()
+ {
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('第二章 我是Marco小哥哥'),
+ 2
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('01我是Marco小哥哥'),
+ 1
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('1 我是Marco小哥哥'),
+ 1
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('1页-我是Marco小哥哥'),
+ 1
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('2-+我是Marco小哥哥'),
+ 2
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('1 2对对对'),
+ 1
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('1、2对对对'),
+ 1
+ );
+ $this->assertEquals(
+ $this->chineseObj->textAnalysis('我爱Marco老师小册10 :'),
+ 10
+ );
+ $this->assertNotEquals(
+ $this->chineseObj->textAnalysis('我爱Marco老师小册10 :'),
+ 12
+ );
+ }
+
+
+ /**
+ * testModelAnalysis
+ *
+ * @throws \ReflectionException
+ */
+ public function testModelAnalysis()
+ {
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('第二章 我是Marco小哥哥'),
+ ChineseTextNumberSort::MODEL_REGULAR_A
+ );
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('01我是Marco小哥哥'),
+ ChineseTextNumberSort::MODEL_REGULAR_B
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('1 我是Marco小哥哥'),
+ ChineseTextNumberSort::MODEL_REGULAR_F
+ );
+
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('1页-我是Marco小哥哥'),
+ ChineseTextNumberSort::MODEL_REGULAR_D
+ );
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('2-+我是Marco小哥哥'),
+ ChineseTextNumberSort::MODEL_REGULAR_E
+ );
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('1 2对对对'),
+ ChineseTextNumberSort::MODEL_REGULAR_F
+ );
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('1、2对对对'),
+ ChineseTextNumberSort::MODEL_REGULAR_G
+ );
+ $this->assertEquals(
+ $this->chineseObj->modelAnalysis('我爱Marco老师小册10 :'),
+ ChineseTextNumberSort::MODEL_REGULAR_H
+ );
+ $this->assertNotEquals(
+ $this->chineseObj->modelAnalysis('我爱Marco老师小册10 :'),
+ ChineseTextNumberSort::MODEL_REGULAR_G
+ );
+ }
+
+ /**
+ * description
+ *
+ * @test
+ */
+ /**
+ * description
+ *
+ * @throws \ReflectionException
+ * @test
+ */
+ public function testAnalysisText()
+ {
+ var_dump($this->chineseObj->getAllModelRegular());
+ die;
+ }
+
+}