Skip to content

Commit 15ff510

Browse files
committed
b-tree, sort
1 parent be236a3 commit 15ff510

13 files changed

+474
-9
lines changed

src/DataStructure.jl

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module DataStructure
22

3-
export LinkedList, BinaryTree, BadOperationException, Graph, Heap
3+
export LinkedList, BinaryTree, BadOperationException, Graph, Heap, Sort, BalanceTree
44

55
struct BadOperationException <: Exception
66
message::String
@@ -11,5 +11,10 @@ include("linkedlist/LinkedList.jl")
1111
include("binarytree/BinaryTree.jl")
1212
include("huffmantree/HuffmanTree.jl")
1313
include("graph/Graph.jl")
14+
include("balancetree/BalanceTree.jl")
15+
include("sort/Sort.jl")
16+
if false
17+
include("../test/runtests.jl")
18+
end
1419

1520
end

src/balancetree.backup/BalanceTree.jl

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module BalanceTree
2+
import Base: isempty, insert!, print, show
3+
4+
export BTree, BTreeNode, printnode
5+
6+
abstract type AbstractBTreeNode{T} end
7+
BTreeNodeType{T} = Union{Nothing, AbstractBTreeNode{T}}
8+
9+
include("btreenode.jl")
10+
include("btree.jl")
11+
12+
13+
end

src/balancetree.backup/btree.jl

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
mutable struct BTree{T}
2+
level::Int
3+
root::BTreeNodeType{T}
4+
end
5+
6+
BTree(T::Union{DataType, UnionAll}, level::Int) = BTree{T}(level, nothing)
7+
8+
function insert!(tree::BTree{T}, data::T) where T
9+
if isnothing(tree.root)
10+
tree.root = BTreeNode(T, tree.level)
11+
end
12+
13+
tree.root = insert!(tree.root, data)
14+
end
15+
16+
function printnode(io::IO, node::BTreeNode{T}, depth = 0) where T
17+
for _ in 1:depth
18+
print(io, "| ")
19+
end
20+
21+
if depth > 0
22+
print(io, "|-----")
23+
end
24+
25+
print(io, node.keys)
26+
println(io)
27+
for child in node.children
28+
printnode(io, child, depth + 1)
29+
end
30+
end

src/balancetree.backup/btreenode.jl

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
@kwdef mutable struct BTreeNode{T} <: AbstractBTreeNode{T}
2+
level::Int
3+
keys::Vector{T}
4+
children::Vector{BTreeNodeType{T}}
5+
parent::BTreeNodeType{T}
6+
end
7+
8+
BTreeNode(T::Union{DataType, UnionAll}, level::Int) = BTreeNode{T}(
9+
level = level,
10+
keyNumber = 0,
11+
childrenNumber = 0,
12+
keys = T[],
13+
children = BTreeNodeType{T}[],
14+
parent = nothing)
15+
16+
reachMaxKeys(node::BTreeNode{T}) where T = length(node.keys) >= node.level
17+
isempty(node::BTreeNode{T}) where T = length(node.keys) == 0
18+
19+
isroot(node::BTreeNode{T}) where T = isnothing(node.parent)
20+
function root(node::BTreeNode{T})::BTreeNodeType{T} where T
21+
current = node
22+
while !isroot(current)
23+
current = current.parent
24+
end
25+
26+
return current
27+
end
28+
29+
function insert!(node::BTreeNode{T}, data::T)::BTreeNode{T} where T
30+
if isempty(node)
31+
push!(node.keys, data)
32+
child1 = BTreeNode(T, node.level)
33+
child1.parent = node
34+
35+
child2 = BTreeNode(T, node.level)
36+
child2.parent = node
37+
38+
push!(node.children, child1, child2)
39+
return node
40+
end
41+
42+
otherNode = findnode(root(node), data)
43+
44+
if !isempty(otherNode)
45+
throw(ErrorException("cannot insert duplicate key to btree, the key is $data"))
46+
end
47+
48+
insertNode!(otherNode.parent, data, BTreeNode(T, otherNode.level))
49+
return root(node)
50+
end
51+
52+
function insertNode!(parent::BTreeNode{T}, data::T, rightOfDataNode::BTreeNode{T}) where T
53+
index = 1
54+
while index <= length(parent.keys) && parent.keys[index] < data
55+
index += 1
56+
end
57+
58+
insert!(parent.keys, index, data)
59+
rightOfDataNode.parent = parent
60+
insert!(parent.children, index + 1, rightOfDataNode)
61+
62+
if !reachMaxKeys(parent)
63+
return
64+
end
65+
66+
upIndex = ceil(Int, parent.level / 2)
67+
up = parent.keys[upIndex]
68+
69+
rightNode = BTreeNode(T, parent.level)
70+
rightNode.keys = parent.keys[upIndex + 1 : parent.level]
71+
rightNode.children = parent.children[upIndex + 1 : parent.level + 1]
72+
73+
for child in rightNode.children
74+
child.parent = rightNode
75+
end
76+
77+
parent.keys = parent.keys[1 : upIndex - 1]
78+
parent.children = parent.children[1 : upIndex]
79+
80+
if isnothing(parent.parent)
81+
parent.parent = BTreeNode(T, parent.level)
82+
push!(parent.parent.keys, up)
83+
push!(parent.parent.children, parent)
84+
push!(parent.parent.children, rightNode)
85+
rightNode.parent = parent.parent
86+
else
87+
insertNode!(parent.parent, up, rightNode)
88+
end
89+
end
90+
91+
function findnode(node::BTreeNode{T}, target::T)::BTreeNode{T} where T
92+
if isempty(node)
93+
return node
94+
end
95+
96+
index = 1
97+
while index <= length(node.keys) && node.keys[index] <= target
98+
if node.keys[index] == target
99+
return node
100+
end
101+
102+
index += 1
103+
end
104+
105+
return findnode(node.children[index], target)
106+
end

