Merge pull request #2 from wangzheng0822/master

update
This commit is contained in:
Qiyuan Jiao 2019-02-27 17:10:53 +08:00 committed by GitHub
commit b9ef965456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 1607 additions and 59 deletions

1
.gitignore vendored
View File

@ -19,6 +19,7 @@
*.tar.gz
*.rar
*.DS_Store
*.exe
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

View File

@ -1,6 +1,74 @@
# 数据结构和算法之美
# [https://time.geekbang.org/column/intro/126](https://time.geekbang.org/column/intro/126)
# 数据结构和算法必知必会的50个代码实现
# Java rate limiting library/framework
# https://github.com/wangzheng0822/ratelimiter4j
## 数组
* 实现一个支持动态扩容的数组
* 实现一个大小固定的有序数组,支持动态增删改操作
* 实现两个有序数组合并为一个有序数组
## 链表
* 实现单链表、循环链表、双向链表,支持增删操作
* 实现单链表反转
* 实现两个有序的链表合并为一个有序链表
* 实现求链表的中间结点
## 栈
* 用数组实现一个顺序栈
* 用链表实现一个链式栈
* 编程模拟实现一个浏览器的前进、后退功能
## 队列
* 用数组实现一个顺序队列
* 用链表实现一个链式队列
* 实现一个循环队列
## 递归
* 编程实现斐波那契数列求值f(n)=f(n-1)+f(n-2)
* 编程实现求阶乘n!
* 编程实现一组数据集合的全排列
## 排序
* 实现归并排序、快速排序、插入排序、冒泡排序、选择排序
* 编程实现O(n)时间复杂度内找到一组数据的第K大元素
## 二分查找
* 实现一个有序数组的二分查找算法
* 实现模糊二分查找算法(比如大于等于给定值的第一个元素)
## 散列表
* 实现一个基于链表法解决冲突问题的散列表
* 实现一个LRU缓存淘汰算法
## 字符串
* 实现一个字符集只包含az这26个英文字母的Trie树
* 实现朴素的字符串匹配算法
## 二叉树
* 实现一个二叉查找树,并且支持插入、删除、查找操作
* 实现查找二叉查找树中某个节点的后继、前驱节点
* 实现二叉树前、中、后序以及按层遍历
## 堆
* 实现一个小顶堆、大顶堆、优先级队列
* 实现堆排序
* 利用优先级队列合并K个有序数组
* 求一组动态数据集合的最大Top K
## 图
* 实现有向图、无向图、有权图、无权图的邻接矩阵和邻接表表示方法
* 实现图的深度优先搜索、广度优先搜索
* 实现Dijkstra算法、A*算法
* 实现拓扑排序的Kahn算法、DFS算法
## 回溯
* 利用回溯算法求解八皇后问题
* 利用回溯算法求解0-1背包问题
## 分治
* 利用分治算法求一组数据的逆序对个数
## 动态规划
* 0-1背包问题
* 最小路径和
* 编程实现莱文斯坦最短编辑距离
* 编程实现查找两个字符串的最长公共子序列
* 编程实现一个数据序列的最长递增子序列

View File

