python算法与数据结构-二叉树的代码实现(46)
閱讀目錄
- 一、二叉樹回憶
- 二、二叉樹比鏈表好在哪里?
- 三、二叉樹的節點定義(C語言版)
- 四、定義一個二叉樹(C語言版)
- 五、初始化樹(C語言版)
- 六、創建節點(C語言版)
- 七、插入節點(C語言版)
- 八、樹的遍歷(C語言版)
- 九、樹的刪除(C語言版)
- 十、樹的查找(C語言版)
- 十一、樹的前序遍歷(C語言版)
- 十二、樹的中序遍歷(C語言版)
- 十三、樹的后序遍歷(C語言版)
- 十四、樹的廣度遍歷(C語言版)
- 十五、樹的python代碼實現
一、二叉樹回憶
上一篇我們對數據結構中常用的樹做了介紹,本篇博客主要以二叉樹為例,講解一下樹的數據結構和代碼實現。回顧二叉樹:二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)
二、二叉樹比鏈表好在哪里?
看看如下的數據:使用鏈表形式存放
我們要向查找數據6,需要從頭開始查找,找到最后一個,查找比較麻煩。再來看看使用二叉樹的形式存儲
?
顯然,我們很清楚自己要查找的目標大致會在那里出現;
例如查找的目標是6,那么我知道6小于9所以根本不會去看右邊的數據;
我們繼續看6大于5所以找到啦目標;
換句話說我們只對比了兩次找到啦目標;
而對于鏈表,我們發現6排在了鏈表的尾部;到此為止我們知道這樣的二叉樹的確是高效的;
三、二叉樹的節點定義(C語言版)
typedef struct N {int data;struct N *left_node;struct N *right_node;}Node;四、定義一個二叉樹(C語言版)
typedef struct tree {struct node *root; }Tree;我們的樹定義得更加簡單,注意我們是先定義節點,再定義樹;
因為樹的定義需要用到節點結構體;
接下來我們需要初始化我們的樹
五、初始化樹(C語言版)
Tree * init_tree() {Tree *tree = (Tree *)malloc(sizeof(Tree));if (tree){tree->root = NULL;}return tree; }六、創建節點(C語言版)
Node *make_node(int data) {Node *node = (Node *)malloc(sizeof(Node));node->left_node = NULL;node->right_node = NULL;node->data = data;return node; }七、插入節點(C語言版)
// 插入節點 Node* insert_node(Tree *tree,int data) {// 判斷根節點是否存在if (tree->root == NULL){// 不存在就創建tree->root = make_node(data);}else{Node *current = tree->root;// 一直循環知道找到準確的插入數據的位置while (1){// 我們的二叉樹不允許重復數字插入,相等直接退出if (current->data == data){return tree->root;}// 如果要插入的數據比根節點大,就放在右邊的子樹中else if(current->data<data){if (current->right_node == NULL){// 創建右節點current->right_node = make_node(data);break;}current = current->right_node;}else{// 如果要插入的數據比根節點小,就放在左邊的子樹中if (current->left_node == NULL){// 創建左節點current->left_node = make_node(data);break;}current = current->left_node;}}}return tree->root; }八、樹的遍歷(C語言版)
void print_inorder(Node *root) {if (root){print_inorder(root->left_node);printf("data:%d\n",root->data);print_inorder(root->right_node);} }九、樹的刪除(C語言版)
樹的刪除比較麻煩,整體分為二種情況:
一、要刪除的節點左右都有子節點
二、要刪除的節點只有一個或者0個節點(即有左節點或者右節點或者一個都沒有)
?其中第一種情況又分幾種小情況。例如:我們要刪除節點6
1.1 我們現在要刪除的是節點6,這時候6節點下面的右節點只有一個7,并且7下面沒有節點,有一個也一樣的,只需要將其右邊的節點7替代他的位置即可。
1.2 我們現在要刪除的是節點6,現在7下面5和8兩個節點,如果還是按照上面的思路刪除的話,刪除之后7下面就有1,5,8三個節點,明顯不對
正確的做法應該是找到要刪除的節點6的右節點7,這時候在找到7的做節點5,去繼承刪除節點6的位置
?
1.3、以要刪除節點6的右節點7為樹的左邊分支的最小子節點是左節點的情況(很繞口)
1.4、以要刪除節點6的右節點7為樹的左邊分支的最小子節點是右節點的情況(很繞口)
樹刪除代碼的實現
int remove_node(Tree *tree,int data) {if (tree->root != NULL){Node *p = NULL;Node *s ;Node *current = tree->root;while (1){// 根節點都沒有直接返回if (current == NULL){return 0;}// 要刪除的節點就是跟節點else if(current->data == data){break;}// 要刪除的節點在根節點的右邊else if(current->data<data){p = current;current = current->right_node;}// 要刪除的節點在根節點的左邊else{p=current;current = current->left_node;}} /**********************上面的代碼片段是找到要刪除的節點**************************/if (current->left_node != NULL && current->right_node != NULL){p = current;// 找到要刪除節點的右節點s = current->right_node;while (s->left_node != NULL){// p = s當current要深入到下一個分叉時,給自己留一個后路;所以保存了自己的前一個備份;p = s;// 沿著左邊一直找到最小的節點s = s->left_node;}current->data = s->data;// 最小值在分支的右邊if ( p->right_node == s){p->right_node = s->right_node;}free(s);} /***************上面的代碼片段是根據要刪除節點左右都有子節點的情況**************/else{// 左子節點為空,只有右子節點if (current->left_node == NULL){// 而且要刪除的節點是跟節點if (p==NULL){// 直接將跟節點的右節點設置為跟節點tree->root = current->right_node;}else{if (p->right_node == current){p->right_node = current->right_node;}else{p->left_node = current->right_node;}}}// 右子節點為空,只有左子節點else{// 而且要刪除的節點是跟節點if (p == NULL){tree->root = current->left_node;}else{if (p->right_node == current){p->right_node = current->left_node;}else{p->left_node = current->left_node;}}}} /***************上面的代碼片段是根據要刪除節點左右只有一個或者沒有子節點的情況**********/}return 1; }十、樹的查找(C語言版)
int find_node(Node *root,int data) {if (root == NULL){return 0;}else if(root->data == data){return 1;}else{if (root->data <data){return find_node(root->right_node, data);}else{return find_node(root->left_node, data);}} }十一、樹的前序遍歷(C語言版)
void preOrder(Node *root) {if (root != NULL){printf("%d ",root->data);preOrder(root->left_node);preOrder(root->right_node);} }十二、樹的中序遍歷(C語言版)
void inOrder(Node *root) {if (root != NULL){inOrder(root->left_node);printf("%d ",root->data);inOrder(root->right_node);} }十三、樹的后序遍歷(C語言版)
void postOreder(Node *root) {if (root != NULL){postOreder(root->left_node);postOreder(root->right_node);printf("%d ",root->data);}}十四、樹的廣度遍歷(C語言版)
void level_order(Tree *tree) {Node *node = tree->root;Node *queue[10];int current = 0;int after_current = 0;if (node == NULL){return;}queue[current++] = node;while (current!=after_current){node = queue[after_current++];printf("%d ",node->data);if (node->left_node != NULL){queue[current++] = node->left_node;}if (node->right_node != NULL){queue[current++] = node->right_node;}} }十五、樹的python代碼實現
由于C語言版寫的很詳細了,python就簡單的實現排序,思路完全一樣。
# coding:utf-8class Node(object):""""""def __init__(self, item):self.elem = itemself.lchild = Noneself.rchild = Noneclass Tree(object):"""二叉樹"""def __init__(self):self.root = Nonedef add(self, item):node = Node(item)if self.root is None:self.root = nodereturnqueue = [self.root]while queue:cur_node = queue.pop(0)if cur_node.lchild is None:cur_node.lchild = nodereturnelse:queue.append(cur_node.lchild)if cur_node.rchild is None:cur_node.rchild = nodereturnelse:queue.append(cur_node.rchild)def breadth_travel(self):"""廣度遍歷"""if self.root is None:returnqueue = [self.root]while queue:cur_node = queue.pop(0)print(cur_node.elem, end=" ")if cur_node.lchild is not None:queue.append(cur_node.lchild)if cur_node.rchild is not None:queue.append(cur_node.rchild)def preorder(self, node):"""先序遍歷"""if node is None:returnprint(node.elem, end=" ")self.preorder(node.lchild)self.preorder(node.rchild)def inorder(self, node):"""中序遍歷"""if node is None:returnself.inorder(node.lchild)print(node.elem, end=" ")self.inorder(node.rchild)def postorder(self, node):"""后序遍歷"""if node is None:returnself.postorder(node.lchild)self.postorder(node.rchild)print(node.elem, end=" ")if __name__ == "__main__":tree = Tree()tree.add(5)tree.add(2)tree.add(3)tree.add(7)tree.add(4)tree.add(8)tree.add(6)tree.preorder(tree.root)print(" ")tree.inorder(tree.root)print(" ")tree.postorder(tree.root)print(" ")tree.breadth_travel()運行結果為:
5 2 7 4 3 8 6 7 2 4 5 8 3 6 7 4 2 8 6 3 5 5 2 3 7 4 8 6寫到此處以吐血,你看到次數也吐血了吧。
?
侯哥語錄:我曾經是一個職業教育者,現在是一個自由開發者。我希望我的分享可以和更多人一起進步。分享一段我喜歡的話給大家:"我所理解的自由不是想干什么就干什么,而是想不干什么就不干什么。當你還沒有能力說不得時候,就努力讓自己變得強大,擁有說不得權利。"
來源:https://www.cnblogs.com/Se7eN-HOU/p/11140752.html
總結
以上是生活随笔為你收集整理的python算法与数据结构-二叉树的代码实现(46)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 股票z值偏低是什么意思
- 下一篇: websocket python爬虫_p