mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
Finished red black tree, but the script has some bugs and is to be polished
This commit is contained in:
parent
3e84fa4a0b
commit
64c62a0ff8
18
README.md
18
README.md
|
@ -1,13 +1,19 @@
|
||||||
# 算法笔记
|
# Algorithm and data structures
|
||||||
记录学习算法的一些笔记, 想法, 以及代码实现 :smiley:
|
>Notes and codes for learning algorithm and data structures :smiley:
|
||||||
|
|
||||||
目前正在看`<<算法导论>>`
|
Some pictures and idead are from `<<Introduction to Algotithm>>
|
||||||
|
|
||||||
|
I use python 3.6+ and c++ to implements them.
|
||||||
|
Since I used f-Strings in python, you may use python 3.6+ to run the following python scripts.
|
||||||
|
|
||||||
> 目前 github 上的文档不支持 latex 数学公式渲染
|
>>I am still learning new things and this repo is always updating.
|
||||||
所以如果要读下面的一些笔记(md文件), 可以移步到[我的博客](https://mbinary.coding.me)
|
Some scripts may have bugs or not be finished yet.
|
||||||
|
|
||||||
# 索引
|
# Notice
|
||||||
|
Currently, Github can't render latex math formulas.
|
||||||
|
So,if you wannt to view the notes which contains latex math formulas and are in markdown format, you can visit [my blog](https://mbinary.coding.me)
|
||||||
|
|
||||||
|
# index
|
||||||
* [.](.)
|
* [.](.)
|
||||||
* [notes](./notes)
|
* [notes](./notes)
|
||||||
* [alg-general.md](./notes/alg-general.md)
|
* [alg-general.md](./notes/alg-general.md)
|
||||||
|
|
313
dataStructure/redBlackTree.py
Normal file
313
dataStructure/redBlackTree.py
Normal file
|
@ -0,0 +1,313 @@
|
||||||
|
'''
|
||||||
|
#########################################################################
|
||||||
|
# File : redBlackTree.py
|
||||||
|
# Author: mbinary
|
||||||
|
# Mail: zhuheqin1@gmail.com
|
||||||
|
# Blog: https://mbinary.coding.me
|
||||||
|
# Github: https://github.com/mbinary
|
||||||
|
# Created Time: 2018-07-12 20:34
|
||||||
|
# Description:
|
||||||
|
#########################################################################
|
||||||
|
'''
|
||||||
|
from functools import total_ordering
|
||||||
|
from random import randint, shuffle
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
|
class node:
|
||||||
|
def __init__(self,val,left=None,right=None,isBlack=False):
|
||||||
|
self.val =val
|
||||||
|
self.left = left
|
||||||
|
self.right = right
|
||||||
|
self.isBlack = isBlack
|
||||||
|
def __lt__(self,nd):
|
||||||
|
return self.val < nd.val
|
||||||
|
def __eq__(self,nd):
|
||||||
|
return nd is not None and self.val==nd.val
|
||||||
|
def setChild(self,nd,isLeft = True):
|
||||||
|
if isLeft: self.left = nd
|
||||||
|
else: self.right = nd
|
||||||
|
def getChild(self,isLeft):
|
||||||
|
if isLeft: return self.left
|
||||||
|
else: return self.right
|
||||||
|
def __bool__(self):
|
||||||
|
return self.val is not None
|
||||||
|
def __str__(self):
|
||||||
|
color = 'B' if self.isBlack else 'R'
|
||||||
|
return f'{color}-{self.val:}'
|
||||||
|
def __repr__(self):
|
||||||
|
return f'node({self.val},isBlack={self.isBlack})'
|
||||||
|
class redBlackTree:
|
||||||
|
def __init__(self):
|
||||||
|
self.root = None
|
||||||
|
def getParent(self,val):
|
||||||
|
if isinstance(val,node):val = val.val
|
||||||
|
if self.root.val == val:return None
|
||||||
|
nd = self.root
|
||||||
|
while nd:
|
||||||
|
if nd.val>val and nd.left is not None:
|
||||||
|
if nd.left.val == val: return nd
|
||||||
|
else: nd = nd.left
|
||||||
|
elif nd.val<val and nd.right is not None:
|
||||||
|
if nd.right.val == val: return nd
|
||||||
|
else: nd = nd.right
|
||||||
|
def find(self,val):
|
||||||
|
if isinstance(val,node):val = val.val
|
||||||
|
nd = self.root
|
||||||
|
while nd:
|
||||||
|
if nd.val ==val:
|
||||||
|
return nd
|
||||||
|
elif nd.val>val:
|
||||||
|
nd = nd.left
|
||||||
|
else:
|
||||||
|
nd = nd.right
|
||||||
|
@staticmethod
|
||||||
|
def checkBlack(nd):
|
||||||
|
return nd is None or nd.isBlack
|
||||||
|
@staticmethod
|
||||||
|
def setBlack(nd,isBlack):
|
||||||
|
if nd is not None:
|
||||||
|
if isBlack is None or isBlack:
|
||||||
|
nd.isBlack = True
|
||||||
|
else:nd.isBlack = False
|
||||||
|
def insert(self,val):
|
||||||
|
if isinstance(val,node):val = val.val
|
||||||
|
def _insert(root,nd):
|
||||||
|
'''return parent'''
|
||||||
|
while root:
|
||||||
|
if root == nd:return None
|
||||||
|
elif root>nd:
|
||||||
|
if root.left :
|
||||||
|
root=root.left
|
||||||
|
else:
|
||||||
|
root.left = nd
|
||||||
|
return root
|
||||||
|
else:
|
||||||
|
if root.right:
|
||||||
|
root = root.right
|
||||||
|
else:
|
||||||
|
root.right = nd
|
||||||
|
return root
|
||||||
|
# insert part
|
||||||
|
nd = node(val)
|
||||||
|
if self.root is None:
|
||||||
|
self.root = nd
|
||||||
|
self.setBlack(self.root,True)
|
||||||
|
return
|
||||||
|
parent = _insert(self.root,nd)
|
||||||
|
if parent is None: return
|
||||||
|
if not parent.isBlack: self.fixUpInsert(parent,nd)
|
||||||
|
|
||||||
|
def fixUpInsert(self,parent,nd):
|
||||||
|
''' adjust color and level, there are two red nodes: the new one and its parent'''
|
||||||
|
while not self.checkBlack(parent):
|
||||||
|
grand = self.getParent(parent)
|
||||||
|
isLeftPrt = grand.left == parent
|
||||||
|
uncle = grand.getChild(not isLeftPrt)
|
||||||
|
if not self.checkBlack(uncle):
|
||||||
|
# case 1: new node's uncle is red
|
||||||
|
self.setBlack(grand, False)
|
||||||
|
self.setBlack(grand.left, True)
|
||||||
|
self.setBlack(grand.right, True)
|
||||||
|
nd = grand
|
||||||
|
parent = self.getParent(nd)
|
||||||
|
else:
|
||||||
|
# case 2: new node's uncle is black(including nil leaf)
|
||||||
|
isLeftNode = parent.left==nd
|
||||||
|
if isLeftNode ^ isLeftPrt:
|
||||||
|
# case 2.1 the new node is inserted in left-right or right-left form
|
||||||
|
# grand grand
|
||||||
|
# parent or parent
|
||||||
|
# nd nd
|
||||||
|
parent.setChild(nd.getChild(isLeftPrt),not isLeftPrt)
|
||||||
|
nd.setChild(parent,isLeftPrt)
|
||||||
|
grand.setChild(nd,isLeftPrt)
|
||||||
|
nd,parent = parent,nd
|
||||||
|
# case 2.2 the new node is inserted in left-left or right-right form
|
||||||
|
# grand grand
|
||||||
|
# parent or parent
|
||||||
|
# nd nd
|
||||||
|
grand.setChild(parent.getChild(not isLeftPrt),isLeftPrt)
|
||||||
|
parent.setChild(grand,not isLeftPrt)
|
||||||
|
self.setBlack(grand, False)
|
||||||
|
self.setBlack(parent, True)
|
||||||
|
self.setBlack(self.root,True)
|
||||||
|
def sort(self,reverse = False):
|
||||||
|
''' return a generator of sorted data'''
|
||||||
|
def inOrder(root):
|
||||||
|
if root is None:return
|
||||||
|
if reverse:
|
||||||
|
yield from inOrder(root.right)
|
||||||
|
else:
|
||||||
|
yield from inOrder(root.left)
|
||||||
|
yield root
|
||||||
|
if reverse:
|
||||||
|
yield from inOrder(root.left)
|
||||||
|
else:
|
||||||
|
yield from inOrder(root.right)
|
||||||
|
yield from inOrder(self.root)
|
||||||
|
def getSuccessor(self,val):
|
||||||
|
if isinstance(val,node):val = val.val
|
||||||
|
def _inOrder(root):
|
||||||
|
if root is None:return
|
||||||
|
if root.val>= val:yield from _inOrder(root.left)
|
||||||
|
yield root
|
||||||
|
yield from _inOrder(root.right)
|
||||||
|
gen = _inOrder(self.root)
|
||||||
|
for i in gen:
|
||||||
|
if i.val==val:
|
||||||
|
try: return gen.__next__()
|
||||||
|
except:return None
|
||||||
|
|
||||||
|
def delete(self,val):
|
||||||
|
# delete node in a binary search tree
|
||||||
|
if isinstance(val,node):val = val.val
|
||||||
|
nd = self.find(val)
|
||||||
|
if nd is None: return
|
||||||
|
y = None
|
||||||
|
if nd.left and nd.right:
|
||||||
|
y= self.getSuccessor(val)
|
||||||
|
else:
|
||||||
|
y = nd
|
||||||
|
py = self.getParent(y.val)
|
||||||
|
x = y.left if y.left else y.right
|
||||||
|
if py is None:
|
||||||
|
self.root = x
|
||||||
|
elif y==py.left:
|
||||||
|
py.left = x
|
||||||
|
else:
|
||||||
|
py.right = x
|
||||||
|
if y != nd:
|
||||||
|
nd.val = y.val
|
||||||
|
|
||||||
|
# adjust colors and rotate
|
||||||
|
if self.checkBlack(y): self.fixUpDel(py,x)
|
||||||
|
|
||||||
|
def fixUpDel(self,prt,chd):
|
||||||
|
if self.root == chd or not self.checkBlack(chd):
|
||||||
|
self.setBlack(chd, True)
|
||||||
|
return
|
||||||
|
isLeft = prt.left == chd
|
||||||
|
brother = prt.getChild(not isLeft)
|
||||||
|
if self.checkBlack(brother):
|
||||||
|
# case 1: brother is black
|
||||||
|
lb = self.checkBlack(brother.left)
|
||||||
|
rb = self.checkBlack(brother.right)
|
||||||
|
if lb and rb:
|
||||||
|
# case 1.1: brother is black and two kids are black
|
||||||
|
self.setBlack(brother,False)
|
||||||
|
chd = prt
|
||||||
|
elif lb or rb:
|
||||||
|
# case 1.2: brother is black and two kids's colors differ
|
||||||
|
if self.checkBlack(brother.getChild(not isLeft)):
|
||||||
|
# uncle's son is nephew, and niece for uncle's daughter
|
||||||
|
nephew = brother.getChild(isLeft),
|
||||||
|
print(nephew)
|
||||||
|
self.setBlack(nephew,True)
|
||||||
|
self.setBlack(brother,False)
|
||||||
|
|
||||||
|
# brother right rotate
|
||||||
|
prt.setChild(nephew,not isLeft)
|
||||||
|
nephew.setChild(brother, not isLeft)
|
||||||
|
brother = prt.right
|
||||||
|
|
||||||
|
# case 1.3: brother is black and two kids are red
|
||||||
|
brother.isBlack = prt.isBlack
|
||||||
|
self.setBlack(prt,True)
|
||||||
|
self.setBlack(brother.right,True)
|
||||||
|
|
||||||
|
# prt left rotate
|
||||||
|
prt.setChild(brother.getChild(isLeft),not isLeft)
|
||||||
|
brother.setChild(prt,isLeft)
|
||||||
|
chd = self.root
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
# case 2: brother is red
|
||||||
|
prt.setChild(brother.getChild(isLeft), not isLeft)
|
||||||
|
brother.setChild(prt, isLeft)
|
||||||
|
self.setBlack(prt,False)
|
||||||
|
self.setBlack(brother,True)
|
||||||
|
self.setBlack(chd,True)
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
def getHeight(nd):
|
||||||
|
if nd is None:return 0
|
||||||
|
return max(getHeight(nd.left),getHeight(nd.right)) +1
|
||||||
|
def levelVisit(root):
|
||||||
|
from collections import deque
|
||||||
|
lst = deque([root])
|
||||||
|
level = []
|
||||||
|
h = getHeight(root)
|
||||||
|
lv = 0
|
||||||
|
ct = 0
|
||||||
|
while lv<=h:
|
||||||
|
ct+=1
|
||||||
|
nd = lst.popleft()
|
||||||
|
if ct >= 2**lv:
|
||||||
|
lv+=1
|
||||||
|
level.append([])
|
||||||
|
level[-1].append(str(nd))
|
||||||
|
if nd is not None:
|
||||||
|
lst.append(nd.left)
|
||||||
|
lst.append(nd.right)
|
||||||
|
else:
|
||||||
|
lst.append(None)
|
||||||
|
lst.append(None)
|
||||||
|
return level
|
||||||
|
lines = levelVisit(self.root)
|
||||||
|
print('-'*5+ 'level visit' + '-'*5)
|
||||||
|
return '\n'.join([' '.join(line) for line in lines])
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.display()
|
||||||
|
|
||||||
|
|
||||||
|
def genNum(n =10):
|
||||||
|
nums =[]
|
||||||
|
for i in range(n):
|
||||||
|
while 1:
|
||||||
|
d = randint(0,100)
|
||||||
|
if d not in nums:
|
||||||
|
nums.append(d)
|
||||||
|
break
|
||||||
|
#nums = [3,4,2,0,1,6]
|
||||||
|
return nums
|
||||||
|
|
||||||
|
def buildTree(n=10,nums=None,visitor=None):
|
||||||
|
if nums is None: nums = genNum(n)
|
||||||
|
rbtree = redBlackTree()
|
||||||
|
print(f'build a red-black tree using {nums}')
|
||||||
|
for i in nums:
|
||||||
|
if visitor:
|
||||||
|
visitor(rbtree)
|
||||||
|
rbtree.insert(i)
|
||||||
|
return rbtree
|
||||||
|
def testInsert():
|
||||||
|
def visitor(t):
|
||||||
|
print(t)
|
||||||
|
nums = [66, 14, 7, 2, 52, 96, 63, 51, 16, 53]
|
||||||
|
rbtree = buildTree(nums = nums,visitor = visitor)
|
||||||
|
print('-'*5+ 'in-order visit' + '-'*5)
|
||||||
|
for i,j in enumerate(rbtree.sort()):
|
||||||
|
print(f'{i+1}: {j}')
|
||||||
|
|
||||||
|
def testSuc():
|
||||||
|
rbtree = buildTree()
|
||||||
|
for i in rbtree.sort():
|
||||||
|
print(f'{i}\'s suc is {rbtree.getSuccessor(i)}')
|
||||||
|
|
||||||
|
def testDelete():
|
||||||
|
#nums = [56, 89, 31, 29, 24, 8, 62, 96, 20, 75] #tuple
|
||||||
|
nums = [66, 14, 7, 2, 52, 96, 63, 51, 16, 53]
|
||||||
|
rbtree = buildTree(nums = nums)
|
||||||
|
print(rbtree)
|
||||||
|
shuffle(nums)
|
||||||
|
for i in nums:
|
||||||
|
print(f'deleting {i}')
|
||||||
|
rbtree.delete(i)
|
||||||
|
print(rbtree)
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
testInsert()
|
||||||
|
#testDelete()
|
||||||
|
#testSuc()
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: 『算法』general
|
title: 『算法』general
|
||||||
date: 2018-07-04
|
date: 2018-07-04
|
||||||
categories: 算法与数据结构
|
categories: 数据结构与算法
|
||||||
tags: [算法]
|
tags: [算法]
|
||||||
keywords:
|
keywords:
|
||||||
mathjax: true
|
mathjax: true
|
||||||
|
@ -61,13 +61,19 @@ top:
|
||||||
|
|
||||||
|
|
||||||
<a id="markdown-4-算法设计" name="4-算法设计"></a>
|
<a id="markdown-4-算法设计" name="4-算法设计"></a>
|
||||||
# 4. 算法设计
|
# 4. 算法设计与分析
|
||||||
<a id="markdown-41-分治divide-and-conquer" name="41-分治divide-and-conquer"></a>
|
<a id="markdown-41-分治divide-and-conquer" name="41-分治divide-and-conquer"></a>
|
||||||
## 4.1. 分治(divide and conquer)
|
## 4.1. 分治(divide and conquer)
|
||||||
结构上是递归的,
|
结构上是递归的,
|
||||||
步骤: 分解,解决, 合并
|
步骤: 分解,解决, 合并
|
||||||
eg 快排,归并排序
|
eg 快排,归并排序
|
||||||
|
|
||||||
|
## 随机化
|
||||||
|
## 递归
|
||||||
|
## 动态规划
|
||||||
|
## 贪心算法
|
||||||
|
## 平摊分析
|
||||||
|
|
||||||
<a id="markdown-5-递归式" name="5-递归式"></a>
|
<a id="markdown-5-递归式" name="5-递归式"></a>
|
||||||
# 5. 递归式
|
# 5. 递归式
|
||||||
$T(n) = aT(\frac{n} {b})+f(n)$
|
$T(n) = aT(\frac{n} {b})+f(n)$
|
||||||
|
@ -78,6 +84,7 @@ eg 快排,归并排序
|
||||||
### 5.1.1. 步骤
|
### 5.1.1. 步骤
|
||||||
* 猜测解的形式
|
* 猜测解的形式
|
||||||
* 用数学归纳法找出常数
|
* 用数学归纳法找出常数
|
||||||
|
|
||||||
<a id="markdown-512-例子" name="512-例子"></a>
|
<a id="markdown-512-例子" name="512-例子"></a>
|
||||||
### 5.1.2. 例子
|
### 5.1.2. 例子
|
||||||
$T(n) = 2T(\frac{n} {2})+n$
|
$T(n) = 2T(\frac{n} {2})+n$
|
||||||
|
@ -91,12 +98,14 @@ $
|
||||||
T(n) &\leqslant 2c\frac{n}{2}log(\frac{n}{2}) + n \leqslant cnlog(\frac{n}{2}) \\
|
T(n) &\leqslant 2c\frac{n}{2}log(\frac{n}{2}) + n \leqslant cnlog(\frac{n}{2}) \\
|
||||||
\end{aligned}
|
\end{aligned}
|
||||||
$
|
$
|
||||||
|
|
||||||
<a id="markdown-513-放缩" name="513-放缩"></a>
|
<a id="markdown-513-放缩" name="513-放缩"></a>
|
||||||
### 5.1.3. 放缩
|
### 5.1.3. 放缩
|
||||||
对于 $T(n) = 2T(\frac{cn}{2}) + 1$
|
对于 $T(n) = 2T(\frac{cn}{2}) + 1$
|
||||||
如果 直接猜测 $T(n) = O (n)$ 不能证明,
|
如果 直接猜测 $T(n) = O (n)$ 不能证明,
|
||||||
而且不要猜测更高的界 $O (n^2)$
|
而且不要猜测更高的界 $O (n^2)$
|
||||||
可以放缩为 n-b
|
可以放缩为 n-b
|
||||||
|
|
||||||
<a id="markdown-514-改变变量" name="514-改变变量"></a>
|
<a id="markdown-514-改变变量" name="514-改变变量"></a>
|
||||||
### 5.1.4. 改变变量
|
### 5.1.4. 改变变量
|
||||||
对于 $ T(n) = 2T(\sqrt{n})+logn $
|
对于 $ T(n) = 2T(\sqrt{n})+logn $
|
||||||
|
@ -176,6 +185,7 @@ for i in range(n):
|
||||||
初始化: i=1 成立
|
初始化: i=1 成立
|
||||||
保持 : 假设 在第 i-1 次迭代之前,成立, 证明在第 i 次迭代之后, 仍然成立,
|
保持 : 假设 在第 i-1 次迭代之前,成立, 证明在第 i 次迭代之后, 仍然成立,
|
||||||
终止: 在 结束后, i=n+1, 得到 概率为 $\frac{1}{n!}$
|
终止: 在 结束后, i=n+1, 得到 概率为 $\frac{1}{n!}$
|
||||||
|
|
||||||
<a id="markdown-7-组合方程的近似算法" name="7-组合方程的近似算法"></a>
|
<a id="markdown-7-组合方程的近似算法" name="7-组合方程的近似算法"></a>
|
||||||
# 7. 组合方程的近似算法
|
# 7. 组合方程的近似算法
|
||||||
* Stiring's approximation: $ n! \approx \sqrt{2\pi n}\left(\frac{n}{e}\right)^n$
|
* Stiring's approximation: $ n! \approx \sqrt{2\pi n}\left(\frac{n}{e}\right)^n$
|
||||||
|
@ -188,7 +198,7 @@ for i in range(n):
|
||||||
## 8.1. 球与盒子
|
## 8.1. 球与盒子
|
||||||
把相同的秋随机投到 b 个盒子里,问在每个盒子里至少有一个球之前,平均至少要投多少个球?
|
把相同的秋随机投到 b 个盒子里,问在每个盒子里至少有一个球之前,平均至少要投多少个球?
|
||||||
称投入一个空盒为击中, 即求取得 b 次击中的概率
|
称投入一个空盒为击中, 即求取得 b 次击中的概率
|
||||||
设投 n 次, 称第 i 个阶段包括第 i-1 次击中到 第 i 次击中的球, 则 $p_i=\frac{b-i+1}{b}$
|
设投 n 次, 称第 i 个阶段包括第 i-1 次击中到 第 i 次击中的球, 则第 i 次击中的概率为 $p_i=\frac{b-i+1}{b}$
|
||||||
用 $n_i$表示第 i 阶段的投球数,则 $n=\sum_{i=1}^b n_i$
|
用 $n_i$表示第 i 阶段的投球数,则 $n=\sum_{i=1}^b n_i$
|
||||||
且 $n_i$服从几何分布, $E(n_i)=\frac{b}{b-i+1}$,
|
且 $n_i$服从几何分布, $E(n_i)=\frac{b}{b-i+1}$,
|
||||||
则由期望的线性性,
|
则由期望的线性性,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: 『数据结构』散列表
|
title: 『数据结构』散列表
|
||||||
date: 2018-07-08 23:25
|
date: 2018-07-08 23:25
|
||||||
categories: 算法与数据结构
|
categories: 数据结构与算法
|
||||||
tags: [数据结构,散列表]
|
tags: [数据结构,散列表]
|
||||||
keywords:
|
keywords:
|
||||||
mathjax: true
|
mathjax: true
|
||||||
|
@ -28,7 +28,6 @@ description:
|
||||||
|
|
||||||
<!-- /TOC -->
|
<!-- /TOC -->
|
||||||
|
|
||||||
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
|
||||||
|
|
||||||
哈希表 (hash table) , 可以实现 $O(1)$ 的 read, write, update
|
哈希表 (hash table) , 可以实现 $O(1)$ 的 read, write, update
|
||||||
相对应 python 中的 dict, c语言中的 map
|
相对应 python 中的 dict, c语言中的 map
|
||||||
|
@ -115,9 +114,9 @@ $$
|
||||||
对于 m 个槽位的表, 只需 $\Theta(n)$的期望时间来处理 n 个元素的 insert, search, delete,其中 有$O(m)$个insert 操作
|
对于 m 个槽位的表, 只需 $\Theta(n)$的期望时间来处理 n 个元素的 insert, search, delete,其中 有$O(m)$个insert 操作
|
||||||
<a id="markdown-2313-实现" name="2313-实现"></a>
|
<a id="markdown-2313-实现" name="2313-实现"></a>
|
||||||
#### 2.3.1.3. 实现
|
#### 2.3.1.3. 实现
|
||||||
选择足够大的 prime p, 记$Z_p=\{0,1,\ldots,p-1\}, Z_p^*=\{1,\ldots,p-1\},$
|
选择足够大的 prime p, 记$Z_p=\{0,1,\ldots,p-1\}, Z_p^{*}=\{1,\ldots,p-1\},$
|
||||||
令$h_{a,b}(k) = ((ak+b)mod\ p) mod\ m$
|
令$h_{a,b}(k) = ((ak+b)mod\ p) mod\ m$
|
||||||
则 $H_{p,m}=\{h_{a,b}|a\in Z_p^*,b\in Z_p\}$
|
则 $H_{p,m}=\{h_{a,b}|a\in Z_p^{*},b\in Z_p\}$
|
||||||
<a id="markdown-24-开放寻址法" name="24-开放寻址法"></a>
|
<a id="markdown-24-开放寻址法" name="24-开放寻址法"></a>
|
||||||
## 2.4. 开放寻址法
|
## 2.4. 开放寻址法
|
||||||
所有表项都在散列表中, 没有链表.
|
所有表项都在散列表中, 没有链表.
|
||||||
|
@ -141,9 +140,16 @@ $h(k,i) = (h_1(k)+i*h_2(k))mod\ m$
|
||||||
|
|
||||||
<a id="markdown-241-不成功查找的探查数的期望" name="241-不成功查找的探查数的期望"></a>
|
<a id="markdown-241-不成功查找的探查数的期望" name="241-不成功查找的探查数的期望"></a>
|
||||||
### 2.4.1. 不成功查找的探查数的期望
|
### 2.4.1. 不成功查找的探查数的期望
|
||||||
对于开放寻址散列表,且 $\alpha<1$,在一次不成功的查找中,有 $E(\text{探查数})\leqslant \frac{1}{1-\alpha}$
|
对于开放寻址散列表,且 $\alpha<1$,一次不成功的查找,是这样的: 已经装填了 n 个, 总共有m 个,则空槽有 m-n 个.
|
||||||
不成功探查是这样的: 前面都是检查到槽被占用但是关键字不同, 最后一次应该是空槽.
|
不成功的探查是这样的: 一直探查到已经装填的元素(但是不是要找的元素), 直到遇到没有装填的空槽. 所以这服从几何分布, 即
|
||||||
|
$$
|
||||||
|
p(\text{不成功探查})=p(\text{第一次找到空槽})=\frac{m-n}{m}
|
||||||
|
$$
|
||||||
|
有
|
||||||
|
$$ E(\text{探查数})=\frac{1}{p}\leqslant \frac{1}{1-\alpha}$$
|
||||||
|
|
||||||
![](https://upload-images.jianshu.io/upload_images/7130568-8d659aa8fe7de1a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
|
![](https://upload-images.jianshu.io/upload_images/7130568-8d659aa8fe7de1a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
|
||||||
|
|
||||||
<a id="markdown-2411-插入探查数的期望" name="2411-插入探查数的期望"></a>
|
<a id="markdown-2411-插入探查数的期望" name="2411-插入探查数的期望"></a>
|
||||||
#### 2.4.1.1. 插入探查数的期望
|
#### 2.4.1.1. 插入探查数的期望
|
||||||
所以, 插入一个关键字, 也最多需要 $\frac{1}{1-\alpha}$次, 因为插入过程就是前面都是被占用了的槽, 最后遇到一个空槽.与探查不成功是一样的过程
|
所以, 插入一个关键字, 也最多需要 $\frac{1}{1-\alpha}$次, 因为插入过程就是前面都是被占用了的槽, 最后遇到一个空槽.与探查不成功是一样的过程
|
||||||
|
@ -162,6 +168,8 @@ $$
|
||||||
$$
|
$$
|
||||||
|
|
||||||
代码
|
代码
|
||||||
|
|
||||||
|
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
||||||
```python
|
```python
|
||||||
class item:
|
class item:
|
||||||
def __init__(self,key,val,nextItem=None):
|
def __init__(self,key,val,nextItem=None):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: 『算法』排序
|
title: 『算法』排序
|
||||||
date: 2018-7-6
|
date: 2018-7-6
|
||||||
categories: 算法与数据结构
|
categories: 数据结构与算法
|
||||||
tags: [算法,排序]
|
tags: [算法,排序]
|
||||||
keywords:
|
keywords:
|
||||||
mathjax: true
|
mathjax: true
|
||||||
|
@ -36,7 +36,6 @@ description:
|
||||||
|
|
||||||
<!-- /TOC -->
|
<!-- /TOC -->
|
||||||
|
|
||||||
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
|
||||||
|
|
||||||
排序的本质就是减少逆序数, 根据是否进行比较,可以分为如下两类.
|
排序的本质就是减少逆序数, 根据是否进行比较,可以分为如下两类.
|
||||||
* 比较排序
|
* 比较排序
|
||||||
|
@ -411,7 +410,7 @@ if __name__ == '__main__':
|
||||||
设有 n 个元素, 则设立 n 个桶
|
设有 n 个元素, 则设立 n 个桶
|
||||||
将各元素通过数值线性映射到桶地址,
|
将各元素通过数值线性映射到桶地址,
|
||||||
类似 hash 链表.
|
类似 hash 链表.
|
||||||
然后在每个桶内, 进行插入排序,
|
然后在每个桶内, 进行插入排序($O(n_i^2)$)
|
||||||
最后合并所有桶.
|
最后合并所有桶.
|
||||||
这里的特点是 n 个桶实现了 $\Theta(n)$的时间复杂度, 但是耗费的空间 为 $\Theta(n)$
|
这里的特点是 n 个桶实现了 $\Theta(n)$的时间复杂度, 但是耗费的空间 为 $\Theta(n)$
|
||||||
|
|
||||||
|
@ -474,3 +473,4 @@ def select(lst,i):
|
||||||
return _select(0,len(lst)-1)
|
return _select(0,len(lst)-1)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: 『数据结构』树
|
title: 『数据结构』树
|
||||||
date: 2018-7-11 18:56
|
date: 2018-7-11 18:56
|
||||||
categories: 算法与数据结构
|
categories: 数据结构与算法
|
||||||
tags: [数据结构,树]
|
tags: [数据结构,树]
|
||||||
keywords:
|
keywords:
|
||||||
mathjax: true
|
mathjax: true
|
||||||
|
@ -26,6 +26,7 @@ description:
|
||||||
- [5.2.2. Zig-zig step](#522-zig-zig-step)
|
- [5.2.2. Zig-zig step](#522-zig-zig-step)
|
||||||
- [5.2.3. Zig-zag step](#523-zig-zag-step)
|
- [5.2.3. Zig-zag step](#523-zig-zag-step)
|
||||||
- [5.3. read-black Tree](#53-read-black-tree)
|
- [5.3. read-black Tree](#53-read-black-tree)
|
||||||
|
- [5.4. treap](#54-treap)
|
||||||
- [6. 总结](#6-总结)
|
- [6. 总结](#6-总结)
|
||||||
- [7. 附代码](#7-附代码)
|
- [7. 附代码](#7-附代码)
|
||||||
- [7.1. 二叉树(binaryTree)](#71-二叉树binarytree)
|
- [7.1. 二叉树(binaryTree)](#71-二叉树binarytree)
|
||||||
|
@ -35,7 +36,6 @@ description:
|
||||||
|
|
||||||
<!-- /TOC -->
|
<!-- /TOC -->
|
||||||
|
|
||||||
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
|
||||||
<a id="markdown-1-概念" name="1-概念"></a>
|
<a id="markdown-1-概念" name="1-概念"></a>
|
||||||
# 1. 概念
|
# 1. 概念
|
||||||
* 双亲
|
* 双亲
|
||||||
|
@ -87,13 +87,13 @@ $$
|
||||||
然后我们来看`<<算法导论>>`(p162,思考题12-4)上怎么求的吧( •̀ ω •́ )y
|
然后我们来看`<<算法导论>>`(p162,思考题12-4)上怎么求的吧( •̀ ω •́ )y
|
||||||
设生成函数
|
设生成函数
|
||||||
$$B(x)=\sum_{n=0}^{\infty}b_n x^n$$
|
$$B(x)=\sum_{n=0}^{\infty}b_n x^n$$
|
||||||
下面证明$B(x)=xB(x)^2+1\quad(\#)$
|
下面证明$B(x)=xB(x)^2+1$
|
||||||
易得$$xB(x)^2=\sum_{i=1}^{\infty}\sum_{n=i}^{\infty}b_{i-1}b_{n-i}x^n$$
|
易得$$xB(x)^2=\sum_{i=1}^{\infty}\sum_{n=i}^{\infty}b_{i-1}b_{n-i}x^n$$
|
||||||
对比$B(x), xB(x)^2+1$的 x 的各次系数,分别是 $b_k,a_{k}$
|
对比$B(x), xB(x)^2+1$的 x 的各次系数,分别是 $b_k,a_{k}$
|
||||||
当 k=0, $a_k=1=b_k$
|
当 k=0, $a_k=1=b_k$
|
||||||
当 k>0
|
当 k>0
|
||||||
$$a_{k} = \sum_{i=1}^{k}b_{i-1}b_{k-i} = b_k$$
|
$$a_{k} = \sum_{i=1}^{k}b_{i-1}b_{k-i} = b_k$$
|
||||||
所以$B(x)=xB(x)^2+1\quad(\#)$
|
所以$B(x)=xB(x)^2+1$
|
||||||
由此解得
|
由此解得
|
||||||
$$B(x)=\frac{1-\sqrt{1-4x} }{2x}$$
|
$$B(x)=\frac{1-\sqrt{1-4x} }{2x}$$
|
||||||
在点 x=0 处,
|
在点 x=0 处,
|
||||||
|
@ -121,7 +121,9 @@ $$
|
||||||
* 若A,B都是好括号列, 则串联后 AB是好括号列
|
* 若A,B都是好括号列, 则串联后 AB是好括号列
|
||||||
* 若A是好括号列, 则 (A)是好括号列
|
* 若A是好括号列, 则 (A)是好括号列
|
||||||
|
|
||||||
>充要条件: 好括号列 <=> 左右括号数相等, 且从左向右看, 看到的右括号数不超过左括号数
|
>充要条件: 好括号列 $\Longleftrightarrow$ 左右括号数相等, 且从左向右看, 看到的右括号数不超过左括号数
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
>定理: 由 n个左括号,n个右括号组成的好括号列个数为$c(n)=\frac{C_{2n}^{n}}{n+1}$
|
>定理: 由 n个左括号,n个右括号组成的好括号列个数为$c(n)=\frac{C_{2n}^{n}}{n+1}$
|
||||||
|
|
||||||
|
@ -209,6 +211,27 @@ Aho-Corasick automation,是在字典树上添加匹配失败边(失配指针),
|
||||||
## 5.3. read-black Tree
|
## 5.3. read-black Tree
|
||||||
同样是平衡的二叉树, 以后单独写一篇关于红黑树的.
|
同样是平衡的二叉树, 以后单独写一篇关于红黑树的.
|
||||||
|
|
||||||
|
<a id="markdown-54-treap" name="54-treap"></a>
|
||||||
|
## 5.4. treap
|
||||||
|
[前面提到](#21-随机构造的二叉查找树), 随机构造的二叉查找树高度为 $h=O(logn)$,以及在[算法 general](https://mbinary.coding.me/alg-genral.html) 中说明了怎样 随机化(shuffle)一个给定的序列.
|
||||||
|
|
||||||
|
所以,为了得到一个平衡的二叉排序树,我们可以将给定的序列随机化, 然后再进行构造二叉排序树.
|
||||||
|
|
||||||
|
但是如果不能一次得到全部的数据,也就是可能插入新的数据的时候,该怎么办呢? 可以证明,满足下面的条件构造的结构相当于同时得到全部数据, 也就是随机化的二叉查找树.
|
||||||
|
|
||||||
|
![treap](https://upload-images.jianshu.io/upload_images/7130568-f8fd5006a58ce451.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
|
||||||
|
|
||||||
|
这种结构叫 `treap`, 不仅有要排序的关键字 key, 还有随机生成的,各不相等的关键字`priority`,代表插入的顺序.
|
||||||
|
|
||||||
|
* 二叉查找树的排序性质: 双亲结点的 key 大于左孩子,小于右孩子
|
||||||
|
* 最小(大)堆的堆序性质: 双亲的 prority小于(大于) 孩子的 prority
|
||||||
|
|
||||||
|
|
||||||
|
插入的实现: 先进行二叉查找树的插入,成为叶子结点, 再通过旋转 实现 `上浮`(堆中术语).
|
||||||
|
将先排序 key, 再排序 prority(排序prority 时通过旋转保持 key 的排序)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a id="markdown-6-总结" name="6-总结"></a>
|
<a id="markdown-6-总结" name="6-总结"></a>
|
||||||
# 6. 总结
|
# 6. 总结
|
||||||
还有很多有趣的树结构,
|
还有很多有趣的树结构,
|
||||||
|
@ -218,6 +241,8 @@ Aho-Corasick automation,是在字典树上添加匹配失败边(失配指针),
|
||||||
|
|
||||||
<a id="markdown-7-附代码" name="7-附代码"></a>
|
<a id="markdown-7-附代码" name="7-附代码"></a>
|
||||||
# 7. 附代码
|
# 7. 附代码
|
||||||
|
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
||||||
|
|
||||||
<a id="markdown-71-二叉树binarytree" name="71-二叉树binarytree"></a>
|
<a id="markdown-71-二叉树binarytree" name="71-二叉树binarytree"></a>
|
||||||
## 7.1. 二叉树(binaryTree)
|
## 7.1. 二叉树(binaryTree)
|
||||||
```python
|
```python
|
||||||
|
|
Loading…
Reference in New Issue
Block a user