Merge branch 'krahets:master' into master

This commit is contained in:
Daniel
2023-01-09 11:05:01 +11:00
committed by GitHub
93 changed files with 2147 additions and 1124 deletions
@@ -15,12 +15,12 @@ int *randomNumbers(int n) {
nums[i] = i + 1;
}
// 随机打乱数组元素
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
return nums;
}
-228
View File
@@ -1,228 +0,0 @@
/**
* File: avl_tree.cpp
* Created Time: 2022-12-2
* Author: mgisr (maguagua0706@gmail.com)
*/
#include "../include/include.hpp"
class AvlTree {
private:
TreeNode *root{};
static bool isBalance(const TreeNode *p);
static int getBalanceFactor(const TreeNode *p);
static void updateHeight(TreeNode *p);
void fixBalance(TreeNode *p);
static bool isLeftChild(const TreeNode *p);
static TreeNode *&fromParentTo(TreeNode *node);
public:
AvlTree() = default;
AvlTree(const AvlTree &p) = default;
const TreeNode *search(int val);
bool insert(int val);
bool remove(int val);
void printTree();
};
// 判断该结点是否平衡
bool AvlTree::isBalance(const TreeNode *p) {
int balance_factor = getBalanceFactor(p);
if (-1 <= balance_factor && balance_factor <= 1) { return true; }
else { return false; }
}
// 获取当前结点的平衡因子
int AvlTree::getBalanceFactor(const TreeNode *p) {
if (p->left == nullptr && p->right == nullptr) { return 0; }
else if (p->left == nullptr) { return (-1 - p->right->height); }
else if (p->right == nullptr) { return p->left->height + 1; }
else { return p->left->height - p->right->height; }
}
// 更新结点高度
void AvlTree::updateHeight(TreeNode *p) {
if (p->left == nullptr && p->right == nullptr) { p->height = 0; }
else if (p->left == nullptr) { p->height = p->right->height + 1; }
else if (p->right == nullptr) { p->height = p->left->height + 1; }
else { p->height = std::max(p->left->height, p->right->height) + 1; }
}
void AvlTree::fixBalance(TreeNode *p) {
// 左旋操作
auto rotate_left = [&](TreeNode *node) -> TreeNode * {
TreeNode *temp = node->right;
temp->parent = p->parent;
node->right = temp->left;
if (temp->left != nullptr) {
temp->left->parent = node;
}
temp->left = node;
node->parent = temp;
updateHeight(node);
updateHeight(temp);
return temp;
};
// 右旋操作
auto rotate_right = [&](TreeNode *node) -> TreeNode * {
TreeNode *temp = node->left;
temp->parent = p->parent;
node->left = temp->right;
if (temp->right != nullptr) {
temp->right->parent = node;
}
temp->right = node;
node->parent = temp;
updateHeight(node);
updateHeight(temp);
return temp;
};
// 根据规则选取旋转方式
if (getBalanceFactor(p) > 1) {
if (getBalanceFactor(p->left) > 0) {
if (p->parent == nullptr) { root = rotate_right(p); }
else { fromParentTo(p) = rotate_right(p); }
} else {
p->left = rotate_left(p->left);
if (p->parent == nullptr) { root = rotate_right(p); }
else { fromParentTo(p) = rotate_right(p); }
}
} else {
if (getBalanceFactor(p->right) < 0) {
if (p->parent == nullptr) { root = rotate_left(p); }
else { fromParentTo(p) = rotate_left(p); }
} else {
p->right = rotate_right(p->right);
if (p->parent == nullptr) { root = rotate_left(p); }
else { fromParentTo(p) = rotate_left(p); }
}
}
}
// 判断当前结点是否为其父节点的左孩子
bool AvlTree::isLeftChild(const TreeNode *p) {
if (p->parent == nullptr) { return false; }
return (p->parent->left == p);
}
// 返回父节点指向当前结点指针的引用
TreeNode *&AvlTree::fromParentTo(TreeNode *node) {
if (isLeftChild(node)) { return node->parent->left; }
else { return node->parent->right; }
}
const TreeNode *AvlTree::search(int val) {
TreeNode *p = root;
while (p != nullptr) {
if (p->val == val) { return p; }
else if (p->val > val) { p = p->left; }
else { p = p->right; }
}
return nullptr;
}
bool AvlTree::insert(int val) {
TreeNode *p = root;
if (p == nullptr) {
root = new TreeNode(val);
return true;
}
for (;;) {
if (p->val == val) { return false; }
else if (p->val > val) {
if (p->left == nullptr) {
p->left = new TreeNode(val, p);
break;
} else {
p = p->left;
}
} else {
if (p->right == nullptr) {
p->right = new TreeNode(val, p);
break;
} else {
p = p->right;
}
}
}
for (; p != nullptr; p = p->parent) {
if (!isBalance(p)) {
fixBalance(p);
break;
} else { updateHeight(p); }
}
return true;
}
bool AvlTree::remove(int val) {
TreeNode *p = root;
if (p == nullptr) { return false; }
while (p != nullptr) {
if (p->val == val) {
TreeNode *real_delete_node = p;
TreeNode *next_node;
if (p->left == nullptr) {
next_node = p->right;
if (p->parent == nullptr) { root = next_node; }
else { fromParentTo(p) = next_node; }
} else if (p->right == nullptr) {
next_node = p->left;
if (p->parent == nullptr) { root = next_node; }
else { fromParentTo(p) = next_node; }
} else {
while (real_delete_node->left != nullptr) {
real_delete_node = real_delete_node->left;
}
std::swap(p->val, real_delete_node->val);
next_node = real_delete_node->right;
if (real_delete_node->parent == p) { p->right = next_node; }
else { real_delete_node->parent->left = next_node; }
}
if (next_node != nullptr) {
next_node->parent = real_delete_node->parent;
}
for (p = real_delete_node; p != nullptr; p = p->parent) {
if (!isBalance(p)) { fixBalance(p); }
updateHeight(p);
}
delete real_delete_node;
return true;
} else if (p->val > val) {
p = p->left;
} else {
p = p->right;
}
}
return false;
}
void inOrder(const TreeNode *root) {
if (root == nullptr) return;
inOrder(root->left);
cout << root->val << ' ';
inOrder(root->right);
}
void AvlTree::printTree() {
inOrder(root);
cout << endl;
}
int main() {
AvlTree tree = AvlTree();
// tree.insert(13);
// tree.insert(24);
// tree.insert(37);
// tree.insert(90);
// tree.insert(53);
tree.insert(53);
tree.insert(90);
tree.insert(37);
tree.insert(24);
tree.insert(13);
tree.remove(90);
tree.printTree();
const TreeNode *p = tree.search(37);
cout << p->val;
return 0;
}
+1 -2
View File
@@ -30,8 +30,7 @@ vector<int> hierOrder(TreeNode* root) {
int main() {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode* root = vecToTree(vector<int>
{ 1, 2, 3, 4, 5, 6, 7, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX });
TreeNode* root = vecToTree(vector<int> { 1, 2, 3, 4, 5, 6, 7 });
cout << endl << "初始化二叉树\n" << endl;
PrintUtil::printTree(root);
+1 -2
View File
@@ -41,8 +41,7 @@ void postOrder(TreeNode* root) {
int main() {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode* root = vecToTree(vector<int>
{ 1, 2, 3, 4, 5, 6, 7, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX});
TreeNode* root = vecToTree(vector<int> { 1, 2, 3, 4, 5, 6, 7 });
cout << endl << "初始化二叉树\n" << endl;
PrintUtil::printTree(root);
+1
View File
@@ -9,6 +9,7 @@
#include <iostream>
#include <string>
#include <sstream>
#include <climits>
#include "ListNode.hpp"
#include "TreeNode.hpp"
+8 -7
View File
@@ -27,23 +27,24 @@ struct TreeNode {
* @return TreeNode*
*/
TreeNode *vecToTree(vector<int> list) {
if (list.empty()) {
if (list.empty())
return nullptr;
}
auto *root = new TreeNode(list[0]);
queue<TreeNode *> que;
size_t n = list.size(), index = 1;
while (index < n) {
que.emplace(root);
size_t n = list.size(), index = 0;
while (!que.empty()) {
auto node = que.front();
que.pop();
if (++index >= n) break;
if (index < n) {
node->left = new TreeNode(list[index++]);
node->left = new TreeNode(list[index]);
que.emplace(node->left);
}
if (++index >= n) break;
if (index < n) {
node->right = new TreeNode(list[index++]);
node->right = new TreeNode(list[index]);
que.emplace(node->right);
}
}
+1 -2
View File
@@ -41,8 +41,7 @@ namespace hello_algo.chapter_tree
{
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode? root = TreeNode.ArrToTree(new int?[] {
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
TreeNode? root = TreeNode.ArrToTree(new int?[] { 1, 2, 3, 4, 5, 6, 7 });
Console.WriteLine("\n初始化二叉树\n");
PrintUtil.PrintTree(root);
+1 -2
View File
@@ -57,8 +57,7 @@ namespace hello_algo.chapter_tree
{
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode? root = TreeNode.ArrToTree(new int?[] {
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
TreeNode? root = TreeNode.ArrToTree(new int?[] { 1, 2, 3, 4, 5, 6, 7 });
Console.WriteLine("\n初始化二叉树\n");
PrintUtil.PrintTree(root);
+2 -2
View File
@@ -11,8 +11,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
</Project>
+5 -5
View File
@@ -19,7 +19,7 @@ namespace hello_algo.include
}
/**
* Generate a binary tree with an array
* Generate a binary tree given an array
* @param arr
* @return
*/
@@ -31,22 +31,22 @@ namespace hello_algo.include
TreeNode root = new TreeNode((int) arr[0]);
Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root);
int i = 1;
while (queue.Count!=0)
int i = 0;
while (queue.Count != 0)
{
TreeNode node = queue.Dequeue();
if (++i >= arr.Length) break;
if (arr[i] != null)
{
node.left = new TreeNode((int) arr[i]);
queue.Enqueue(node.left);
}
i++;
if (++i >= arr.Length) break;
if (arr[i] != null)
{
node.right = new TreeNode((int) arr[i]);
queue.Enqueue(node.right);
}
i++;
}
return root;
}
@@ -5,7 +5,7 @@
package chapter_array_and_linkedlist
/* 列表类简易实现 */
type MyList struct {
type myList struct {
numsCapacity int
nums []int
numsSize int
@@ -13,8 +13,8 @@ type MyList struct {
}
/* 构造函数 */
func newMyList() *MyList {
return &MyList{
func newMyList() *myList {
return &myList{
numsCapacity: 10, // 列表容量
nums: make([]int, 10), // 数组(存储列表元素)
numsSize: 0, // 列表长度(即当前元素数量)
@@ -23,17 +23,17 @@ func newMyList() *MyList {
}
/* 获取列表长度(即当前元素数量) */
func (l *MyList) size() int {
func (l *myList) size() int {
return l.numsSize
}
/* 获取列表容量 */
func (l *MyList) capacity() int {
func (l *myList) capacity() int {
return l.numsCapacity
}
/* 访问元素 */
func (l *MyList) get(index int) int {
func (l *myList) get(index int) int {
// 索引如果越界则抛出异常,下同
if index >= l.numsSize {
panic("索引越界")
@@ -42,7 +42,7 @@ func (l *MyList) get(index int) int {
}
/* 更新元素 */
func (l *MyList) set(num, index int) {
func (l *myList) set(num, index int) {
if index >= l.numsSize {
panic("索引越界")
}
@@ -50,7 +50,7 @@ func (l *MyList) set(num, index int) {
}
/* 尾部添加元素 */
func (l *MyList) add(num int) {
func (l *myList) add(num int) {
// 元素数量超出容量时,触发扩容机制
if l.numsSize == l.numsCapacity {
l.extendCapacity()
@@ -61,7 +61,7 @@ func (l *MyList) add(num int) {
}
/* 中间插入元素 */
func (l *MyList) insert(num, index int) {
func (l *myList) insert(num, index int) {
if index >= l.numsSize {
panic("索引越界")
}
@@ -79,7 +79,7 @@ func (l *MyList) insert(num, index int) {
}
/* 删除元素 */
func (l *MyList) remove(index int) int {
func (l *myList) remove(index int) int {
if index >= l.numsSize {
panic("索引越界")
}
@@ -95,7 +95,7 @@ func (l *MyList) remove(index int) int {
}
/* 列表扩容 */
func (l *MyList) extendCapacity() {
func (l *myList) extendCapacity() {
// 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组
l.nums = append(l.nums, make([]int, l.numsCapacity*(l.extendRatio-1))...)
// 更新列表容量
@@ -103,7 +103,7 @@ func (l *MyList) extendCapacity() {
}
/* 返回有效长度的列表 */
func (l *MyList) toArray() []int {
func (l *myList) toArray() []int {
// 仅转换有效长度范围内的列表元素
return l.nums[:l.numsSize]
}
@@ -9,31 +9,31 @@ import (
"strconv"
)
/* Node 结构体 */
type Node struct {
/* 结构体 */
type node struct {
val int
next *Node
next *node
}
/* TreeNode 二叉树 */
type TreeNode struct {
/* treeNode 二叉树 */
type treeNode struct {
val int
left *TreeNode
right *TreeNode
left *treeNode
right *treeNode
}
/* 创建 Node 结构体 */
func newNode(val int) *Node {
return &Node{val: val}
/* 创建 node 结构体 */
func newNode(val int) *node {
return &node{val: val}
}
/* 创建 TreeNode 结构体 */
func newTreeNode(val int) *TreeNode {
return &TreeNode{val: val}
/* 创建 treeNode 结构体 */
func newTreeNode(val int) *treeNode {
return &treeNode{val: val}
}
/* 输出二叉树 */
func printTree(root *TreeNode) {
func printTree(root *treeNode) {
if root == nil {
return
}
@@ -72,7 +72,7 @@ func spaceLinear(n int) {
// 长度为 n 的数组占用 O(n) 空间
_ = make([]int, n)
// 长度为 n 的列表占用 O(n) 空间
var nodes []*Node
var nodes []*node
for i := 0; i < n; i++ {
nodes = append(nodes, newNode(i))
}
@@ -112,7 +112,7 @@ func spaceQuadraticRecur(n int) int {
}
/* 指数阶(建立满二叉树) */
func buildTree(n int) *TreeNode {
func buildTree(n int) *treeNode {
if n == 0 {
return nil
}
+16 -16
View File
@@ -7,30 +7,30 @@ package chapter_hashing
import "fmt"
/* 键值对 int->String */
type Entry struct {
type entry struct {
key int
val string
}
/* 基于数组简易实现的哈希表 */
type ArrayHashMap struct {
bucket []*Entry
type arrayHashMap struct {
bucket []*entry
}
func newArrayHashMap() *ArrayHashMap {
func newArrayHashMap() *arrayHashMap {
// 初始化一个长度为 100 的桶(数组)
bucket := make([]*Entry, 100)
return &ArrayHashMap{bucket: bucket}
bucket := make([]*entry, 100)
return &arrayHashMap{bucket: bucket}
}
/* 哈希函数 */
func (a *ArrayHashMap) hashFunc(key int) int {
func (a *arrayHashMap) hashFunc(key int) int {
index := key % 100
return index
}
/* 查询操作 */
func (a *ArrayHashMap) get(key int) string {
func (a *arrayHashMap) get(key int) string {
index := a.hashFunc(key)
pair := a.bucket[index]
if pair == nil {
@@ -40,22 +40,22 @@ func (a *ArrayHashMap) get(key int) string {
}
/* 添加操作 */
func (a *ArrayHashMap) put(key int, val string) {
pair := &Entry{key: key, val: val}
func (a *arrayHashMap) put(key int, val string) {
pair := &entry{key: key, val: val}
index := a.hashFunc(key)
a.bucket[index] = pair
}
/* 删除操作 */
func (a *ArrayHashMap) remove(key int) {
func (a *arrayHashMap) remove(key int) {
index := a.hashFunc(key)
// 置为 nil ,代表删除
a.bucket[index] = nil
}
/* 获取所有键对 */
func (a *ArrayHashMap) entrySet() []*Entry {
var pairs []*Entry
func (a *arrayHashMap) entrySet() []*entry {
var pairs []*entry
for _, pair := range a.bucket {
if pair != nil {
pairs = append(pairs, pair)
@@ -65,7 +65,7 @@ func (a *ArrayHashMap) entrySet() []*Entry {
}
/* 获取所有键 */
func (a *ArrayHashMap) keySet() []int {
func (a *arrayHashMap) keySet() []int {
var keys []int
for _, pair := range a.bucket {
if pair != nil {
@@ -76,7 +76,7 @@ func (a *ArrayHashMap) keySet() []int {
}
/* 获取所有值 */
func (a *ArrayHashMap) valueSet() []string {
func (a *arrayHashMap) valueSet() []string {
var values []string
for _, pair := range a.bucket {
if pair != nil {
@@ -87,7 +87,7 @@ func (a *ArrayHashMap) valueSet() []string {
}
/* 打印哈希表 */
func (a *ArrayHashMap) print() {
func (a *arrayHashMap) print() {
for _, pair := range a.bucket {
if pair != nil {
fmt.Println(pair.key, "->", pair.val)
@@ -6,8 +6,9 @@ package chapter_searching
import (
"fmt"
. "github.com/krahets/hello-algo/pkg"
"testing"
. "github.com/krahets/hello-algo/pkg"
)
func TestHashingSearch(t *testing.T) {
+6 -6
View File
@@ -8,25 +8,25 @@ package chapter_sorting
// 左子数组区间 [left, mid]
// 右子数组区间 [mid + 1, right]
func merge(nums []int, left, mid, right int) {
// 初始化辅助数组 借助 copy模块
// 初始化辅助数组 借助 copy 模块
tmp := make([]int, right-left+1)
for i := left; i <= right; i++ {
tmp[i-left] = nums[i]
}
// 左子数组的起始索引和结束索引
left_start, left_end := left-left, mid-left
leftStart, leftEnd := left-left, mid-left
// 右子数组的起始索引和结束索引
right_start, right_end := mid+1-left, right-left
rightStart, rightEnd := mid+1-left, right-left
// i, j 分别指向左子数组、右子数组的首元素
i, j := left_start, right_start
i, j := leftStart, rightStart
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for k := left; k <= right; k++ {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if i > left_end {
if i > leftEnd {
nums[k] = tmp[j]
j++
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if j > right_end || tmp[i] <= tmp[j] {
} else if j > rightEnd || tmp[i] <= tmp[j] {
nums[k] = tmp[i]
i++
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
+10 -10
View File
@@ -5,16 +5,16 @@
package chapter_sorting
// 快速排序
type QuickSort struct{}
type quickSort struct{}
// 快速排序(中位基准数优化)
type QuickSortMedian struct{}
type quickSortMedian struct{}
// 快速排序(尾递归优化)
type QuickSortTailCall struct{}
type quickSortTailCall struct{}
/* 哨兵划分 */
func (q *QuickSort) partition(nums []int, left, right int) int {
func (q *quickSort) partition(nums []int, left, right int) int {
// 以 nums[left] 作为基准数
i, j := left, right
for i < j {
@@ -33,7 +33,7 @@ func (q *QuickSort) partition(nums []int, left, right int) int {
}
/* 快速排序 */
func (q *QuickSort) quickSort(nums []int, left, right int) {
func (q *quickSort) quickSort(nums []int, left, right int) {
// 子数组长度为 1 时终止递归
if left >= right {
return
@@ -46,7 +46,7 @@ func (q *QuickSort) quickSort(nums []int, left, right int) {
}
/* 选取三个元素的中位数 */
func (q *QuickSortMedian) medianThree(nums []int, left, mid, right int) int {
func (q *quickSortMedian) medianThree(nums []int, left, mid, right int) int {
if (nums[left] > nums[mid]) != (nums[left] > nums[right]) {
return left
} else if (nums[mid] < nums[left]) != (nums[mid] > nums[right]) {
@@ -56,7 +56,7 @@ func (q *QuickSortMedian) medianThree(nums []int, left, mid, right int) int {
}
/* 哨兵划分(三数取中值)*/
func (q *QuickSortMedian) partition(nums []int, left, right int) int {
func (q *quickSortMedian) partition(nums []int, left, right int) int {
// 以 nums[left] 作为基准数
med := q.medianThree(nums, left, (left+right)/2, right)
// 将中位数交换至数组最左端
@@ -79,7 +79,7 @@ func (q *QuickSortMedian) partition(nums []int, left, right int) int {
}
/* 快速排序 */
func (q *QuickSortMedian) quickSort(nums []int, left, right int) {
func (q *quickSortMedian) quickSort(nums []int, left, right int) {
// 子数组长度为 1 时终止递归
if left >= right {
return
@@ -92,7 +92,7 @@ func (q *QuickSortMedian) quickSort(nums []int, left, right int) {
}
/* 哨兵划分 */
func (q *QuickSortTailCall) partition(nums []int, left, right int) int {
func (q *quickSortTailCall) partition(nums []int, left, right int) int {
// 以 nums[left] 作为基准数
i, j := left, right
for i < j {
@@ -111,7 +111,7 @@ func (q *QuickSortTailCall) partition(nums []int, left, right int) int {
}
/* 快速排序(尾递归优化)*/
func (q *QuickSortTailCall) quickSort(nums []int, left, right int) {
func (q *quickSortTailCall) quickSort(nums []int, left, right int) {
// 子数组长度为 1 时终止
for left < right {
// 哨兵划分操作
+3 -3
View File
@@ -11,7 +11,7 @@ import (
// 快速排序
func TestQuickSort(t *testing.T) {
q := QuickSort{}
q := quickSort{}
nums := []int{4, 1, 3, 1, 5, 2}
q.quickSort(nums, 0, len(nums)-1)
fmt.Println("快速排序完成后 nums = ", nums)
@@ -19,7 +19,7 @@ func TestQuickSort(t *testing.T) {
// 快速排序(中位基准数优化)
func TestQuickSortMedian(t *testing.T) {
q := QuickSortMedian{}
q := quickSortMedian{}
nums := []int{4, 1, 3, 1, 5, 2}
q.quickSort(nums, 0, len(nums)-1)
fmt.Println("快速排序(中位基准数优化)完成后 nums = ", nums)
@@ -27,7 +27,7 @@ func TestQuickSortMedian(t *testing.T) {
// 快速排序(尾递归优化)
func TestQuickSortTailCall(t *testing.T) {
q := QuickSortTailCall{}
q := quickSortTailCall{}
nums := []int{4, 1, 3, 1, 5, 2}
q.quickSort(nums, 0, len(nums)-1)
fmt.Println("快速排序(尾递归优化)完成后 nums = ", nums)
+19 -19
View File
@@ -5,16 +5,16 @@
package chapter_stack_and_queue
/* 基于环形数组实现的队列 */
type ArrayQueue struct {
type arrayQueue struct {
data []int // 用于存储队列元素的数组
capacity int // 队列容量(即最多容量的元素个数)
front int // 头指针,指向队首
rear int // 尾指针,指向队尾 + 1
}
// NewArrayQueue 基于环形数组实现的队列
func NewArrayQueue(capacity int) *ArrayQueue {
return &ArrayQueue{
// newArrayQueue 基于环形数组实现的队列
func newArrayQueue(capacity int) *arrayQueue {
return &arrayQueue{
data: make([]int, capacity),
capacity: capacity,
front: 0,
@@ -22,21 +22,21 @@ func NewArrayQueue(capacity int) *ArrayQueue {
}
}
// Size 获取队列的长度
func (q *ArrayQueue) Size() int {
// size 获取队列的长度
func (q *arrayQueue) size() int {
size := (q.capacity + q.rear - q.front) % q.capacity
return size
}
// IsEmpty 判断队列是否为空
func (q *ArrayQueue) IsEmpty() bool {
// isEmpty 判断队列是否为空
func (q *arrayQueue) isEmpty() bool {
return q.rear-q.front == 0
}
// Offer 入队
func (q *ArrayQueue) Offer(v int) {
// offer 入队
func (q *arrayQueue) offer(v int) {
// 当 rear == capacity 表示队列已满
if q.Size() == q.capacity {
if q.size() == q.capacity {
return
}
// 尾结点后添加
@@ -45,9 +45,9 @@ func (q *ArrayQueue) Offer(v int) {
q.rear = (q.rear + 1) % q.capacity
}
// Poll 出队
func (q *ArrayQueue) Poll() any {
if q.IsEmpty() {
// poll 出队
func (q *arrayQueue) poll() any {
if q.isEmpty() {
return nil
}
v := q.data[q.front]
@@ -56,9 +56,9 @@ func (q *ArrayQueue) Poll() any {
return v
}
// Peek 访问队首元素
func (q *ArrayQueue) Peek() any {
if q.IsEmpty() {
// peek 访问队首元素
func (q *arrayQueue) peek() any {
if q.isEmpty() {
return nil
}
v := q.data[q.front]
@@ -66,6 +66,6 @@ func (q *ArrayQueue) Peek() any {
}
// 获取 Slice 用于打印
func (s *ArrayQueue) toSlice() []int {
return s.data[s.front:s.rear]
func (q *arrayQueue) toSlice() []int {
return q.data[q.front:q.rear]
}
+18 -18
View File
@@ -5,47 +5,47 @@
package chapter_stack_and_queue
/* 基于数组实现的栈 */
type ArrayStack struct {
type arrayStack struct {
data []int // 数据
}
func NewArrayStack() *ArrayStack {
return &ArrayStack{
func newArrayStack() *arrayStack {
return &arrayStack{
// 设置栈的长度为 0,容量为 16
data: make([]int, 0, 16),
}
}
// Size 栈的长度
func (s *ArrayStack) Size() int {
// size 栈的长度
func (s *arrayStack) size() int {
return len(s.data)
}
// IsEmpty 栈是否为空
func (s *ArrayStack) IsEmpty() bool {
return s.Size() == 0
// isEmpty 栈是否为空
func (s *arrayStack) isEmpty() bool {
return s.size() == 0
}
// Push 入栈
func (s *ArrayStack) Push(v int) {
// push 入栈
func (s *arrayStack) push(v int) {
// 切片会自动扩容
s.data = append(s.data, v)
}
// Pop 出栈
func (s *ArrayStack) Pop() any {
// pop 出栈
func (s *arrayStack) pop() any {
// 弹出栈前,先判断是否为空
if s.IsEmpty() {
if s.isEmpty() {
return nil
}
val := s.Peek()
val := s.peek()
s.data = s.data[:len(s.data)-1]
return val
}
// Peek 获取栈顶元素
func (s *ArrayStack) Peek() any {
if s.IsEmpty() {
// peek 获取栈顶元素
func (s *arrayStack) peek() any {
if s.isEmpty() {
return nil
}
val := s.data[len(s.data)-1]
@@ -53,6 +53,6 @@ func (s *ArrayStack) Peek() any {
}
// 获取 Slice 用于打印
func (s *ArrayStack) toSlice() []int {
func (s *arrayStack) toSlice() []int {
return s.data
}
+15 -15
View File
@@ -51,48 +51,48 @@ func TestDeque(t *testing.T) {
func TestLinkedListDeque(t *testing.T) {
// 初始化队列
deque := NewLinkedListDeque()
deque := newLinkedListDeque()
// 元素入队
deque.OfferLast(2)
deque.OfferLast(5)
deque.OfferLast(4)
deque.OfferFirst(3)
deque.OfferFirst(1)
deque.offerLast(2)
deque.offerLast(5)
deque.offerLast(4)
deque.offerFirst(3)
deque.offerFirst(1)
fmt.Print("队列 deque = ")
PrintList(deque.toList())
// 访问队首元素
front := deque.PeekFirst()
front := deque.peekFirst()
fmt.Println("队首元素 front =", front)
rear := deque.PeekLast()
rear := deque.peekLast()
fmt.Println("队尾元素 rear =", rear)
// 元素出队
pollFirst := deque.PollFirst()
pollFirst := deque.pollFirst()
fmt.Print("队首出队元素 pollFirst = ", pollFirst, ",队首出队后 deque = ")
PrintList(deque.toList())
pollLast := deque.PollLast()
pollLast := deque.pollLast()
fmt.Print("队尾出队元素 pollLast = ", pollLast, ",队尾出队后 deque = ")
PrintList(deque.toList())
// 获取队的长度
size := deque.Size()
size := deque.size()
fmt.Println("队的长度 size =", size)
// 判断是否为空
isEmpty := deque.IsEmpty()
isEmpty := deque.isEmpty()
fmt.Println("队是否为空 =", isEmpty)
}
// BenchmarkArrayQueue 67.92 ns/op in Mac M1 Pro
func BenchmarkLinkedListDeque(b *testing.B) {
stack := NewLinkedListDeque()
stack := newLinkedListDeque()
// use b.N for looping
for i := 0; i < b.N; i++ {
stack.OfferLast(777)
stack.offerLast(777)
}
for i := 0; i < b.N; i++ {
stack.PollFirst()
stack.pollFirst()
}
}
@@ -8,31 +8,31 @@ import (
"container/list"
)
// LinkedListDeque 基于链表实现的双端队列, 使用内置包 list 来实现栈
type LinkedListDeque struct {
// linkedListDeque 基于链表实现的双端队列, 使用内置包 list 来实现栈
type linkedListDeque struct {
data *list.List
}
// NewLinkedListDeque 初始化双端队列
func NewLinkedListDeque() *LinkedListDeque {
return &LinkedListDeque{
// newLinkedListDeque 初始化双端队列
func newLinkedListDeque() *linkedListDeque {
return &linkedListDeque{
data: list.New(),
}
}
// OfferFirst 队首元素入队
func (s *LinkedListDeque) OfferFirst(value any) {
// offerFirst 队首元素入队
func (s *linkedListDeque) offerFirst(value any) {
s.data.PushFront(value)
}
// OfferLast 队尾元素入队
func (s *LinkedListDeque) OfferLast(value any) {
// offerLast 队尾元素入队
func (s *linkedListDeque) offerLast(value any) {
s.data.PushBack(value)
}
// PollFirst 队首元素出队
func (s *LinkedListDeque) PollFirst() any {
if s.IsEmpty() {
// pollFirst 队首元素出队
func (s *linkedListDeque) pollFirst() any {
if s.isEmpty() {
return nil
}
e := s.data.Front()
@@ -40,9 +40,9 @@ func (s *LinkedListDeque) PollFirst() any {
return e.Value
}
// PollLast 队尾元素出队
func (s *LinkedListDeque) PollLast() any {
if s.IsEmpty() {
// pollLast 队尾元素出队
func (s *linkedListDeque) pollLast() any {
if s.isEmpty() {
return nil
}
e := s.data.Back()
@@ -50,35 +50,35 @@ func (s *LinkedListDeque) PollLast() any {
return e.Value
}
// PeekFirst 访问队首元素
func (s *LinkedListDeque) PeekFirst() any {
if s.IsEmpty() {
// peekFirst 访问队首元素
func (s *linkedListDeque) peekFirst() any {
if s.isEmpty() {
return nil
}
e := s.data.Front()
return e.Value
}
// PeekLast 访问队尾元素
func (s *LinkedListDeque) PeekLast() any {
if s.IsEmpty() {
// peekLast 访问队尾元素
func (s *linkedListDeque) peekLast() any {
if s.isEmpty() {
return nil
}
e := s.data.Back()
return e.Value
}
// Size 获取队列的长度
func (s *LinkedListDeque) Size() int {
// size 获取队列的长度
func (s *linkedListDeque) size() int {
return s.data.Len()
}
// IsEmpty 判断队列是否为空
func (s *LinkedListDeque) IsEmpty() bool {
// isEmpty 判断队列是否为空
func (s *linkedListDeque) isEmpty() bool {
return s.data.Len() == 0
}
// 获取 List 用于打印
func (s *LinkedListDeque) toList() *list.List {
func (s *linkedListDeque) toList() *list.List {
return s.data
}
@@ -9,26 +9,26 @@ import (
)
/* 基于链表实现的队列 */
type LinkedListQueue struct {
type linkedListQueue struct {
// 使用内置包 list 来实现队列
data *list.List
}
// NewLinkedListQueue 初始化链表
func NewLinkedListQueue() *LinkedListQueue {
return &LinkedListQueue{
// newLinkedListQueue 初始化链表
func newLinkedListQueue() *linkedListQueue {
return &linkedListQueue{
data: list.New(),
}
}
// Offer 入队
func (s *LinkedListQueue) Offer(value any) {
// offer 入队
func (s *linkedListQueue) offer(value any) {
s.data.PushBack(value)
}
// Poll 出队
func (s *LinkedListQueue) Poll() any {
if s.IsEmpty() {
// poll 出队
func (s *linkedListQueue) poll() any {
if s.isEmpty() {
return nil
}
e := s.data.Front()
@@ -36,26 +36,26 @@ func (s *LinkedListQueue) Poll() any {
return e.Value
}
// Peek 访问队首元素
func (s *LinkedListQueue) Peek() any {
if s.IsEmpty() {
// peek 访问队首元素
func (s *linkedListQueue) peek() any {
if s.isEmpty() {
return nil
}
e := s.data.Front()
return e.Value
}
// Size 获取队列的长度
func (s *LinkedListQueue) Size() int {
// size 获取队列的长度
func (s *linkedListQueue) size() int {
return s.data.Len()
}
// IsEmpty 判断队列是否为空
func (s *LinkedListQueue) IsEmpty() bool {
// isEmpty 判断队列是否为空
func (s *linkedListQueue) isEmpty() bool {
return s.data.Len() == 0
}
// 获取 List 用于打印
func (s *LinkedListQueue) toList() *list.List {
func (s *linkedListQueue) toList() *list.List {
return s.data
}
@@ -9,26 +9,26 @@ import (
)
/* 基于链表实现的栈 */
type LinkedListStack struct {
type linkedListStack struct {
// 使用内置包 list 来实现栈
data *list.List
}
// NewLinkedListStack 初始化链表
func NewLinkedListStack() *LinkedListStack {
return &LinkedListStack{
// newLinkedListStack 初始化链表
func newLinkedListStack() *linkedListStack {
return &linkedListStack{
data: list.New(),
}
}
// Push 入栈
func (s *LinkedListStack) Push(value int) {
// push 入栈
func (s *linkedListStack) push(value int) {
s.data.PushBack(value)
}
// Pop 出栈
func (s *LinkedListStack) Pop() any {
if s.IsEmpty() {
// pop 出栈
func (s *linkedListStack) pop() any {
if s.isEmpty() {
return nil
}
e := s.data.Back()
@@ -36,26 +36,26 @@ func (s *LinkedListStack) Pop() any {
return e.Value
}
// Peek 访问栈顶元素
func (s *LinkedListStack) Peek() any {
if s.IsEmpty() {
// peek 访问栈顶元素
func (s *linkedListStack) peek() any {
if s.isEmpty() {
return nil
}
e := s.data.Back()
return e.Value
}
// Size 获取栈的长度
func (s *LinkedListStack) Size() int {
// size 获取栈的长度
func (s *linkedListStack) size() int {
return s.data.Len()
}
// IsEmpty 判断栈是否为空
func (s *LinkedListStack) IsEmpty() bool {
// isEmpty 判断栈是否为空
func (s *linkedListStack) isEmpty() bool {
return s.data.Len() == 0
}
// 获取 List 用于打印
func (s *LinkedListStack) toList() *list.List {
func (s *linkedListStack) toList() *list.List {
return s.data
}
+26 -26
View File
@@ -48,87 +48,87 @@ func TestQueue(t *testing.T) {
func TestArrayQueue(t *testing.T) {
// 初始化队列,使用队列的通用接口
capacity := 10
queue := NewArrayQueue(capacity)
queue := newArrayQueue(capacity)
// 元素入队
queue.Offer(1)
queue.Offer(3)
queue.Offer(2)
queue.Offer(5)
queue.Offer(4)
queue.offer(1)
queue.offer(3)
queue.offer(2)
queue.offer(5)
queue.offer(4)
fmt.Print("队列 queue = ")
PrintSlice(queue.toSlice())
// 访问队首元素
peek := queue.Peek()
peek := queue.peek()
fmt.Println("队首元素 peek =", peek)
// 元素出队
poll := queue.Poll()
poll := queue.poll()
fmt.Print("出队元素 poll = ", poll, ", 出队后 queue = ")
PrintSlice(queue.toSlice())
// 获取队的长度
size := queue.Size()
size := queue.size()
fmt.Println("队的长度 size =", size)
// 判断是否为空
isEmpty := queue.IsEmpty()
isEmpty := queue.isEmpty()
fmt.Println("队是否为空 =", isEmpty)
}
func TestLinkedListQueue(t *testing.T) {
// 初始化队
queue := NewLinkedListQueue()
queue := newLinkedListQueue()
// 元素入队
queue.Offer(1)
queue.Offer(3)
queue.Offer(2)
queue.Offer(5)
queue.Offer(4)
queue.offer(1)
queue.offer(3)
queue.offer(2)
queue.offer(5)
queue.offer(4)
fmt.Print("队列 queue = ")
PrintList(queue.toList())
// 访问队首元素
peek := queue.Peek()
peek := queue.peek()
fmt.Println("队首元素 peek =", peek)
// 元素出队
poll := queue.Poll()
poll := queue.poll()
fmt.Print("出队元素 poll = ", poll, ", 出队后 queue = ")
PrintList(queue.toList())
// 获取队的长度
size := queue.Size()
size := queue.size()
fmt.Println("队的长度 size =", size)
// 判断是否为空
isEmpty := queue.IsEmpty()
isEmpty := queue.isEmpty()
fmt.Println("队是否为空 =", isEmpty)
}
// BenchmarkArrayQueue 8 ns/op in Mac M1 Pro
func BenchmarkArrayQueue(b *testing.B) {
capacity := 1000
stack := NewArrayQueue(capacity)
stack := newArrayQueue(capacity)
// use b.N for looping
for i := 0; i < b.N; i++ {
stack.Offer(777)
stack.offer(777)
}
for i := 0; i < b.N; i++ {
stack.Poll()
stack.poll()
}
}
// BenchmarkLinkedQueue 62.66 ns/op in Mac M1 Pro
func BenchmarkLinkedQueue(b *testing.B) {
stack := NewLinkedListQueue()
stack := newLinkedListQueue()
// use b.N for looping
for i := 0; i < b.N; i++ {
stack.Offer(777)
stack.offer(777)
}
for i := 0; i < b.N; i++ {
stack.Poll()
stack.poll()
}
}
+26 -26
View File
@@ -46,85 +46,85 @@ func TestStack(t *testing.T) {
func TestArrayStack(t *testing.T) {
// 初始化栈, 使用接口承接
stack := NewArrayStack()
stack := newArrayStack()
// 元素入栈
stack.Push(1)
stack.Push(3)
stack.Push(2)
stack.Push(5)
stack.Push(4)
stack.push(1)
stack.push(3)
stack.push(2)
stack.push(5)
stack.push(4)
fmt.Print("栈 stack = ")
PrintSlice(stack.toSlice())
// 访问栈顶元素
peek := stack.Peek()
peek := stack.peek()
fmt.Println("栈顶元素 peek =", peek)
// 元素出栈
pop := stack.Pop()
pop := stack.pop()
fmt.Print("出栈元素 pop = ", pop, ", 出栈后 stack = ")
PrintSlice(stack.toSlice())
// 获取栈的长度
size := stack.Size()
size := stack.size()
fmt.Println("栈的长度 size =", size)
// 判断是否为空
isEmpty := stack.IsEmpty()
isEmpty := stack.isEmpty()
fmt.Println("栈是否为空 =", isEmpty)
}
func TestLinkedListStack(t *testing.T) {
// 初始化栈
stack := NewLinkedListStack()
stack := newLinkedListStack()
// 元素入栈
stack.Push(1)
stack.Push(3)
stack.Push(2)
stack.Push(5)
stack.Push(4)
stack.push(1)
stack.push(3)
stack.push(2)
stack.push(5)
stack.push(4)
fmt.Print("栈 stack = ")
PrintList(stack.toList())
// 访问栈顶元素
peek := stack.Peek()
peek := stack.peek()
fmt.Println("栈顶元素 peek =", peek)
// 元素出栈
pop := stack.Pop()
pop := stack.pop()
fmt.Print("出栈元素 pop = ", pop, ", 出栈后 stack = ")
PrintList(stack.toList())
// 获取栈的长度
size := stack.Size()
size := stack.size()
fmt.Println("栈的长度 size =", size)
// 判断是否为空
isEmpty := stack.IsEmpty()
isEmpty := stack.isEmpty()
fmt.Println("栈是否为空 =", isEmpty)
}
// BenchmarkArrayStack 8 ns/op in Mac M1 Pro
func BenchmarkArrayStack(b *testing.B) {
stack := NewArrayStack()
stack := newArrayStack()
// use b.N for looping
for i := 0; i < b.N; i++ {
stack.Push(777)
stack.push(777)
}
for i := 0; i < b.N; i++ {
stack.Pop()
stack.pop()
}
}
// BenchmarkLinkedListStack 65.02 ns/op in Mac M1 Pro
func BenchmarkLinkedListStack(b *testing.B) {
stack := NewLinkedListStack()
stack := newLinkedListStack()
// use b.N for looping
for i := 0; i < b.N; i++ {
stack.Push(777)
stack.push(777)
}
for i := 0; i < b.N; i++ {
stack.Pop()
stack.pop()
}
}
+211
View File
@@ -0,0 +1,211 @@
// File: avl_tree.go
// Created Time: 2023-01-08
// Author: Reanon (793584285@qq.com)
package chapter_tree
import . "github.com/krahets/hello-algo/pkg"
/* AVL Tree*/
type avlTree struct {
// 根节点
root *TreeNode
}
func newAVLTree() *avlTree {
return &avlTree{root: nil}
}
/* 获取结点高度 */
func height(node *TreeNode) int {
// 空结点高度为 -1 ,叶结点高度为 0
if node != nil {
return node.Height
}
return -1
}
/* 更新结点高度 */
func updateHeight(node *TreeNode) {
lh := height(node.Left)
rh := height(node.Right)
// 结点高度等于最高子树高度 + 1
if lh > rh {
node.Height = lh + 1
} else {
node.Height = rh + 1
}
}
/* 获取平衡因子 */
func balanceFactor(node *TreeNode) int {
// 空结点平衡因子为 0
if node == nil {
return 0
}
// 结点平衡因子 = 左子树高度 - 右子树高度
return height(node.Left) - height(node.Right)
}
/* 右旋操作 */
func rightRotate(node *TreeNode) *TreeNode {
child := node.Left
grandChild := child.Right
// 以 child 为原点,将 node 向右旋转
child.Right = node
node.Left = grandChild
// 更新结点高度
updateHeight(node)
updateHeight(child)
// 返回旋转后子树的根节点
return child
}
/* 左旋操作 */
func leftRotate(node *TreeNode) *TreeNode {
child := node.Right
grandChild := child.Left
// 以 child 为原点,将 node 向左旋转
child.Left = node
node.Right = grandChild
// 更新结点高度
updateHeight(node)
updateHeight(child)
// 返回旋转后子树的根节点
return child
}
/* 执行旋转操作,使该子树重新恢复平衡 */
func rotate(node *TreeNode) *TreeNode {
// 获取结点 node 的平衡因子
// Go 推荐短变量,这里 bf 指代 balanceFactor
bf := balanceFactor(node)
// 左偏树
if bf > 1 {
if balanceFactor(node.Left) >= 0 {
// 右旋
return rightRotate(node)
} else {
// 先左旋后右旋
node.Left = leftRotate(node.Left)
return rightRotate(node)
}
}
// 右偏树
if bf < -1 {
if balanceFactor(node.Right) <= 0 {
// 左旋
return leftRotate(node)
} else {
// 先右旋后左旋
node.Right = rightRotate(node.Right)
return leftRotate(node)
}
}
// 平衡树,无需旋转,直接返回
return node
}
/* 插入结点 */
func (t *avlTree) insert(val int) *TreeNode {
t.root = insertHelper(t.root, val)
return t.root
}
/* 递归插入结点(辅助函数) */
func insertHelper(node *TreeNode, val int) *TreeNode {
if node == nil {
return NewTreeNode(val)
}
/* 1. 查找插入位置,并插入结点 */
if val < node.Val {
node.Left = insertHelper(node.Left, val)
} else if val > node.Val {
node.Right = insertHelper(node.Right, val)
} else {
// 重复结点不插入,直接返回
return node
}
// 更新结点高度
updateHeight(node)
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node)
// 返回子树的根节点
return node
}
/* 删除结点 */
func (t *avlTree) remove(val int) *TreeNode {
root := removeHelper(t.root, val)
return root
}
/* 递归删除结点(辅助函数) */
func removeHelper(node *TreeNode, val int) *TreeNode {
if node == nil {
return nil
}
/* 1. 查找结点,并删除之 */
if val < node.Val {
node.Left = removeHelper(node.Left, val)
} else if val > node.Val {
node.Right = removeHelper(node.Right, val)
} else {
if node.Left == nil || node.Right == nil {
child := node.Left
if node.Right != nil {
child = node.Right
}
// 子结点数量 = 0 ,直接删除 node 并返回
if child == nil {
return nil
} else {
// 子结点数量 = 1 ,直接删除 node
node = child
}
} else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
temp := getInOrderNext(node.Right)
node.Right = removeHelper(node.Right, temp.Val)
node.Val = temp.Val
}
}
// 更新结点高度
updateHeight(node)
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node)
// 返回子树的根节点
return node
}
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
func getInOrderNext(node *TreeNode) *TreeNode {
if node == nil {
return node
}
// 循环访问左子结点,直到叶结点时为最小结点,跳出
for node.Left != nil {
node = node.Left
}
return node
}
/* 查找结点 */
func (t *avlTree) search(val int) *TreeNode {
cur := t.root
// 循环查找,越过叶结点后跳出
for cur != nil {
// 目标结点在 root 的右子树中
if cur.Val < val {
cur = cur.Right
} else if cur.Val > val {
// 目标结点在 root 的左子树中
cur = cur.Left
} else {
// 找到目标结点,跳出循环
break
}
}
// 返回目标结点
return cur
}
+54
View File
@@ -0,0 +1,54 @@
// File: avl_tree_test.go
// Created Time: 2023-01-08
// Author: Reanon (793584285@qq.com)
package chapter_tree
import (
"fmt"
"testing"
. "github.com/krahets/hello-algo/pkg"
)
func TestAVLTree(t *testing.T) {
/* 初始化空 AVL 树 */
tree := newAVLTree()
/* 插入结点 */
// 请关注插入结点后,AVL 树是如何保持平衡的
testInsert(tree, 1)
testInsert(tree, 2)
testInsert(tree, 3)
testInsert(tree, 4)
testInsert(tree, 5)
testInsert(tree, 8)
testInsert(tree, 7)
testInsert(tree, 9)
testInsert(tree, 10)
testInsert(tree, 6)
/* 插入重复结点 */
testInsert(tree, 7)
/* 删除结点 */
// 请关注删除结点后,AVL 树是如何保持平衡的
testRemove(tree, 8) // 删除度为 0 的结点
testRemove(tree, 5) // 删除度为 1 的结点
testRemove(tree, 4) // 删除度为 2 的结点
/* 查询结点 */
node := tree.search(7)
fmt.Printf("\n查找到的结点对象为 %#v ,结点值 = %d \n", node, node.Val)
}
func testInsert(tree *avlTree, val int) {
tree.insert(val)
fmt.Printf("\n插入结点 %d 后,AVL 树为 \n", val)
PrintTree(tree.root)
}
func testRemove(tree *avlTree, val int) {
tree.remove(val)
fmt.Printf("\n删除结点 %d 后,AVL 树为 \n", val)
PrintTree(tree.root)
}
+12 -12
View File
@@ -10,26 +10,26 @@ import (
. "github.com/krahets/hello-algo/pkg"
)
type BinarySearchTree struct {
type binarySearchTree struct {
root *TreeNode
}
func NewBinarySearchTree(nums []int) *BinarySearchTree {
func newBinarySearchTree(nums []int) *binarySearchTree {
// sorting array
sort.Ints(nums)
root := buildBinarySearchTree(nums, 0, len(nums)-1)
return &BinarySearchTree{
return &binarySearchTree{
root: root,
}
}
/* 获取根结点 */
func (bst *BinarySearchTree) GetRoot() *TreeNode {
func (bst *binarySearchTree) getRoot() *TreeNode {
return bst.root
}
/* 获取中序遍历的下一个结点 */
func (bst *BinarySearchTree) GetInOrderNext(node *TreeNode) *TreeNode {
func (bst *binarySearchTree) getInOrderNext(node *TreeNode) *TreeNode {
if node == nil {
return node
}
@@ -41,7 +41,7 @@ func (bst *BinarySearchTree) GetInOrderNext(node *TreeNode) *TreeNode {
}
/* 查找结点 */
func (bst *BinarySearchTree) Search(num int) *TreeNode {
func (bst *binarySearchTree) search(num int) *TreeNode {
node := bst.root
// 循环查找,越过叶结点后跳出
for node != nil {
@@ -61,7 +61,7 @@ func (bst *BinarySearchTree) Search(num int) *TreeNode {
}
/* 插入结点 */
func (bst *BinarySearchTree) Insert(num int) *TreeNode {
func (bst *binarySearchTree) insert(num int) *TreeNode {
cur := bst.root
// 若树为空,直接提前返回
if cur == nil {
@@ -92,7 +92,7 @@ func (bst *BinarySearchTree) Insert(num int) *TreeNode {
}
/* 删除结点 */
func (bst *BinarySearchTree) Remove(num int) *TreeNode {
func (bst *binarySearchTree) remove(num int) *TreeNode {
cur := bst.root
// 若树为空,直接提前返回
if cur == nil {
@@ -136,10 +136,10 @@ func (bst *BinarySearchTree) Remove(num int) *TreeNode {
// 子结点数为 2
} else {
// 获取中序遍历中待删除结点 cur 的下一个结点
next := bst.GetInOrderNext(cur)
next := bst.getInOrderNext(cur)
temp := next.Val
// 递归删除结点 next
bst.Remove(next.Val)
bst.remove(next.Val)
// 将 next 的值复制给 cur
cur.Val = temp
}
@@ -160,7 +160,7 @@ func buildBinarySearchTree(nums []int, left, right int) *TreeNode {
return root
}
// Print binary search tree
func (bst *BinarySearchTree) Print() {
// print binary search tree
func (bst *binarySearchTree) print() {
PrintTree(bst.root)
}
@@ -11,31 +11,31 @@ import (
func TestBinarySearchTree(t *testing.T) {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
bst := NewBinarySearchTree(nums)
bst := newBinarySearchTree(nums)
fmt.Println("\n初始化的二叉树为:")
bst.Print()
bst.print()
// 获取根结点
node := bst.GetRoot()
node := bst.getRoot()
fmt.Println("\n二叉树的根结点为:", node.Val)
// 查找结点
node = bst.Search(5)
node = bst.search(5)
fmt.Println("\n查找到的结点对象为", node, ",结点值 =", node.Val)
// 插入结点
node = bst.Insert(16)
node = bst.insert(16)
fmt.Println("\n插入结点后 16 的二叉树为:")
bst.Print()
bst.print()
// 删除结点
bst.Remove(1)
bst.remove(1)
fmt.Println("\n删除结点 1 后的二叉树为:")
bst.Print()
bst.Remove(2)
bst.print()
bst.remove(2)
fmt.Println("\n删除结点 2 后的二叉树为:")
bst.Print()
bst.Remove(4)
bst.print()
bst.remove(4)
fmt.Println("\n删除结点 4 后的二叉树为:")
bst.Print()
bst.print()
}
@@ -14,11 +14,11 @@ import (
func TestLevelOrder(t *testing.T) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
root := ArrayToTree([]int{1, 2, 3, 4, 5, 6, 7})
fmt.Println("初始化二叉树: ")
root := ArrToTree([]any{1, 2, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树: ")
PrintTree(root)
// 层序遍历
nums := levelOrder(root)
fmt.Println("层序遍历的结点打印序列 =", nums)
fmt.Println("\n层序遍历的结点打印序列 =", nums)
}
@@ -14,22 +14,22 @@ import (
func TestPreInPostOrderTraversal(t *testing.T) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
root := ArrayToTree([]int{1, 2, 3, 4, 5, 6, 7})
fmt.Println("初始化二叉树: ")
root := ArrToTree([]any{1, 2, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树: ")
PrintTree(root)
// 前序遍历
nums = nil
preOrder(root)
fmt.Println("前序遍历的结点打印序列 =", nums)
fmt.Println("\n前序遍历的结点打印序列 =", nums)
// 中序遍历
nums = nil
inOrder(root)
fmt.Println("中序遍历的结点打印序列 =", nums)
fmt.Println("\n中序遍历的结点打印序列 =", nums)
// 后序遍历
nums = nil
postOrder(root)
fmt.Println("后序遍历的结点打印序列 =", nums)
fmt.Println("\n后序遍历的结点打印序列 =", nums)
}
+2 -2
View File
@@ -76,7 +76,7 @@ func printTreeHelper(root *TreeNode, prev *trunk, isLeft bool) {
printTreeHelper(root.Left, trunk, false)
}
// trunk Help to Print tree structure
// trunk Help to print tree structure
type trunk struct {
prev *trunk
str string
@@ -103,4 +103,4 @@ func PrintMap[K comparable, V any](m map[K]V) {
for key, value := range m {
fmt.Println(key, "->", value)
}
}
}
+23 -16
View File
@@ -9,41 +9,48 @@ import (
)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
Val int // 结点值
Height int // 结点高度
Left *TreeNode // 左子结点引用
Right *TreeNode // 右子结点引用
}
func NewTreeNode(v int) *TreeNode {
return &TreeNode{
Left: nil,
Right: nil,
Val: v,
Val: v,
Height: 0,
Left: nil,
Right: nil,
}
}
// ArrayToTree Generate a binary tree with an array
func ArrayToTree(arr []int) *TreeNode {
// ArrToTree Generate a binary tree given an array
func ArrToTree(arr []any) *TreeNode {
if len(arr) <= 0 {
return nil
}
root := NewTreeNode(arr[0])
// TreeNode only accept integer value for now.
root := NewTreeNode(arr[0].(int))
// Let container.list as queue
queue := list.New()
queue.PushBack(root)
i := 1
i := 0
for queue.Len() > 0 {
// poll
node := queue.Remove(queue.Front()).(*TreeNode)
i++
if i < len(arr) {
node.Left = NewTreeNode(arr[i])
queue.PushBack(node.Left)
i++
if arr[i] != nil {
node.Left = NewTreeNode(arr[i].(int))
queue.PushBack(node.Left)
}
}
i++
if i < len(arr) {
node.Right = NewTreeNode(arr[i])
queue.PushBack(node.Right)
i++
if arr[i] != nil {
node.Right = NewTreeNode(arr[i].(int))
queue.PushBack(node.Right)
}
}
}
return root
+2 -2
View File
@@ -10,8 +10,8 @@ import (
)
func TestTreeNode(t *testing.T) {
arr := []int{2, 3, 5, 6, 7}
node := ArrayToTree(arr)
arr := []any{1, 2, 3, nil, 5, 6, nil}
node := ArrToTree(arr)
// print tree
PrintTree(node)
+1 -2
View File
@@ -30,8 +30,7 @@ public class binary_tree_bfs {
public static void main(String[] args) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode root = TreeNode.arrToTree(new Integer[] {
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null });
TreeNode root = TreeNode.arrToTree(new Integer[] { 1, 2, 3, 4, 5, 6, 7 });
System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(root);
+1 -2
View File
@@ -43,8 +43,7 @@ public class binary_tree_dfs {
public static void main(String[] args) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode root = TreeNode.arrToTree(new Integer[] {
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
TreeNode root = TreeNode.arrToTree(new Integer[] { 1, 2, 3, 4, 5, 6, 7 });
System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(root);
+8
View File
@@ -8,6 +8,7 @@ package include;
import java.util.*;
class Trunk {
Trunk prev;
String str;
@@ -103,4 +104,11 @@ public class PrintUtil {
System.out.println(kv.getKey() + " -> " + kv.getValue());
}
}
public static void printHeap(PriorityQueue<Integer> queue) {
Integer[] nums = (Integer[])queue.toArray();
TreeNode root = TreeNode.arrToTree(nums);
printTree(root);
}
}
+4 -20
View File
@@ -22,7 +22,7 @@ public class TreeNode {
}
/**
* Generate a binary tree with an array
* Generate a binary tree given an array
* @param arr
* @return
*/
@@ -32,19 +32,19 @@ public class TreeNode {
TreeNode root = new TreeNode(arr[0]);
Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
int i = 1;
int i = 0;
while(!queue.isEmpty()) {
TreeNode node = queue.poll();
if (++i >= arr.length) break;
if(arr[i] != null) {
node.left = new TreeNode(arr[i]);
queue.add(node.left);
}
i++;
if (++i >= arr.length) break;
if(arr[i] != null) {
node.right = new TreeNode(arr[i]);
queue.add(node.right);
}
i++;
}
return root;
}
@@ -71,20 +71,4 @@ public class TreeNode {
}
return list;
}
/**
* Get a tree node with specific value in a binary tree
* @param root
* @param val
* @return
*/
public static TreeNode getTreeNode(TreeNode root, int val) {
if (root == null)
return null;
if (root.val == val)
return root;
TreeNode left = getTreeNode(root.left, val);
TreeNode right = getTreeNode(root.right, val);
return left != null ? left : right;
}
}
@@ -28,10 +28,10 @@ function hierOrder(root) {
/* Driver Code */
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]);
var root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log("\n初始化二叉树\n");
printTree(root);
/* 层序遍历 */
let list = hierOrder(root);
console.log("\n层序遍历的结点打印序列 = " + list);
console.log("\n层序遍历的结点打印序列 = " + list);
@@ -40,7 +40,7 @@ function postOrder(root) {
/* Driver Code */
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]);
var root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log("\n初始化二叉树\n");
printTree(root);
@@ -58,4 +58,3 @@ console.log("\n中序遍历的结点打印序列 = " + list);
list.length = 0;
postOrder(root);
console.log("\n后序遍历的结点打印序列 = " + list);
+8 -7
View File
@@ -14,7 +14,7 @@ function TreeNode(val, left, right) {
}
/**
* Generate a binary tree with an array
* Generate a binary tree given an array
* @param arr
* @return
*/
@@ -24,20 +24,21 @@ function arrToTree(arr) {
let root = new TreeNode(arr[0]);
let queue = [root]
let i = 1;
while(queue.length) {
let i = 0;
while (queue.length) {
let node = queue.shift();
if(arr[i] !== null) {
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.left = new TreeNode(arr[i]);
queue.push(node.left);
}
i++;
if(arr[i] !== null) {
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.right = new TreeNode(arr[i]);
queue.push(node.right);
}
i++;
}
return root;
}
+10 -12
View File
@@ -5,30 +5,28 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
class AVLTree:
def __init__(self, root: typing.Optional[TreeNode] = None):
def __init__(self, root: Optional[TreeNode] = None):
self.root = root
""" 获取结点高度 """
def height(self, node: typing.Optional[TreeNode]) -> int:
def height(self, node: Optional[TreeNode]) -> int:
# 空结点高度为 -1 ,叶结点高度为 0
if node is not None:
return node.height
return -1
""" 更新结点高度 """
def __update_height(self, node: TreeNode):
def __update_height(self, node: Optional[TreeNode]):
# 结点高度等于最高子树高度 + 1
node.height = max([self.height(node.left), self.height(node.right)]) + 1
""" 获取平衡因子 """
def balance_factor(self, node: TreeNode) -> int:
def balance_factor(self, node: Optional[TreeNode]) -> int:
# 空结点平衡因子为 0
if node is None:
return 0
@@ -36,7 +34,7 @@ class AVLTree:
return self.height(node.left) - self.height(node.right)
""" 右旋操作 """
def __right_rotate(self, node: TreeNode) -> TreeNode:
def __right_rotate(self, node: Optional[TreeNode]) -> TreeNode:
child = node.left
grand_child = child.right
# 以 child 为原点,将 node 向右旋转
@@ -49,7 +47,7 @@ class AVLTree:
return child
""" 左旋操作 """
def __left_rotate(self, node: TreeNode) -> TreeNode:
def __left_rotate(self, node: Optional[TreeNode]) -> TreeNode:
child = node.right
grand_child = child.left
# 以 child 为原点,将 node 向左旋转
@@ -62,7 +60,7 @@ class AVLTree:
return child
""" 执行旋转操作,使该子树重新恢复平衡 """
def __rotate(self, node: TreeNode) -> TreeNode:
def __rotate(self, node: Optional[TreeNode]) -> TreeNode:
# 获取结点 node 的平衡因子
balance_factor = self.balance_factor(node)
# 左偏树
@@ -92,7 +90,7 @@ class AVLTree:
return self.root
""" 递归插入结点(辅助函数)"""
def __insert_helper(self, node: typing.Optional[TreeNode], val: int) -> TreeNode:
def __insert_helper(self, node: Optional[TreeNode], val: int) -> TreeNode:
if node is None:
return TreeNode(val)
# 1. 查找插入位置,并插入结点
@@ -114,7 +112,7 @@ class AVLTree:
return root
""" 递归删除结点(辅助函数) """
def __remove_helper(self, node: typing.Optional[TreeNode], val: int) -> typing.Optional[TreeNode]:
def __remove_helper(self, node: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if node is None:
return None
# 1. 查找结点,并删除之
@@ -141,7 +139,7 @@ class AVLTree:
return self.__rotate(node)
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def __get_inorder_next(self, node: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
def __get_inorder_next(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
if node is None:
return None
# 循环访问左子结点,直到叶结点时为最小结点,跳出
@@ -5,20 +5,18 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
""" 二叉搜索树 """
class BinarySearchTree:
def __init__(self, nums: typing.List[int]) -> None:
def __init__(self, nums: List[int]) -> None:
nums.sort()
self.__root = self.build_tree(nums, 0, len(nums) - 1)
""" 构建二叉搜索树 """
def build_tree(self, nums: typing.List[int], start_index: int, end_index: int) -> typing.Optional[TreeNode]:
def build_tree(self, nums: List[int], start_index: int, end_index: int) -> Optional[TreeNode]:
if start_index > end_index:
return None
@@ -31,11 +29,11 @@ class BinarySearchTree:
return root
@property
def root(self) -> typing.Optional[TreeNode]:
def root(self) -> Optional[TreeNode]:
return self.__root
""" 查找结点 """
def search(self, num: int) -> typing.Optional[TreeNode]:
def search(self, num: int) -> Optional[TreeNode]:
cur = self.root
# 循环查找,越过叶结点后跳出
while cur is not None:
@@ -51,7 +49,7 @@ class BinarySearchTree:
return cur
""" 插入结点 """
def insert(self, num: int) -> typing.Optional[TreeNode]:
def insert(self, num: int) -> Optional[TreeNode]:
root = self.root
# 若树为空,直接提前返回
if root is None:
@@ -81,7 +79,7 @@ class BinarySearchTree:
return node
""" 删除结点 """
def remove(self, num: int) -> typing.Optional[TreeNode]:
def remove(self, num: int) -> Optional[TreeNode]:
root = self.root
# 若树为空,直接提前返回
if root is None:
@@ -126,7 +124,7 @@ class BinarySearchTree:
return cur
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def get_inorder_next(self, root: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
def get_inorder_next(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return root
# 循环访问左子结点,直到叶结点时为最小结点,跳出
@@ -138,7 +136,7 @@ class BinarySearchTree:
""" Driver Code """
if __name__ == "__main__":
# 初始化二叉搜索树
nums = list(range(1, 16))
nums = list(range(1, 16)) # [1, 2, ..., 15]
bst = BinarySearchTree(nums=nums)
print("\n初始化的二叉树为\n")
print_tree(bst.root)
+1 -1
View File
@@ -36,5 +36,5 @@ if __name__ == "__main__":
print_tree(n1)
# 删除结点
n1.left = n2
print("\n删除结点 P 后\n");
print("\n删除结点 P 后\n")
print_tree(n1)
+2 -4
View File
@@ -5,14 +5,12 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
""" 层序遍历 """
def hier_order(root: TreeNode):
def hier_order(root: Optional[TreeNode]):
# 初始化队列,加入根结点
queue = collections.deque()
queue.append(root)
@@ -32,7 +30,7 @@ def hier_order(root: TreeNode):
if __name__ == "__main__":
# 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7, None, None, None, None, None, None, None, None])
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n")
print_tree(root)
+4 -6
View File
@@ -5,8 +5,6 @@ Author: a16su (lpluls001@gmail.com)
"""
import sys, os.path as osp
import typing
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from include import *
@@ -14,7 +12,7 @@ from include import *
res = []
""" 前序遍历 """
def pre_order(root: typing.Optional[TreeNode]):
def pre_order(root: Optional[TreeNode]):
if root is None:
return
# 访问优先级:根结点 -> 左子树 -> 右子树
@@ -23,7 +21,7 @@ def pre_order(root: typing.Optional[TreeNode]):
pre_order(root=root.right)
""" 中序遍历 """
def in_order(root: typing.Optional[TreeNode]):
def in_order(root: Optional[TreeNode]):
if root is None:
return
# 访问优先级:左子树 -> 根结点 -> 右子树
@@ -32,7 +30,7 @@ def in_order(root: typing.Optional[TreeNode]):
in_order(root=root.right)
""" 后序遍历 """
def post_order(root: typing.Optional[TreeNode]):
def post_order(root: Optional[TreeNode]):
if root is None:
return
# 访问优先级:左子树 -> 右子树 -> 根结点
@@ -45,7 +43,7 @@ def post_order(root: typing.Optional[TreeNode]):
if __name__ == "__main__":
# 初始化二叉树
# 这里借助了一个从数组直接生成二叉树的函数
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7, None, None, None, None, None, None, None, None])
root = list_to_tree(arr=[1, 2, 3, 4, 5, 6, 7])
print("\n初始化二叉树\n")
print_tree(root)
+1 -1
View File
@@ -4,7 +4,7 @@ import queue
import random
import functools
import collections
from typing import List
from typing import Optional, List, Dict, DefaultDict, OrderedDict, Set, Deque
from .linked_list import ListNode, list_to_linked_list, linked_list_to_list, get_list_node
from .binary_tree import TreeNode, list_to_tree, tree_to_list, get_tree_node
from .print_util import print_matrix, print_linked_list, print_tree, print_dict
+10 -26
View File
@@ -26,39 +26,30 @@ class TreeNode:
def list_to_tree(arr):
"""Generate a binary tree with a list
Args:
arr ([type]): [description]
Returns:
[type]: [description]
"""
if not arr:
return None
i = 1
root = TreeNode(int(arr[0]))
queue = collections.deque()
queue.append(root)
i = 0
root = TreeNode(arr[0])
queue = collections.deque([root])
while queue:
node = queue.popleft()
i += 1
if i >= len(arr): break
if arr[i] != None:
node.left = TreeNode(int(arr[i]))
node.left = TreeNode(arr[i])
queue.append(node.left)
i += 1
if i >= len(arr): break
if arr[i] != None:
node.right = TreeNode(int(arr[i]))
node.right = TreeNode(arr[i])
queue.append(node.right)
i += 1
return root
def tree_to_list(root):
"""Serialize a tree into an array
Args:
root ([type]): [description]
Returns:
[type]: [description]
"""
if not root: return []
queue = collections.deque()
@@ -75,13 +66,6 @@ def tree_to_list(root):
def get_tree_node(root, val):
"""Get a tree node with specific value in a binary tree
Args:
root ([type]): [description]
val ([type]): [description]
Returns:
[type]: [description]
"""
if not root:
return
+4
View File
@@ -9,6 +9,8 @@ let package = Package(
.executable(name: "worst_best_time_complexity", targets: ["worst_best_time_complexity"]),
.executable(name: "space_complexity", targets: ["space_complexity"]),
.executable(name: "leetcode_two_sum", targets: ["leetcode_two_sum"]),
.executable(name: "array", targets: ["array"]),
.executable(name: "linked_list", targets: ["linked_list"]),
],
targets: [
.target(name: "utils", path: "utils"),
@@ -16,5 +18,7 @@ let package = Package(
.executableTarget(name: "worst_best_time_complexity", path: "chapter_computational_complexity", sources: ["worst_best_time_complexity.swift"]),
.executableTarget(name: "space_complexity", dependencies: ["utils"], path: "chapter_computational_complexity", sources: ["space_complexity.swift"]),
.executableTarget(name: "leetcode_two_sum", path: "chapter_computational_complexity", sources: ["leetcode_two_sum.swift"]),
.executableTarget(name: "array", path: "chapter_array_and_linkedlist", sources: ["array.swift"]),
.executableTarget(name: "linked_list", dependencies: ["utils"], path: "chapter_array_and_linkedlist", sources: ["linked_list.swift"]),
]
)
@@ -0,0 +1,103 @@
/**
* File: array.swift
* Created Time: 2023-01-05
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func randomAccess(nums: [Int]) -> Int {
// [0, nums.count)
let randomIndex = nums.indices.randomElement()!
//
let randomNum = nums[randomIndex]
return randomNum
}
/* */
func extend(nums: [Int], enlarge: Int) -> [Int] {
//
var res = Array(repeating: 0, count: nums.count + enlarge)
//
for i in nums.indices {
res[i] = nums[i]
}
//
return res
}
/* index num */
func insert(nums: inout [Int], num: Int, index: Int) {
// index
for i in sequence(first: nums.count - 1, next: { $0 > index + 1 ? $0 - 1 : nil }) {
nums[i] = nums[i - 1]
}
// num index
nums[index] = num
}
/* index */
func remove(nums: inout [Int], index: Int) {
let count = nums.count
// index
for i in sequence(first: index, next: { $0 < count - 1 - 1 ? $0 + 1 : nil }) {
nums[i] = nums[i + 1]
}
}
/* */
func traverse(nums: [Int]) {
var count = 0
//
for _ in nums.indices {
count += 1
}
//
for _ in nums {
count += 1
}
}
/* */
func find(nums: [Int], target: Int) -> Int {
for i in nums.indices {
if nums[i] == target {
return i
}
}
return -1
}
@main
enum _Array {
/* Driver Code */
static func main() {
/* */
let arr = Array(repeating: 0, count: 5)
print("数组 arr = \(arr)")
var nums = [1, 3, 2, 5, 4]
print("数组 nums = \(nums)")
/* 访 */
let randomNum = randomAccess(nums: nums)
print("在 nums 中获取随机元素 \(randomNum)")
/* */
nums = extend(nums: nums, enlarge: 3)
print("将数组长度扩展至 8 ,得到 nums = \(nums)")
/* */
insert(nums: &nums, num: 6, index: 3)
print("在索引 3 处插入数字 6 ,得到 nums = \(nums)")
/* */
remove(nums: &nums, index: 2)
print("删除索引 2 处的元素,得到 nums = \(nums)")
/* */
traverse(nums: nums)
/* */
let index = find(nums: nums, target: 3)
print("在 nums 中查找元素 3 ,得到索引 = \(index)")
}
}
@@ -0,0 +1,91 @@
/**
* File: linked_list.swift
* Created Time: 2023-01-08
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* n0 P */
func insert(n0: ListNode, P: ListNode) {
let n1 = n0.next
n0.next = P
P.next = n1
}
/* n0 */
func remove(n0: ListNode) {
if n0.next == nil {
return
}
// n0 -> P -> n1
let P = n0.next
let n1 = P?.next
n0.next = n1
P?.next = nil
}
/* 访 index */
func access(head: ListNode, index: Int) -> ListNode? {
var head: ListNode? = head
for _ in 0 ..< index {
head = head?.next
if head == nil {
return nil
}
}
return head
}
/* target */
func find(head: ListNode, target: Int) -> Int {
var head: ListNode? = head
var index = 0
while head != nil {
if head?.val == target {
return index
}
head = head?.next
index += 1
}
return -1
}
@main
enum LinkedList {
/* Driver Code */
static func main() {
/* */
//
let n0 = ListNode(x: 1)
let n1 = ListNode(x: 3)
let n2 = ListNode(x: 2)
let n3 = ListNode(x: 5)
let n4 = ListNode(x: 4)
//
n0.next = n1
n1.next = n2
n2.next = n3
n3.next = n4
print("初始化的链表为")
PrintUtil.printLinkedList(head: n0)
/* */
insert(n0: n0, P: ListNode(x: 0))
print("插入结点后的链表为")
PrintUtil.printLinkedList(head: n0)
/* */
remove(n0: n0)
print("删除结点后的链表为")
PrintUtil.printLinkedList(head: n0)
/* 访 */
let node = access(head: n0, index: 3)
print("链表中索引 3 处的结点的值 = \(node!.val)")
/* */
let index = find(head: n0, target: 2)
print("链表中值为 2 的结点的索引 = \(index)")
}
}
@@ -6,14 +6,14 @@
import utils
//
/* */
@discardableResult
func function() -> Int {
// do something
return 0
}
//
/* */
func constant(n: Int) {
// O(1)
let a = 0
@@ -30,7 +30,7 @@ func constant(n: Int) {
}
}
// 线
/* 线 */
func linear(n: Int) {
// n O(n)
let nums = Array(repeating: 0, count: n)
@@ -40,7 +40,7 @@ func linear(n: Int) {
let map = Dictionary(uniqueKeysWithValues: (0 ..< n).map { ($0, "\($0)") })
}
// 线
/* 线 */
func linearRecur(n: Int) {
print("递归 n = \(n)")
if n == 1 {
@@ -49,13 +49,13 @@ func linearRecur(n: Int) {
linearRecur(n: n - 1)
}
//
/* */
func quadratic(n: Int) {
// O(n^2)
let numList = Array(repeating: Array(repeating: 0, count: n), count: n)
}
//
/* */
@discardableResult
func quadraticRecur(n: Int) -> Int {
if n <= 0 {
@@ -67,7 +67,7 @@ func quadraticRecur(n: Int) -> Int {
return quadraticRecur(n: n - 1)
}
//
/* */
func buildTree(n: Int) -> TreeNode? {
if n == 0 {
return nil
@@ -80,7 +80,7 @@ func buildTree(n: Int) -> TreeNode? {
@main
enum SpaceComplexity {
// Driver Code
/* Driver Code */
static func main() {
let n = 5
//
@@ -4,7 +4,7 @@
* Author: nuomi1 (nuomi1@qq.com)
*/
//
/* */
func constant(n: Int) -> Int {
var count = 0
let size = 100_000
@@ -14,7 +14,7 @@ func constant(n: Int) -> Int {
return count
}
// 线
/* 线 */
func linear(n: Int) -> Int {
var count = 0
for _ in 0 ..< n {
@@ -23,7 +23,7 @@ func linear(n: Int) -> Int {
return count
}
// 线
/* 线 */
func arrayTraversal(nums: [Int]) -> Int {
var count = 0
//
@@ -33,7 +33,7 @@ func arrayTraversal(nums: [Int]) -> Int {
return count
}
//
/* */
func quadratic(n: Int) -> Int {
var count = 0
//
@@ -45,7 +45,7 @@ func quadratic(n: Int) -> Int {
return count
}
//
/* */
func bubbleSort(nums: inout [Int]) -> Int {
var count = 0 //
// n-1, n-2, ..., 1
@@ -64,7 +64,7 @@ func bubbleSort(nums: inout [Int]) -> Int {
return count
}
//
/* */
func exponential(n: Int) -> Int {
var count = 0
var base = 1
@@ -79,7 +79,7 @@ func exponential(n: Int) -> Int {
return count
}
//
/* */
func expRecur(n: Int) -> Int {
if n == 1 {
return 1
@@ -87,7 +87,7 @@ func expRecur(n: Int) -> Int {
return expRecur(n: n - 1) + expRecur(n: n - 1) + 1
}
//
/* */
func logarithmic(n: Int) -> Int {
var count = 0
var n = n
@@ -98,7 +98,7 @@ func logarithmic(n: Int) -> Int {
return count
}
//
/* */
func logRecur(n: Int) -> Int {
if n <= 1 {
return 0
@@ -106,7 +106,7 @@ func logRecur(n: Int) -> Int {
return logRecur(n: n / 2) + 1
}
// 线
/* 线 */
func linearLogRecur(n: Double) -> Int {
if n <= 1 {
return 1
@@ -118,7 +118,7 @@ func linearLogRecur(n: Double) -> Int {
return count
}
//
/* */
func factorialRecur(n: Int) -> Int {
if n == 0 {
return 1
@@ -133,39 +133,40 @@ func factorialRecur(n: Int) -> Int {
@main
enum TimeComplexity {
/* Driver Code */
static func main() {
// n
let n = 8
print("输入数据大小 n =", n)
print("输入数据大小 n = \(n)")
var count = constant(n: n)
print("常数阶的计算操作数量 =", count)
print("常数阶的计算操作数量 = \(count)")
count = linear(n: n)
print("线性阶的计算操作数量 =", count)
print("线性阶的计算操作数量 = \(count)")
count = arrayTraversal(nums: Array(repeating: 0, count: n))
print("线性阶(遍历数组)的计算操作数量 =", count)
print("线性阶(遍历数组)的计算操作数量 = \(count)")
count = quadratic(n: n)
print("平方阶的计算操作数量 =", count)
print("平方阶的计算操作数量 = \(count)")
var nums = Array(sequence(first: n, next: { $0 > 0 ? $0 - 1 : nil })) // [n,n-1,...,2,1]
count = bubbleSort(nums: &nums)
print("平方阶(冒泡排序)的计算操作数量 =", count)
print("平方阶(冒泡排序)的计算操作数量 = \(count)")
count = exponential(n: n)
print("指数阶(循环实现)的计算操作数量 =", count)
print("指数阶(循环实现)的计算操作数量 = \(count)")
count = expRecur(n: n)
print("指数阶(递归实现)的计算操作数量 =", count)
print("指数阶(递归实现)的计算操作数量 = \(count)")
count = logarithmic(n: n)
print("对数阶(循环实现)的计算操作数量 =", count)
print("对数阶(循环实现)的计算操作数量 = \(count)")
count = logRecur(n: n)
print("对数阶(递归实现)的计算操作数量 =", count)
print("对数阶(递归实现)的计算操作数量 = \(count)")
count = linearLogRecur(n: Double(n))
print("线性对数阶(递归实现)的计算操作数量 =", count)
print("线性对数阶(递归实现)的计算操作数量 = \(count)")
count = factorialRecur(n: n)
print("阶乘阶(递归实现)的计算操作数量 =", count)
print("阶乘阶(递归实现)的计算操作数量 = \(count)")
}
}
@@ -4,7 +4,7 @@
* Author: nuomi1 (nuomi1@qq.com)
*/
// { 1, 2, ..., n }
/* { 1, 2, ..., n } */
func randomNumbers(n: Int) -> [Int] {
// nums = { 1, 2, 3, ..., n }
var nums = Array(1 ... n)
@@ -13,7 +13,7 @@ func randomNumbers(n: Int) -> [Int] {
return nums
}
// nums 1
/* nums 1 */
func findOne(nums: [Int]) -> Int {
for i in nums.indices {
if nums[i] == 1 {
@@ -25,14 +25,14 @@ func findOne(nums: [Int]) -> Int {
@main
enum WorstBestTimeComplexity {
// Driver Code
/* Driver Code */
static func main() {
for _ in 0 ..< 10 {
let n = 100
let nums = randomNumbers(n: n)
let index = findOne(nums: nums)
print("数组 [ 1, 2, ..., n ] 被打乱后 =", nums)
print("数字 1 的索引为", index)
print("数组 [ 1, 2, ..., n ] 被打乱后 = \(nums)")
print("数字 1 的索引为 \(index)")
}
}
}
+10
View File
@@ -15,6 +15,16 @@ public enum PrintUtil {
}
}
public static func printLinkedList(head: ListNode) {
var head: ListNode? = head
var list: [String] = []
while head != nil {
list.append("\(head!.val)")
head = head?.next
}
print(list.joined(separator: " -> "))
}
public static func printTree(root: TreeNode?) {
printTree(root: root, prev: nil, isLeft: false)
}
@@ -30,7 +30,7 @@ function hierOrder(root: TreeNode | null): number[] {
/* Driver Code */
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]);
var root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log('\n初始化二叉树\n');
printTree(root);
@@ -47,7 +47,7 @@ function postOrder(root: TreeNode | null): void {
/* Driver Code */
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
const root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]);
const root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log('\n初始化二叉树\n');
printTree(root);
+4 -4
View File
@@ -20,7 +20,7 @@ class TreeNode {
}
/**
* Generate a binary tree with an array
* Generate a binary tree given an array
* @param arr
* @return
*/
@@ -31,19 +31,19 @@ function arrToTree(arr: (number | null)[]): TreeNode | null {
const root = new TreeNode(arr[0] as number);
const queue = [root];
let i = 1;
let i = 0;
while (queue.length) {
let node = queue.shift() as TreeNode;
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.left = new TreeNode(arr[i] as number);
queue.push(node.left);
}
i++;
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.right = new TreeNode(arr[i] as number);
queue.push(node.right);
}
i++;
}
return root;
}
+2
View File
@@ -0,0 +1,2 @@
zig-cache/
zig-out/
+46
View File
@@ -0,0 +1,46 @@
const std = @import("std");
// zig version 0.10.0
pub fn build(b: *std.build.Builder) void {
const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions();
// "chapter_computational_complexity/time_complexity.zig"
// Run Command: zig build run_time_complexity
const exe_time_complexity = b.addExecutable("time_complexity", "chapter_computational_complexity/time_complexity.zig");
exe_time_complexity.addPackagePath("include", "include/include.zig");
exe_time_complexity.setTarget(target);
exe_time_complexity.setBuildMode(mode);
exe_time_complexity.install();
const run_cmd_time_complexity = exe_time_complexity.run();
run_cmd_time_complexity.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_time_complexity.addArgs(args);
const run_step_time_complexity = b.step("run_time_complexity", "Run time_complexity");
run_step_time_complexity.dependOn(&run_cmd_time_complexity.step);
// "chapter_computational_complexity/worst_best_time_complexity.zig"
// Run Command: zig build run_worst_best_time_complexity
const exe_worst_best_time_complexity = b.addExecutable("worst_best_time_complexity", "chapter_computational_complexity/worst_best_time_complexity.zig");
exe_worst_best_time_complexity.addPackagePath("include", "include/include.zig");
exe_worst_best_time_complexity.setTarget(target);
exe_worst_best_time_complexity.setBuildMode(mode);
exe_worst_best_time_complexity.install();
const run_cmd_worst_best_time_complexity = exe_worst_best_time_complexity.run();
run_cmd_worst_best_time_complexity.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_worst_best_time_complexity.addArgs(args);
const run_step_worst_best_time_complexity = b.step("run_worst_best_time_complexity", "Run worst_best_time_complexity");
run_step_worst_best_time_complexity.dependOn(&run_cmd_worst_best_time_complexity.step);
// "chapter_computational_complexity/leetcode_two_sum.zig"
// Run Command: zig build run_leetcode_two_sum
const exe_leetcode_two_sum = b.addExecutable("leetcode_two_sum", "chapter_computational_complexity/leetcode_two_sum.zig");
exe_leetcode_two_sum.addPackagePath("include", "include/include.zig");
exe_leetcode_two_sum.setTarget(target);
exe_leetcode_two_sum.setBuildMode(mode);
exe_leetcode_two_sum.install();
const run_cmd_leetcode_two_sum = exe_leetcode_two_sum.run();
run_cmd_leetcode_two_sum.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_leetcode_two_sum.addArgs(args);
const run_step_leetcode_two_sum = b.step("run_leetcode_two_sum", "Run leetcode_two_sum");
run_step_leetcode_two_sum.dependOn(&run_cmd_leetcode_two_sum.step);
}
@@ -0,0 +1,61 @@
// File: leetcode_two_sum.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
const SolutionBruteForce = struct {
pub fn twoSum(self: *SolutionBruteForce, nums: []i32, target: i32) [2]i32 {
_ = self;
var size: usize = nums.len;
var i: usize = 0;
// 两层循环,时间复杂度 O(n^2)
while (i < size - 1) : (i += 1) {
var j = i + 1;
while (j < size) : (j += 1) {
if (nums[i] + nums[j] == target) {
return [_]i32{@intCast(i32, i), @intCast(i32, j)};
}
}
}
return undefined;
}
};
const SolutionHashMap = struct {
pub fn twoSum(self: *SolutionHashMap, nums: []i32, target: i32) ![2]i32 {
_ = self;
var size: usize = nums.len;
// 辅助哈希表,空间复杂度 O(n)
var dic = std.AutoHashMap(i32, i32).init(std.heap.page_allocator);
defer dic.deinit();
var i: usize = 0;
// 单层循环,时间复杂度 O(n)
while (i < size) : (i += 1) {
if (dic.contains(target - nums[i])) {
return [_]i32{dic.get(target - nums[i]).?, @intCast(i32, i)};
}
try dic.put(nums[i], @intCast(i32, i));
}
return undefined;
}
};
// Driver Code
pub fn main() !void {
// ======= Test Case =======
var nums = [_]i32{ 2, 7, 11, 15 };
var target: i32 = 9;
// 方法一
var slt1 = SolutionBruteForce{};
var res = slt1.twoSum(&nums, target);
std.debug.print("方法一 res = ", .{});
inc.PrintUtil.printArray(i32, &res);
// 方法二
var slt2 = SolutionHashMap{};
res = try slt2.twoSum(&nums, target);
std.debug.print("方法二 res = ", .{});
inc.PrintUtil.printArray(i32, &res);
}
@@ -3,6 +3,7 @@
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱
pub fn randomNumbers(comptime n: usize) [n]i32 {
@@ -26,17 +27,15 @@ pub fn findOne(nums: []i32) i32 {
}
// Driver Code
pub fn main() !void {
pub fn main() void {
var i: i32 = 0;
while (i < 10) : (i += 1) {
const n: usize = 100;
var nums = randomNumbers(n);
var index = findOne(&nums);
std.debug.print("\n数组 [ 1, 2, ..., n ] 被打乱后 = ", .{});
for (nums) |num, j| {
std.debug.print("{}{s}", .{num, if (j == nums.len-1) "" else "," });
}
std.debug.print("\n数字 1 的索引为 {}\n", .{index});
inc.PrintUtil.printArray(i32, &nums);
std.debug.print("数字 1 的索引为 {}\n", .{index});
}
}
+13
View File
@@ -0,0 +1,13 @@
// File: TreeNode.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
// Print an Array
pub fn printArray(comptime T: type, nums: []T) void {
std.debug.print("[", .{});
for (nums) |num, j| {
std.debug.print("{}{s}", .{num, if (j == nums.len-1) "]\n" else ", " });
}
}
+5
View File
@@ -0,0 +1,5 @@
// File: include.zig
// Created Time: 2023-01-04
// Author: sjinzh (sjinzh@gmail.com)
pub const PrintUtil = @import("PrintUtil.zig");