日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

Python3实现红黑树[上篇]

發(fā)布時(shí)間:2023/12/2 python 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python3实现红黑树[上篇] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Python3實(shí)現(xiàn)紅黑樹[上篇]

由于時(shí)間有限,這次只寫了紅黑樹添加節(jié)點(diǎn),關(guān)于節(jié)點(diǎn)的刪除放在下一講 https://blog.csdn.net/qq_18138105/article/details/105324025。

關(guān)于紅黑樹的介紹,來(lái)由,性質(zhì)和定義,可以看這篇文章,本篇就不再贅述了:紅黑樹,超強(qiáng)動(dòng)靜圖詳解,簡(jiǎn)單易懂

關(guān)于紅黑樹,其實(shí)比較容易摸不著頭腦的是“左旋”和“右旋”。

既然是旋轉(zhuǎn),那么肯定有支點(diǎn)和旋點(diǎn),也就是以支點(diǎn)為軸,旋點(diǎn)繞支點(diǎn) 順時(shí)針逆時(shí)針旋轉(zhuǎn)。
那么,“左旋” 和 “右旋” 到底哪個(gè)是順時(shí)針,哪個(gè)是逆時(shí)針呢?
在這里,旋點(diǎn)一定是支點(diǎn)的父節(jié)點(diǎn),也就是說(shuō)旋點(diǎn)的位置比支點(diǎn)高,因此 左旋就是逆時(shí)針旋轉(zhuǎn),右旋就是順時(shí)針旋轉(zhuǎn)!

對(duì)于旋轉(zhuǎn),分享一個(gè)口訣:

右旋: 支點(diǎn)占旋點(diǎn)原位,支點(diǎn)的右給旋點(diǎn)作為左,旋點(diǎn)作為支點(diǎn)的右,交換支點(diǎn)和旋點(diǎn)的顏色 左旋: 支點(diǎn)占旋點(diǎn)原位,支點(diǎn)的左給旋點(diǎn)作為右,旋點(diǎn)作為支點(diǎn)的左,交換支點(diǎn)和旋點(diǎn)的顏色

先借用大神的2個(gè)圖。如下圖所示,就是 以p為支點(diǎn),g右旋的過(guò)程,看看是否符合上面的口訣呢: 經(jīng)過(guò)右旋后,支點(diǎn)p占據(jù)旋點(diǎn)g的原位,支點(diǎn)p的右T3作為了旋點(diǎn)g的左,旋點(diǎn)g作為了p的右

再看看左旋:經(jīng)過(guò)左旋后,支點(diǎn)p占據(jù)旋點(diǎn)g的原位,支點(diǎn)p的左T3作為了旋點(diǎn)g的右,旋點(diǎn)g作為了p的左。也是符合上面的口訣的。

以下便是python3代碼實(shí)現(xiàn) 紅黑樹插入節(jié)點(diǎn)的過(guò)程。