src/balancetree/BalanceTree.jl

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module BalanceTree
2+
import Base: insert!, isempty, show, print
3+
export BTree, BTreeNode
4+
5+
include("node.jl")
6+
include("btree.jl")
7+
end

src/balancetree/btree.jl

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@kwdef mutable struct BTree{T}
2+
root::BTreeNode{T}
3+
degree::Int
4+
end
5+
6+
function BTree(T::Union{DataType, UnionAll}, degree::Int)
7+
if degree <= 2
8+
throw(ErrorException("cannot create a btree which degree <= 2"))
9+
end
10+
11+
return BTree{T}(degree = degree, root = BTreeNode{T}(degree = degree))
12+
end
13+
14+
function insert!(tree::BTree{T}, data::T) where T
15+
node = findnode(tree.root, data)
16+
tree.root = insert!(node, data, nothing)
17+
end
18+
19+
show(io::IO, tree::BTree) = printnode(io, tree.root, 0)
20+
print(io::IO, tree::BTree) = show(io, tree)

src/balancetree/node.jl

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
@kwdef mutable struct BTreeNode{T}
2+
degree::Int
3+
keys::Vector{T} = T[]
4+
children::Vector{BTreeNode{T}} = BTreeNode{T}[]
5+
parent::Union{Nothing, BTreeNode{T}} = nothing
6+
end
7+
8+
reachMaxKeys(node::BTreeNode) = length(node.keys) >= node.degree
9+
isempty(node::BTreeNode) = length(node.keys) == 0
10+
isleaf(node::BTreeNode) = length(node.children) == 0
11+
isroot(node::BTreeNode) = isnothing(node.parent)
12+
13+
function rootof(node::BTreeNode)::BTreeNode
14+
current = node
15+
while !isroot(current)
16+
current = current.parent
17+
end
18+
19+
return current
20+
end
21+
22+
# TODO insert at root, return the root of node
23+
# 在当前的 node 中插入数据
24+
# data 表示要插入的数据
25+
# nodeOfDataInRight 是在 split! 时不为空值,他这个时候表示分裂出的新节点
26+
function insert!(node::BTreeNode{T}, data::T, nodeOfDataInRight::Union{Nothing, BTreeNode{T}})::BTreeNode{T} where T
27+
index = (Iterators.takewhile(x -> x < data, node.keys) |> collect |> length) + 1
28+
insert!(node.keys, index, data)
29+
30+
if !isnothing(nodeOfDataInRight)
31+
insert!(node.children, index + 1, nodeOfDataInRight)
32+
nodeOfDataInRight.parent = node
33+
end
34+
35+
root = if !reachMaxKeys(node)
36+
node
37+
else
38+
split!(node)
39+
end
40+
41+
return rootof(root)
42+
end
43+
44+
# TODO split this node
45+
# has been reachMaxKeys
46+
function split!(node::BTreeNode{T})::BTreeNode{T} where T
47+
# 将 node.keys 分割成两部分,
48+
# 中间的元素是 upIndex, 我们取右边的 keys[upIndex + 1 : end] 来作为新节点的元素,
49+
# 将 children[upIndex + 2 : end] 来作为新节点的字节点元素
50+
upIndex = ceil(Int, node.degree / 2)
51+
up = node.keys[upIndex]
52+
53+
rightKeys = node.keys[upIndex + 1 : end]
54+
rightChildren = node.children[upIndex + 2 : end]
55+
56+
# 将冗余的数据去除
57+
deleteat!(node.keys, upIndex : length(node.keys))
58+
deleteat!(node.children, upIndex + 2 : length(node.children))
59+
60+
# 新建一个节点作为新节点
61+
rightNode = BTreeNode{T}(degree = node.degree, keys = rightKeys, children = rightChildren)
62+
63+
for child in rightChildren
64+
child.parent = rightNode
65+
end
66+
67+
if isroot(node) # 如果这个节点是根节点,新建一个节点作为新的根节点
68+
parent = BTreeNode{T}(degree = node.degree)
69+
push!(parent.keys, up)
70+
push!(parent.children, node, rightNode)
71+
72+
node.parent = parent
73+
rightNode.parent = parent
74+
75+
return parent
76+
else # 不然的话,将 up 的值插入到 node.parent 中的 keys 中
77+
insert!(node.parent, up, rightNode)
78+
79+
return node.parent
80+
end
81+
end
82+
83+
function printnode(io::IO, node::BTreeNode, depth::Int)
84+
for _ in 1:depth
85+
print(io, "| ")
86+
end
87+
88+
if depth > 0
89+
print(io, "|-----")
90+
end
91+
92+
print(io, node.keys)
93+
println(io)
94+
for child in node.children
95+
printnode(io, child, depth + 1)
96+
end
97+
end
98+
99+
show(io::IO, node::BTreeNode) = printnode(io, node, 0)
100+
print(io::IO, node::BTreeNode) = show(io, node)
101+
102+
function findnode(node::BTreeNode{T}, target::T)::BTreeNode{T} where T
103+
if isempty(node)
104+
return node
105+
end
106+
107+
index = 1
108+
while index <= length(node.keys) && node.keys[index] <= target
109+
if node.keys[index] == target
110+
return node
111+
end
112+
113+
index += 1
114+
end
115+
116+
return if isleaf(node)
117+
node
118+
else
119+
findnode(node.children[index], target)
120+
end
121+
end

src/binarytree/iterate.jl

+8-4
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ function iterate(iterator::PreOrderIterator{T}) where T
6464
node === treenil && return nothing
6565

6666
stack = List(AbstractBinaryTreeNode)
67-
push!(stack, node)
68-
current = pop!(stack)
67+
#= push!(stack, node)
68+
current = pop!(stack) =#
69+
70+
current = node
6971

7072
if hasright(current)
7173
push!(stack, right(current))
@@ -99,8 +101,10 @@ function iterate(iterator::PostOrderIterator{T}) where T
99101
node === treenil && return nothing
100102

101103
stack = List(AbstractBinaryTreeNode)
102-
push!(stack, node)
103-
current = pop!(stack)
104+
#= push!(stack, node)
105+
current = pop!(stack) =#
106+
107+
current = node
104108

105109
if hasleft(current)
106110
push!(stack, left(current))

src/sort/Sort.jl

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Sort
2+
export quicksort!, heapsort, radixsort!
3+
export MaxHeap, MinHeap
4+
include("quicksort.jl")
5+
include("radixsort.jl")
6+
include("heapsort.jl")
7+
end

0 commit comments

Comments
 (0)