@ -1,6 +1,6 @@
using System;
namespace _05_array
namespace algo05_array
{
public sealed class Array<T> where T : IComparable<T>
{

View File

@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

View File

@ -1,7 +1,6 @@
using System.Text.RegularExpressions;
using _05_array;
using algo05_array;
namespace _06_linked_list
namespace algo06_linked_list
{
/// <summary>
/// 使用数组实现LRU缓存淘汰算法

View File

@ -1,4 +1,4 @@
namespace _06_linked_list
namespace algo06_linked_list
{
/// <summary>
/// 使用单链表实现LRU缓存淘汰算法

View File

@ -1,6 +1,6 @@
using System;
namespace _06_linked_list
namespace algo06_linked_list
{
/// <summary>
/// 单链表的插入、删除、清空、查找

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\05-array\_05_array.csproj" />
<ProjectReference Include="..\05-array\algo05_array.csproj" />
</ItemGroup>
</Project>

View File

@ -1,7 +1,7 @@
using System;
using _06_linked_list;
using algo06_linked_list;
namespace _07_linkedlist
namespace algo07_linkedlist
{
/// <summary>
/// 单链表常用算法操作

View File

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\06-linkedlist\_06_linked_list.csproj" />
<ProjectReference Include="..\..\06-linkedlist\algo06_linked_list.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,41 @@
using System;
namespace algo08_stack
{
public class ArrayStack<T>
{
private readonly int _capacity;
private readonly T[] _data;
private int _top = -1; // 指向栈顶元素,当为-1时表示栈为空
public ArrayStack(int capacity)
{
_capacity = capacity;
_data = new T[capacity];
}
public int Count => _top + 1;
public void Push(T val)
{
if (Count == _capacity) throw new InvalidOperationException("Stack full.");
_top++;
_data[_top] = val;
}
public T Pop()
{
if (_top == -1) throw new InvalidOperationException("Stack empty.");
T val = _data[_top];
_top--;
return val;
}
}
}

View File

@ -0,0 +1,51 @@
using System;
namespace algo08_stack
{
public class LinkedStack<T>
{
private StackListNode<T> _top;
public int Count { get; private set; }
public void Push(T val)
{
var newNode = new StackListNode<T>(val);
newNode.Next = _top;
_top = newNode;
Count++;
}
public T Pop()
{
if (_top == null) throw new InvalidOperationException("Stack empty");
T val = _top.Value;
_top = _top.Next;
Count--;
return val;
}
public void Clear()
{
while (Count > 0)
{
Pop();
}
}
}
public class StackListNode<T>
{
public StackListNode(T nodeValue)
{
Value = nodeValue;
}
public T Value { get; set; }
public StackListNode<T> Next { get; set; }
}
}

View File

@ -0,0 +1,39 @@
namespace algo08_stack
{
/// <summary>
/// 利用链栈实现浏览器怎么进后退
/// </summary>
public class LinkedStackBrowser
{
private readonly LinkedStack<string> _backStack = new LinkedStack<string>();
private readonly LinkedStack<string> _forwardStack = new LinkedStack<string>();
public void Open(string url)
{
_backStack.Push(url);
_forwardStack.Clear();
}
public string Backward()
{
if (_backStack.Count == 0) return string.Empty;
string url = _backStack.Pop();
_forwardStack.Push(url);
return url;
}
public string Forward()
{
if (_forwardStack.Count == 0) return string.Empty;
string url = _forwardStack.Pop();
_backStack.Push(url);
return url;
}
}
}

View File

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -1,7 +1,7 @@
using System;
using algo05_array;
using Xunit;
using Xunit.Abstractions;
using _05_array;
namespace _05_array_tests
{

View File

@ -15,7 +15,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\05-array\_05_array.csproj" />
<ProjectReference Include="..\..\05-array\algo05_array.csproj" />
</ItemGroup>
</Project>

View File

@ -1,7 +1,7 @@
using System;
using _06_linked_list;
using algo06_linked_list;
namespace _06_linkedlist_tests
namespace algo06_linkedlist_tests
{
public class BaseLinkedListTests
{

View File

@ -1,9 +1,9 @@
using algo05_array;
using algo06_linked_list;
using Xunit;
using Xunit.Abstractions;
using _05_array;
using _06_linked_list;
namespace _06_linkedlist_tests
namespace algo06_linkedlist_tests
{
public class LRUWithArrayTests
{

View File

@ -1,8 +1,8 @@
using Xunit;
using Xunit.Abstractions;
using _06_linked_list;
using algo06_linked_list;
namespace _06_linkedlist_tests
namespace algo06_linkedlist_tests
{
public class LRUWithLinkedListTests : BaseLinkedListTests
{

View File

@ -1,9 +1,9 @@
using System;
using Xunit;
using Xunit.Abstractions;
using _06_linked_list;
using algo06_linked_list;
namespace _06_linkedlist_tests
namespace algo06_linkedlist_tests
{
public class SingleLinkedListTests : BaseLinkedListTests
{

View File

@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RootNamespace>_06_linkedlist_tests</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
@ -14,8 +13,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\05-array\_05_array.csproj" />
<ProjectReference Include="..\..\06-linkedlist\_06_linked_list.csproj" />
<ProjectReference Include="..\..\05-array\algo05_array.csproj" />
<ProjectReference Include="..\..\06-linkedlist\algo06_linked_list.csproj" />
</ItemGroup>
</Project>

View File

@ -1,10 +1,10 @@
using System;
using Xunit;
using _06_linkedlist_tests;
using _06_linked_list;
using _07_linkedlist;
using algo06_linkedlist_tests;
using algo06_linked_list;
using algo07_linkedlist;
namespace _07_linkedlist_tests
namespace algo07_linkedlist_tests
{
public class SingleLinkedListAlgoTests : BaseLinkedListTests
{

View File

@ -13,9 +13,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\06-linkedlist\_06_linked_list.csproj" />
<ProjectReference Include="..\..\07-linkedlist\_07_linkedlist\_07_linkedlist.csproj" />
<ProjectReference Include="..\_06_linkedlist_tests\_06_linkedlist_tests.csproj" />
<ProjectReference Include="..\..\06-linkedlist\algo06_linked_list.csproj" />
<ProjectReference Include="..\..\07-linkedlist\_07_linkedlist\algo07_linkedlist.csproj" />
<ProjectReference Include="..\_06_linkedlist_tests\algo06_linkedlist_tests.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,81 @@
using System;
using algo08_stack;
using Xunit;
using Xunit.Abstractions;
namespace algo08_stack_tests
{
public class ArrayStackTests
{
private readonly ITestOutputHelper _output;
public ArrayStackTests(ITestOutputHelper output)
{
_output = output;
}
private void PrintStackArray<T>(ArrayStack<T> list)
{
if (list.Count == 0) return;
while (list.Count > 0)
{
T item = list.Pop();
_output.WriteLine(item.ToString());
}
}
[Fact]
public void Push_3_Elements_Then_Length_Equal_3()
{
var stack = new ArrayStack<int>(5);
stack.Push(2);
stack.Push(4);
stack.Push(6);
Assert.Equal(3, stack.Count);
PrintStackArray(stack);
}
[Fact]
public void Push_Throw_InvalidOperationException_When_Stack_Full()
{
var stack = new ArrayStack<int>(5);
stack.Push(2);
stack.Push(4);
stack.Push(6);
stack.Push(8);
stack.Push(10);
Exception ex = Assert.Throws<InvalidOperationException>(() => stack.Push(11));
Assert.IsType<InvalidOperationException>(ex);
PrintStackArray(stack);
}
[Fact]
public void Pop_Throw_InvalidOperationException_When_Stack_Empty()
{
var stack = new ArrayStack<int>(5);
Exception ex = Assert.Throws<InvalidOperationException>(() => stack.Pop());
Assert.IsType<InvalidOperationException>(ex);
PrintStackArray(stack);
}
[Fact]
public void Pop_Valid_When_Stack_Not_Empty()
{
var stack = new ArrayStack<int>(5);
stack.Push(2);
stack.Push(4);
int val = stack.Pop();
Assert.Equal(4, val);
PrintStackArray(stack);
}
}
}

View File

@ -0,0 +1,65 @@
using System;
using algo08_stack;
using Xunit;
using Xunit.Abstractions;
namespace algo08_stack_tests
{
public class LinkedStackTests
{
private readonly ITestOutputHelper _output;
public LinkedStackTests(ITestOutputHelper output)
{
_output = output;
}
private void PrintStackLinkedList<T>(LinkedStack<T> list)
{
if (list.Count == 0) return;
while (list.Count > 0)
{
var val = list.Pop();
_output.WriteLine(val.ToString());
}
}
[Fact]
public void Push_3_Elements_Then_Length_Equal_3()
{
var stack = new LinkedStack<int>();
stack.Push(2);
stack.Push(4);
stack.Push(6);
Assert.Equal(3, stack.Count);
PrintStackLinkedList(stack);
}
[Fact]
public void Pop_Throw_InvalidOperationException_When_Stack_Empty()
{
var stack = new LinkedStack<int>();
Exception ex = Assert.Throws<InvalidOperationException>(() => stack.Pop());
Assert.IsType<InvalidOperationException>(ex);
PrintStackLinkedList(stack);
}
[Fact]
public void Pop_Valid_When_Stack_Not_Empty()
{
var stack = new LinkedStack<int>();
stack.Push(2);
stack.Push(4);
var nodeVal = stack.Pop();
Assert.Equal(4, nodeVal);
PrintStackLinkedList(stack);
}
}
}

View File

@ -0,0 +1,107 @@
using algo08_stack;
using Xunit;
using Xunit.Abstractions;
namespace algo08_stack_tests
{
public class LinkedStackBrowserTests
{
private readonly ITestOutputHelper _output;
public LinkedStackBrowserTests(ITestOutputHelper output)
{
_output = output;
}
[Fact]
public void Browser_Open_4_Links_Back_2_Return_Right_Link()
{
var browser = new LinkedStackBrowser();
browser.Open("www.google.com");
browser.Open("www.baidu.com");
browser.Open("www.qq.com");
browser.Open("www.dadu.com");
string url = browser.Backward();
url = browser.Backward();
Assert.Equal("www.qq.com", url);
}
[Fact]
public void Browser_Open_4_Links_Back_4_Return_Empty()
{
var browser = new LinkedStackBrowser();
browser.Open("www.google.com");
browser.Open("www.baidu.com");
browser.Open("www.qq.com");
browser.Open("www.dadu.com");
browser.Backward();
browser.Backward();
browser.Backward();
browser.Backward();
string url = browser.Backward();
Assert.Equal(string.Empty, url);
}
[Fact]
public void Browser_Forward_Before_End()
{
var browser = new LinkedStackBrowser();
browser.Open("www.google.com");
browser.Open("www.baidu.com");
browser.Open("www.qq.com");
browser.Open("www.dadu.com");
browser.Backward();
browser.Backward();
browser.Backward();
browser.Forward();
string url = browser.Forward();
Assert.Equal("www.qq.com", url);
}
[Fact]
public void Browser_Forward_Until_End()
{
var browser = new LinkedStackBrowser();
browser.Open("www.google.com");
browser.Open("www.baidu.com");
browser.Open("www.qq.com");
browser.Open("www.dadu.com");
browser.Backward();
browser.Backward();
browser.Backward();
browser.Forward();
browser.Forward();
browser.Forward();
string url = browser.Forward();
Assert.Equal(string.Empty, url);
}
[Fact]
public void Browser_Backward_And_Open_New_Then_Cannot_Forward()
{
var browser = new LinkedStackBrowser();
browser.Open("www.google.com");
browser.Open("www.baidu.com");
browser.Open("www.qq.com");
browser.Backward();
browser.Backward();
browser.Open("www.dadu.com");
string url = browser.Forward();
Assert.Equal(string.Empty, url);
}
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\08-stack\algo08_stack\algo08_stack.csproj" />
</ItemGroup>
</Project>

View File

@ -3,19 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_05_array", "05-array\_05_array.csproj", "{B88033F6-FF08-434A-AED7-91F5CDB73402}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo05_array", "05-array\algo05_array.csproj", "{B88033F6-FF08-434A-AED7-91F5CDB73402}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_06_linked_list", "06-linkedlist\_06_linked_list.csproj", "{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo06_linked_list", "06-linkedlist\algo06_linked_list.csproj", "{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_05_array_tests", "Tests\_05_array_tests\_05_array_tests.csproj", "{14982212-49E4-4409-8BFD-2D8A2945BD83}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo05_array_tests", "Tests\_05_array_tests\algo05_array_tests.csproj", "{14982212-49E4-4409-8BFD-2D8A2945BD83}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_06_linkedlist_tests", "Tests\_06_linkedlist_tests\_06_linkedlist_tests.csproj", "{1B93D9C6-D6C1-4619-BFB9-D84C29099223}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo06_linkedlist_tests", "Tests\_06_linkedlist_tests\algo06_linkedlist_tests.csproj", "{1B93D9C6-D6C1-4619-BFB9-D84C29099223}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_07_linkedlist", "07-linkedlist\_07_linkedlist\_07_linkedlist.csproj", "{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo07_linkedlist", "07-linkedlist\_07_linkedlist\algo07_linkedlist.csproj", "{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_07_linkedlist_tests", "Tests\_07_linkedlist_tests\_07_linkedlist_tests.csproj", "{66C3BC00-C135-4279-A666-A330A86F20D5}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo07_linkedlist_tests", "Tests\_07_linkedlist_tests\algo07_linkedlist_tests.csproj", "{66C3BC00-C135-4279-A666-A330A86F20D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo08_stack", "08-stack\algo08_stack\algo08_stack.csproj", "{E080D481-C98E-43F3-B1D1-51DCF4CF7146}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "algo08_stack_tests", "Tests\algo08_stack_tests\algo08_stack_tests.csproj", "{6A249475-54EA-4039-9B0C-DC0E0A884C07}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -102,10 +106,35 @@ Global
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x64.Build.0 = Release|Any CPU
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x86.ActiveCfg = Release|Any CPU
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x86.Build.0 = Release|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Debug|x64.ActiveCfg = Debug|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Debug|x64.Build.0 = Debug|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Debug|x86.ActiveCfg = Debug|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Debug|x86.Build.0 = Debug|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Release|Any CPU.Build.0 = Release|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Release|x64.ActiveCfg = Release|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Release|x64.Build.0 = Release|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Release|x86.ActiveCfg = Release|Any CPU
{E080D481-C98E-43F3-B1D1-51DCF4CF7146}.Release|x86.Build.0 = Release|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Debug|x64.ActiveCfg = Debug|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Debug|x64.Build.0 = Debug|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Debug|x86.ActiveCfg = Debug|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Debug|x86.Build.0 = Debug|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Release|Any CPU.Build.0 = Release|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Release|x64.ActiveCfg = Release|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Release|x64.Build.0 = Release|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Release|x86.ActiveCfg = Release|Any CPU
{6A249475-54EA-4039-9B0C-DC0E0A884C07}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{14982212-49E4-4409-8BFD-2D8A2945BD83} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
{1B93D9C6-D6C1-4619-BFB9-D84C29099223} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
{66C3BC00-C135-4279-A666-A330A86F20D5} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
{6A249475-54EA-4039-9B0C-DC0E0A884C07} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,41 @@
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
var slow *ListNode = head
var fast *ListNode = head
var prev *ListNode = nil
var temp *ListNode = nil
if (head == nil || head.Next == nil) {
return true
}
for (fast != nil && fast.Next !=nil){
fast = fast.Next.Next
temp = slow.Next
slow.Next = prev
prev = slow
slow = temp
} // 快的先跑完,同时反转了一半链表,剪短
if fast != nil {
slow = slow.Next // 处理余数,跨过中位数
// prev 增加中 2->1->nil
}
var l1 *ListNode = prev
var l2 *ListNode = slow
for (l1 != nil && l2 !=nil && l1.Val == l2.Val){
l1 = l1.Next
l2 = l2.Next
}
return (l1 == nil && l2 == nil)
}

73
go/34_kmp/kmp.go Normal file
View File

@ -0,0 +1,73 @@
package main
import (
"fmt"
)
func getNexts(pattern string) []int {
m := len(pattern)
nexts := make([]int, m)
for index := range nexts {
nexts[index] = -1
}
for i := 1; i < m - 1; i++ {
j := nexts[i - 1]
for pattern[j + 1] != pattern[i] && j >= 0 {
j = nexts[j]
}
if pattern[j + 1] == pattern[i] {
j += 1
}
nexts[i] = j
}
return nexts
}
func findByKMP(s string, pattern string) int {
n := len(s)
m := len(pattern)
if n < m {
return -1
}
nexts := getNexts(pattern)
j := 0
for i := 0; i < n; i++ {
for j > 0 && s[i] != pattern[j] {
j = nexts[j - 1] + 1
}
if s[i] == pattern[j] {
if j == m - 1 {
return i - m + 1
}
j += 1
}
}
return -1
}
func main(){
s := "abc abcdab abcdabcdabde"
pattern := "bcdabd"
fmt.Println(findByKMP(s, pattern)) //16
s = "aabbbbaaabbababbabbbabaaabb"
pattern = "abab"
fmt.Println(findByKMP(s, pattern)) //11
s = "aabbbbaaabbababbabbbabaaabb"
pattern = "ababacd"
fmt.Println(findByKMP(s, pattern)) //-1
s = "hello"
pattern = "ll"
fmt.Println(findByKMP(s, pattern)) //2
}

29
go/45_bitmap/bitmap.go Normal file
View File

@ -0,0 +1,29 @@
package bitmap
// BitMap implement bitmap
type BitMap []byte
// New create BitMap
func New(length uint) BitMap {
return make([]byte, length/8+1)
}
// Set set value in bitmap
func (b BitMap) Set(value uint) {
byteIndex := value / 8
if byteIndex >= uint(len(b)) {
return
}
bitIndex := value % 8
[]byte(b)[byteIndex] |= 1 << bitIndex
}
// Get check whether value exist or not
func (b BitMap) Get(value uint) bool {
byteIndex := value / 8
if byteIndex >= uint(len(b)) {
return false
}
bitIndex := value % 8
return []byte(b)[byteIndex]&(1<<bitIndex) != 0
}

View File

@ -0,0 +1,15 @@
package bitmap
import (
"testing"
)
func TestBitMap(t *testing.T) {
bitMap := New(80)
for i := 0; i <= 100; i += 10 {
bitMap.Set(uint(i))
}
for i := 0; i <= 100; i += 10 {
t.Log(bitMap.Get(uint(i)))
}
}

View File

@ -5,7 +5,7 @@ package array;
* 2数组中的数据是int类型的
*
* Author: Zheng
* modify: xing
* modify: xing, Gsealy
*/
public class Array {
//定义整型数据data保存数据
@ -71,7 +71,6 @@ public class Array {
}
this.data = arr;*/
--count;
return true;
}
@ -83,7 +82,7 @@ public class Array {
}
public static void main(String[] args) {
ArrayOperate array = new ArrayOperate(5);
Array array = new Array(5);
array.printAll();
array.insert(0, 3);
array.insert(0, 4);
@ -93,6 +92,4 @@ public class Array {
//array.insert(3, 11);
array.printAll();
}
}

View File

@ -81,7 +81,8 @@ public class LRUBasedArray<T> {
* @param object
*/
public void removeAndCache(T object) {
value[--count] = null;
T key = value[--count];
holder.remove(key);
cache(object, count);
}

View File

@ -151,7 +151,7 @@ function isEven(num){
}
var num = [1,2,3,4,5,6,7,8];
var someEven = num.some(isEven);
if(even){
if(someEven){
console.log("有些数字是偶数");
}else{
console.log("没有数字是偶数");
@ -208,14 +208,24 @@ console.log(pass)
#### 二维数组
JavaScript 可以通过在数组里在嵌套一个数组来形成二维数组。
```
var grades = [[88,86,82],[91,82,83],[77,72,79]];
var grades = [
[88,86,82],
[91,82,83],
[77,72,79],
[86,80,82]
];
console.log(grades[1][2]); // 83
```
#### 处理二维数组
对于二维数组的处理可以分为两种,一种按列访问,一种是按行访问。
按列访问,外层循环对应行,内层循环对应列。例如,上述的数组,每一行对应一个学生的成绩记录,可以通过相加所有成绩,然后除以科目数来得到该生的平均成绩。
按列访问,外层循环对应行,内层循环对应列。例如,上述的数组,每一行对应一个学生三门科目的成绩记录,可以通过相加所有成绩,然后除以科目数来得到该生的平均成绩。
```
var grades = [[88,86,82],[91,82,83],[77,72,79]];
var grades = [
[88,86,82],
[91,82,83],
[77,72,79],
[86,80,82]
];
var total = 0;
var average = 0.0;
for(var row = 0;row<grades.length;++row){
@ -232,27 +242,34 @@ for(var row = 0;row<grades.length;++row){
> student 1 average: 85.33
student 2 average: 85.33
student 3 average: 76.00
student 4 average: 82.67
对于按行访问,则外层循环对应列,内城循环对应行,例如还是上述数组,现在的数组表示一个学生各科的分数,我们来求其平均成绩
对于按行访问,则外层循环对应列,内层循环对应行,例如还是上述数组,现在的数组表示一个学生三场考试四门科目的各科分数,我们来求每场考试的平均成绩
```
var grades = [[88,86,82],[91,82,83],[77,72,79]];
var grades = [
[88,86,82],
[91,82,83],
[77,72,79],
[86,80,82]
];
var total = 0;
var average = 0.0;
for(var col = 0;col <grades.length;++col ){
for(var row= 0;row<grades[col ].length;++row){
//这里假设每场考试的科目都一样所以可以通过grades[0].length来获取考试数量
for(var col = 0;col <grades[0].length;++col ){
for(var row= 0;row<grades.length;++row){
total += grades[row][col];
}
average = total/grades[col ].length;
average = total/grades.length;
console.log("exam "+parseInt(col +1)+" average: "+average.toFixed(2));
total = 0;
average = 0.0;
}
```
输出结果为:
> exam 1 average: 85.33
> exam 1 average: 85.50
exam 2 average: 80.00
exam 3 average: 81.33
exam 3 average: 81.50
其实只要调整 for 循环的顺序就可以控制是按行还是按列来输出此外JavaScript 还可以处理一些参差不齐的数组比如一个二维数组中的数组有的是两个元素有的是四个元素并不是都相同在这种情况下JavaScript 依然可以处理运行而不报错,这是因为不管多或少,都可以通过 length 属性来计算。
#### 对象数组

View File

@ -0,0 +1,56 @@
class TrieNode {
constructor(data){
this.data = data;
this.children = new Array(26);
this.isEndingChar = false
}
}
class TrieTree {
constructor(data){
this.root = new TrieNode('/')
}
insert (text) {
let node = this.root;
for (let char of text) {
let index = char.charCodeAt() - 'a'.charCodeAt();
if(!node.children[index]) {
node.children[index] = new TrieNode(char);
}
node = node.children[index];
}
node.isEndingChar = true;
}
find (text) {
let node = this.root;
for(let char of text) {
let index = char.charCodeAt() - 'a'.charCodeAt();
if(node.children[index]) {
node = node.children[index];
} else {
return false;
}
}
return node.isEndingChar;
}
}
var tree = new TrieTree();
var strs = ["how", "hi", "her", "hello", "so", "see"];
for(let str of strs) {
tree.insert(str);
}
for(let str of strs) {
console.log(tree.find(str));
}
console.log(tree.find('world'));

View File

@ -0,0 +1,103 @@
MAX_LEN = 128;
class ACNode {
constructor(data){
this.data = data;
this.children = new Array(MAX_LEN);
this.isEndingChar = false;
this.length = 0;
this.fail = null;
}
}
class ACTree {
constructor(data){
this.root = new ACNode('/')
}
insert (text) {
let node = this.root;
for (let char of text) {
let index = char.charCodeAt() + 1;
if(!node.children[index]) {
node.children[index] = new ACNode(char);
}
node = node.children[index];
}
node.isEndingChar = true;
node.length = text.length;
}
buildFailurePointer() {
let root = this.root;
let queue = [];
queue.push(root);
while (queue.length > 0) {
let p = queue.shift();
for (let i = 0; i < MAX_LEN; i++) {
let pc = p.children[i];
if (!pc) {
continue;
}
if(p == root) {
pc.fail = root;
} else {
let q = p.fail;
while (q) {
let qc = q.children[pc.data.charCodeAt() + 1];
if(qc) {
pc.fail = qc;
break;
}
q = q.fail;
}
if(!q) {
pc.fail = root;
}
}
queue.push(pc);
}
}
}
match (text) {
let root = this.root;
let n = text.length;
let p = root;
for(let i = 0; i < n; i++) {
let idx = text[i].charCodeAt() + 1;
while(!p.children[idx] && p != root){
p = p.fail;
}
p = p.children[idx];
if(!p) {
p = root;
}
let tmp = p;
while ( tmp != root) {
if (tmp.isEndingChar == true) {
console.log(`Start from ${i - p.length + 1}, length: ${p.length}`);
}
tmp = tmp.fail;
}
}
}
}
let automata = new ACTree();
let patterns = ["at", "art", "oars", "soar"];
for (let pattern of patterns) {
automata.insert(pattern);
}
automata.buildFailurePointer()
automata.match("soarsoars");

View File

@ -0,0 +1,74 @@
<?php
/**
* 8皇后解法共92种解法 回溯思想
* Class Queen
*/
class Queen
{
public $result = [];
function cal8queens($row)
{
if ($row == 8) {
$this->printQueens();
return;
}
//每一行有8中放法
for($column = 0; $column < 8; $column++) {
if ($this->isOk($row, $column)) {
$this->result[$row] = $column;
$this->cal8queens($row + 1);
}
}
}
//row行的column列是否合适
function isOk($row, $column)
{
$leftup = $column - 1;
$rightdown = $column + 1;
for ($i = $row - 1; $i >= 0; $i--) {
//判断上一行的 column 列是否有值
if ($this->result[$i] == $column) {
return false;
}
//左上角是否有值
if ($leftup >= 0 && $this->result[$i] == $leftup) {
return false;
}
//右下角是否有值
if ($rightdown < 8 && $this->result[$i] == $rightdown) {
return false;
}
$leftup--;
$rightdown++;
}
return true;
}
//打印
function printQueens()
{
for ($row = 0; $row < 8; $row++) {
for ($column = 0; $column < 8; $column++) {
if ($this->result[$row] == $column) {
echo 'Q';
} else {
echo '*';
}
}
echo '<br>';
}
}
}
$queen = new Queen();
$queen->cal8queens(0);

View File

@ -0,0 +1,25 @@
package ch39_back_tracking
class BagWeight(maxBagItemCount: Int, maxBagWeight: Int) {
def calculateMaxWeight(items: Array[Int]): Int = {
var maxWeight = 0
def _calcMaxWeight(itemIndex: Int, currentWeight: Int): Unit = {
if (currentWeight == maxBagWeight || itemIndex == items.length) {
if (currentWeight > maxWeight) {
maxWeight = currentWeight
}
} else {
//check next item
_calcMaxWeight(itemIndex + 1, currentWeight)
if (currentWeight + items(itemIndex) <= maxBagWeight) {
_calcMaxWeight(itemIndex + 1, currentWeight + items(itemIndex))
}
}
}
_calcMaxWeight(0, 0)
maxWeight
}
}

View File

@ -0,0 +1,78 @@
package ch39_back_tracking
import scala.util.control.Breaks._
class EightQueens {
//use array index to identify the row,the value of the row to identify the column
val result = new Array[Int](8)
var count = 0
def calc8Queues(row: Int): Unit = {
if (row == 8) {
//everything is done
print8Queens()
return
}
for (column <- Range(0, 8)) {
if (isOkOnColumn(row, column)) {
result(row) = column //place the column value into the array
calc8Queues(row + 1) //calculate next row
}
}
}
def isOkOnColumn(row: Int, column: Int): Boolean = {
var ok = true
var leftUp = column - 1
var rightUp = column + 1
breakable {
//will compare all the rows above current row
for (i <- row - 1 to 0 by -1) {
//check current column
if (result(i) == column) {
ok = false
break
}
//check left up
if (leftUp >= 0) {
if (result(i) == leftUp) {
ok = false
break
}
}
//check right up
if (rightUp < 8) {
if (result(i) == rightUp) {
ok = false
break
}
}
//move leftUp and rightUp
leftUp -= 1
rightUp += 1
}
}
ok
}
def print8Queens(): Unit = {
count +=1
for (row <- Range(0, 8)) {
for (column <- Range(0, 8)) {
if (result(row) == column) {
print("Q ")
} else {
print("* ")
}
}
//new line for next row
println("")
}
println(count+"==============")
}
}

View File

@ -0,0 +1,77 @@
package ch39_back_tracking
import scala.util.control.Breaks.{break, breakable}
class NQueens(numberOfQueens:Int) {
//use array index to identify the row,the value of the row to identify the column
val result = new Array[Int](numberOfQueens)
var count = 0
def calcNQueues(row: Int): Unit = {
if (row == numberOfQueens) {
//everything is done
printNQueens()
return
}
for (column <- Range(0, numberOfQueens)) {
if (isOkOnColumn(row, column)) {
result(row) = column //place the column value into the array
calcNQueues(row + 1) //calculate next row
}
}
}
def isOkOnColumn(row: Int, column: Int): Boolean = {
var ok = true
var leftUp = column - 1
var rightUp = column + 1
breakable {
//will compare all the rows above current row
for (i <- row - 1 to 0 by -1) {
//check current column
if (result(i) == column) {
ok = false
break
}
//check left up
if (leftUp >= 0) {
if (result(i) == leftUp) {
ok = false
break
}
}
//check right up
if (rightUp < numberOfQueens) {
if (result(i) == rightUp) {
ok = false
break
}
}
//move leftUp and rightUp
leftUp -= 1
rightUp += 1
}
}
ok
}
def printNQueens(): Unit = {
count +=1
for (row <- Range(0, numberOfQueens)) {
for (column <- Range(0, numberOfQueens)) {
if (result(row) == column) {
print("Q ")
} else {
print("* ")
}
}
//new line for next row
println("")
}
println(count+"==============")
}
}

View File

@ -0,0 +1,113 @@
package ch39_back_tracking
import scala.util.control.Breaks._
class Sudoku {
def resolve(grid: Array[Array[Int]]): Unit = {
printGrid(grid)
println("")
if (resolve(grid, 0, 0)) {
printGrid(grid)
} else {
println("no result")
printGrid(grid)
}
}
private[this] def resolve(grid: Array[Array[Int]], row: Int, column: Int): Boolean = {
if (row == 8 && column == 9) {
//find the result
return true
}
if (column == 9) {
//move to next line
return resolve(grid, row + 1, 0)
}
if (grid(row)(column) != 0) {
//given number, resolve next one
return resolve(grid, row, column + 1)
}
//start the real resolve
for (num <- 1 to 9) {
if (isOk(grid, row, column, num)) {
grid(row)(column) = num
if (resolve(grid, row, column + 1)) {
return true
}
}
}
//do not find anything, reset given row and column
grid(row)(column) = 0
false
}
def isOk(grid: Array[Array[Int]], row: Int, column: Int, num: Int): Boolean = {
isRowOk(grid, row, num) && isColumnOk(grid, column, num) && isSmallBoxOk(grid, row, column, num)
}
def isRowOk(grid: Array[Array[Int]], row: Int, num: Int): Boolean = {
var isOk = true
breakable {
for (column <- Range(0, 9)) {
if (grid(row)(column) == num) {
isOk = false
break
}
}
}
isOk
}
def isColumnOk(grid: Array[Array[Int]], column: Int, num: Int): Boolean = {
var isOk = true
breakable {
for (row <- Range(0, 9)) {
if (grid(row)(column) == num) {
isOk = false
break
}
}
}
isOk
}
def isSmallBoxOk(grid: Array[Array[Int]], row: Int, column: Int, num: Int): Boolean = {
val rowOffSet = (row / 3) * 3
val columnOffSet = (column / 3) * 3
var isOk = true
breakable {
for (i <- Range(0, 3)) {
for (j <- Range(0, 3)) {
if (grid(i + rowOffSet)(j + columnOffSet) == num) {
isOk = false
break
}
}
}
}
isOk
}
def printGrid(grid: Array[Array[Int]]): Unit = {
for (i <- Range(0, 9)) {
if (i % 3 == 0) {
println("-------------------------")
}
for (j <- Range(0, 9)) {
if (j % 3 == 0) {
print("| ")
}
print(grid(i)(j) + " ")
}
println("| ")
}
println("-------------------------")
}
}

View File

@ -0,0 +1,100 @@
package ch43_topology_sort
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
class GraphTopology(vertex: Int) {
//define the graph
val adjacency = new Array[mutable.MutableList[Int]](vertex)
for (i <- Range(0, vertex)) {
adjacency(i) = new mutable.MutableList[Int]()
}
def addEdge(startIndex: Int, targetIndex: Int) = {
adjacency(startIndex) += targetIndex
}
def topologySortByKahn(): Array[Int] = {
val seq = new mutable.ArrayBuffer[Int]()
//inDegrees contains all the inDegree for a given node
val inDegrees = new Array[Int](vertex)
for (i <- Range(0, vertex)) {
for (j <- adjacency(i).indices) {
val index = adjacency(i).get(j).get
inDegrees(index) += 1
}
}
val queue = new mutable.Queue[Int]()
for (i <- inDegrees.indices) {
if (inDegrees(i) == 0) {
// means there is no inDegree for this node,
// this could be the starting point of the dependency graph
queue += i
}
}
//start to navigating the graph from the starting point
while (queue.nonEmpty) {
val index = queue.dequeue()
//push to the result
seq += index
for (i <- adjacency(index).indices) {
val inDegreeIndex = adjacency(index).get(i).get
inDegrees(inDegreeIndex) -= 1
if (inDegrees(inDegreeIndex) == 0) {
queue += inDegreeIndex
}
}
}
seq.toArray
}
def topologySortByDFS(): Array[Int] = {
val inverseAdj = new Array[mutable.MutableList[Int]](vertex)
for (i <- Range(0, vertex)) {
inverseAdj(i) = new mutable.MutableList[Int]()
}
//build the inverse adj
for (i <- Range(0, vertex)) {
for (j <- adjacency(i).indices) {
val index = adjacency(i).get(j).get
inverseAdj(index) += i
}
}
val visited = new Array[Boolean](vertex)
val seq = new ArrayBuffer[Int]()
for (i <- Range(0, vertex)) {
if (!visited(i)) {
visited(i) = true
//call dfs
seq ++= dfs(i, inverseAdj, visited)
}
}
seq.toArray
}
def dfs(index: Int, inverseAdj: Array[mutable.MutableList[Int]], visited: Array[Boolean]): ArrayBuffer[Int] = {
val seq = new ArrayBuffer[Int]()
for (i <- inverseAdj(index).indices) {
val sourceIndex = inverseAdj(index).get(i).get
if (!visited(sourceIndex)) {
visited(sourceIndex) = true
seq ++= dfs(sourceIndex, inverseAdj, visited)
}
}
seq += index
seq
}
}

View File

@ -0,0 +1,15 @@
package ch39_back_tracking
import org.scalatest.FlatSpec
class BagWeightTest extends FlatSpec {
behavior of "BagWeightTest"
it should "calculateMaxWeight" in {
val bagWeight = new BagWeight(5,9)
val maxWeight = bagWeight.calculateMaxWeight(Array(1,2,3,5,6))
println(maxWeight)
}
}

View File

@ -0,0 +1,14 @@
package ch39_back_tracking
import org.scalatest.FlatSpec
class EightQueensTest extends FlatSpec {
behavior of "EightQueensTest"
it should "calc8Queues" in {
val eightQueens = new EightQueens()
eightQueens.calc8Queues(0)
}
}

View File

@ -0,0 +1,21 @@
package ch39_back_tracking
import org.scalatest.FlatSpec
class NQueensTest extends FlatSpec {
behavior of "NQueensTest"
it should "calc8Queues" in {
val eightQueens = new NQueens(8)
eightQueens.calcNQueues(0)
}
it should "calc4Queues" in {
val eightQueens = new NQueens(4)
eightQueens.calcNQueues(0)
}
}

View File

@ -0,0 +1,74 @@
package ch39_back_tracking
import org.scalatest.FlatSpec
class SudokuTest extends FlatSpec {
behavior of "SudokuTest"
it should "resolve - 1" in {
val grid = Array(
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0)
)
val sudoku = new Sudoku()
sudoku.resolve(grid)
}
it should "resolve - 2" in {
val grid = Array(
Array(0, 0, 7, 2, 5, 6, 4, 0 ,0),
Array(4, 0, 0, 0, 0, 0, 0, 0, 5),
Array(0, 1, 0, 0, 3, 9, 0, 6, 0),
Array(0, 0, 0, 5, 0, 8, 0, 0, 0),
Array(0, 0, 8, 0, 6, 0, 2, 0, 0),
Array(0, 9, 0, 1, 0, 7, 0, 0, 0),
Array(0, 3, 0, 0, 7, 0, 0, 9, 0),
Array(2, 0, 0, 0, 0, 0, 0, 0, 4),
Array(0, 0, 6, 3, 1, 2, 7, 0, 8)
)
val sudoku = new Sudoku()
sudoku.resolve(grid)
}
it should "resolve - 3" in {
val grid = Array(
Array(3, 8, 0, 0, 0, 0, 0, 0, 1),
Array(0, 0, 6, 4, 0, 0, 7, 8, 5),
Array(0, 0, 9, 0, 2, 0, 3, 0, 0),
Array(0, 6, 0, 0, 9, 0, 0, 0, 0),
Array(8, 0, 0, 3, 0, 2, 0, 0, 9),
Array(0, 0, 0, 0, 4, 0, 0, 7, 0),
Array(0, 0, 1, 0, 7, 0, 5, 0, 0),
Array(4, 9, 5, 0, 0, 6, 1, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 9, 2)
)
val sudoku = new Sudoku()
sudoku.resolve(grid)
}
it should "print grid" in {
val grid = Array(
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0)
)
val sudoku = new Sudoku()
sudoku.printGrid(grid)
}
}

View File

@ -0,0 +1,120 @@
package ch43_topology_sort
import org.scalatest.{FlatSpec, Matchers}
class GraphTopologyTest extends FlatSpec with Matchers {
behavior of "GraphTopologyTest"
/*
a -> b
| |
\|/ \|/
c -> d -> e
*/
it should "topologySortByKahn - 1" in {
val nodes = Array("a", "b", "c", "d", "e")
val graphTopology = new GraphTopology(nodes.length)
graphTopology.addEdge(0, 1)
graphTopology.addEdge(0, 2)
graphTopology.addEdge(1, 3)
graphTopology.addEdge(2, 3)
graphTopology.addEdge(3, 4)
val seq = graphTopology.topologySortByKahn()
seq.map(nodes(_)).mkString(",") should equal("a,b,c,d,e")
}
/*
a -> d ---
| |
\|/ \|/
e -> c
*/
it should "topologySortByKahn - 2" in {
val nodes = Array("a", "b", "c", "d", "e")
val graphTopology = new GraphTopology(nodes.length)
graphTopology.addEdge(0, 3)
graphTopology.addEdge(3, 4)
graphTopology.addEdge(3, 2)
graphTopology.addEdge(4, 2)
val seq = graphTopology.topologySortByKahn()
seq.map(nodes(_)).mkString(",") should equal("a,b,d,e,c")
}
/*
a -> d <- b
| /|\
\|/ |
e -> c
*/
it should "topologySortByKahn - 3" in {
val nodes = Array("a", "b", "c", "d", "e")
val graphTopology = new GraphTopology(nodes.length)
graphTopology.addEdge(0, 3)
graphTopology.addEdge(3, 4)
graphTopology.addEdge(4, 2)
graphTopology.addEdge(2, 1)
graphTopology.addEdge(1, 3)
val seq = graphTopology.topologySortByKahn()
seq.map(nodes(_)).mkString(",") should equal("a")
}
/*
a -> b
| |
\|/ \|/
c -> d -> e
*/
it should "topologySortByDFS - 1" in {
val nodes = Array("a", "b", "c", "d", "e")
val graphTopology = new GraphTopology(nodes.length)
graphTopology.addEdge(0, 1)
graphTopology.addEdge(0, 2)
graphTopology.addEdge(1, 3)
graphTopology.addEdge(2, 3)
graphTopology.addEdge(3, 4)
val seq = graphTopology.topologySortByDFS()
seq.map(nodes(_)).mkString(",") should equal("a,b,c,d,e")
}
/*
a -> d ---
| |
\|/ \|/
e -> c
*/
it should "topologySortByDFS - 2" in {
val nodes = Array("a", "b", "c", "d", "e")
val graphTopology = new GraphTopology(nodes.length)
graphTopology.addEdge(0, 3)
graphTopology.addEdge(3, 4)
graphTopology.addEdge(3, 2)
graphTopology.addEdge(4, 2)
val seq = graphTopology.topologySortByDFS()
seq.map(nodes(_)).mkString(",") should equal("a,b,d,e,c")
}
/*
a -> d <- b
| /|\
\|/ |
e -> c
*/
it should "topologySortByDFS - 3" in {
val nodes = Array("a", "b", "c", "d", "e")
val graphTopology = new GraphTopology(nodes.length)
graphTopology.addEdge(0, 3)
graphTopology.addEdge(3, 4)
graphTopology.addEdge(4, 2)
graphTopology.addEdge(2, 1)
graphTopology.addEdge(1, 3)
val seq = graphTopology.topologySortByKahn()
seq.map(nodes(_)).mkString(",") should equal("a")
}
}