# 紅黑樹節(jié)點(diǎn) class RBN(object):def __init__(self, data):self.data = data # 數(shù)據(jù)域self.color = 0 # 0紅 1黑self.left = Noneself.right = Noneself.parent = None# 紅黑樹 class RBT(object):def __init__(self):self.root = None# 中序遍歷def midTraverse(self, x):if x == None:returnself.midTraverse(x.left)colorStr = '黑' if x.color == 1 else '紅'parentStr = '父=' + ('nil' if x.parent == None else str(x.parent.data))print(x.data, colorStr, parentStr)self.midTraverse(x.right)# 添加一個(gè)節(jié)點(diǎn)def add(self, x):# 如果沒有根節(jié)點(diǎn) 作為根節(jié)點(diǎn)if self.root == None:self.root = xx.color = 1 # 根節(jié)點(diǎn)為黑色# print('添加成功', x.data)return# 尋找合適的插入位置p = self.rootwhile p != None:if x.data < p.data:if p.left == None:p.left = xx.parent = p# print('添加成功', x.data)self.addFix(x)breakp = p.leftelif x.data > p.data:if p.right == None:p.right = xx.parent = p# print('添加成功', x.data)self.addFix(x)breakp = p.rightelse:return# 調(diào)整紅黑樹def addFix(self, x):while True:if x == self.root: # 如果處理到根節(jié)點(diǎn)了 則著色為黑x.color = 1returnp = x.parent # 爸爸if p.color == 1 or x.color == 1: # 自己和爸爸只要有一個(gè)是黑的 就構(gòu)不成雙紅 則返回return# 接下來(lái)分析紅爸爸情況g = p.parent # 爺爺 紅爸爸肯定有爸爸,因?yàn)榧t色絕不是根節(jié)點(diǎn)u = g.left if p == g.right else g.right # 叔叔 叔叔可能為空節(jié)點(diǎn)if u != None and u.color == 0: # 紅叔叔 則著色 然后從爺爺開始向上繼續(xù)調(diào)整u.color = p.color = 1 # 叔叔和爸爸都變黑色g.color = 0 # 爺爺變紅色x = g # x指向爺爺,然后繼續(xù)循環(huán)continue# 接下來(lái)分析黑叔叔得情況 有四種情況 左左,左右,右左,右右if p == g.left and x == p.left: # 左左# 以爸爸為支點(diǎn)右旋爺爺self.rotateRight(p)elif p == g.left and x == p.right: # 左右# 以x為支點(diǎn)左旋爸爸self.rotateLeft(x)# 以x為支點(diǎn)右旋爺爺(上面的旋轉(zhuǎn)把爺爺變成了新爸爸)self.rotateRight(x)elif p == g.right and x == p.right: # 右右 其實(shí)就是 左左的鏡像# 以爸爸為支點(diǎn)左旋爺爺self.rotateLeft(p)elif p == g.right and x == p.left: # 右左 其實(shí)就是 左右的鏡像# 以x為支點(diǎn)右旋爸爸self.rotateRight(x)# 以x為支點(diǎn)左旋爺爺(上面的旋轉(zhuǎn)把爺爺變成了新爸爸)self.rotateLeft(x)## 關(guān)于紅黑樹的旋轉(zhuǎn),一直是個(gè)難搞的點(diǎn)# 這里我提供一個(gè)口訣:# 右旋: 支點(diǎn)占旋點(diǎn)原位,支點(diǎn)的右給旋點(diǎn)作為左,旋點(diǎn)作為支點(diǎn)的右# 左旋: 支點(diǎn)占旋點(diǎn)原位,支點(diǎn)的左給旋點(diǎn)作為右,旋點(diǎn)作為支點(diǎn)的左## 右旋 p支點(diǎn)def rotateRight(self, p):g = p.parent # 支點(diǎn)的父節(jié)點(diǎn)就是旋點(diǎn)# 右旋gif g == self.root: # 若g是根節(jié)點(diǎn) 則p升為根節(jié)點(diǎn)self.root = pp.parent = Noneelse: # 若g不是根節(jié)點(diǎn) 那么必然存在g.parent p占據(jù)g的位置gp = g.parentp.parent = gpif g == gp.left:gp.left = pelse:gp.right = pg.left = p.rightif p.right != None:p.right.parent = gp.right = gg.parent = p# g和p顏色交換p.color, g.color = g.color, p.color# 左旋 p 支點(diǎn)def rotateLeft(self, p):g = p.parent # 支點(diǎn)的父節(jié)點(diǎn)就是旋點(diǎn)# 左旋gif g == self.root: # 若g是根節(jié)點(diǎn) 則p升為根節(jié)點(diǎn)self.root = pp.parent = Noneelse: # 若g不是根節(jié)點(diǎn) 那么必然存在g.parent p占據(jù)g的位置gp = g.parentp.parent = gpif g == gp.left:gp.left = pelse:gp.right = pg.right = p.leftif p.left != None:p.left.parent = gp.left = gg.parent = p# g和p顏色交換p.color, g.color = g.color, p.colorif __name__ == '__main__':rbt = RBT()datas = [10, 20, 30, 15]# datas = [11, 2, 14, 1, 7, 15, 5, 8, 4]for x in datas:rbt.add(RBN(x))rbt.midTraverse(rbt.root)

關(guān)于紅黑樹節(jié)點(diǎn)的刪除,請(qǐng)看下回分解。

總結(jié)

以上是生活随笔為你收集整理的Python3实现红黑树[上篇]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。