二叉树操作总结
2013-02-21 17:32 littlelion 阅读(515) 评论(0) 编辑 收藏 举报关于树及二叉树的基本定义就不多说,下面以BST为例,介绍一下二叉树的创建、遍历以及一些简单的算法。
- 首先是结点定义及初始化:
struct node{ int data; node* lchild; node* rchild; }; node* init_node(int value){ node* new_node = new node(); new_node->data = value; new_node->lchild = NULL; new_node->rchild = NULL; return new_node; }
还是那句话,初始化别放在main函数中,关于这个问题,程序员们肯定说这还用说吗,但对于没写过程序的人(例如我)来说,可能根本就不会想到这是个问题。
- 关于BST,咱都知道,即root->data > root->lchild->data && root->data < root->rchild->data; 那么在加入新结点时只需要根据这个条件找到它的父节点即可。
所以,找到要插入结点的父节点并插入的方法如下:
node* search_parent(node* root,int value){ node* parent = root; node* current_node = root; while(current_node!=NULL){ parent = current_node; if(current_node->data >= value){ current_node = current_node->lchild; }else{ current_node = current_node->rchild; } } return parent; } void add_node(node* root,int value){ node* new_node = init_node(value); node* parent = search_parent(root,value); if(value >= parent->data){ parent->rchild = new_node; }else{ parent->lchild = new_node; } }
- 好,下面初始化一个BST并且遍历它,关于二叉树的遍历方式,前序中序后序
node* init_BST(int* arr,int len){ node* root = init_node(9); for(int i=0;i<len;i++){ add_node(root,arr[i]); } return root; } void inorder(node* root){ if(root){ inorder(root->lchild); cout<<root->data<<" "; inorder(root->rchild); } } void preorder(node* root){ if(root){ cout<<root->data<<" "; preorder(root->lchild); preorder(root->rchild); } } void postorder(node* root){ if(root){ postorder(root->lchild); postorder(root->rchild); cout<<root->data<<" "; } }
- 下面来考虑几个有关二叉树的算法
1.求叶子结点数
叶子结点既没有左子树也没有右子树,因此只要满足current->lchild==NULL && current->rchild==NULL; 则count+=1;
总的叶子结点数 = l_叶子结点数 + r_叶子结点数,代码如下:
int leaf_node(node* root){ node* current_node = root; if(current_node==NULL) return 0; else if(current_node->lchild==NULL && current_node->rchild==NULL){ cout<<endl<<"leaf node is "<<current_node->data<<" "; return 1; } else return leaf_node(current_node->lchild)+leaf_node(current_node->rchild); }
2.求树的高度
数据结构书中给出的算法是
if(root == NULL)
height = 0;
else
height = max(height(root->lchild),height(root->rchild))+1
由于是求子树的高度,要知道height(root),只需知道height(root->lchild)和height(root->rchild),同理,要知道height(root->lchild)和height(root->rchild),只需知道它们各自子树的高度,依次类推。这样的想法,用递归来实现,递归退出的条件为urrent_node->lchild==NULL && current_node->rchild==NULL
int height(node* root){ int lheight,rheight; node* current_node = root; if(current_node==NULL) return 0; else if(current_node->lchild==NULL && current_node->rchild==NULL) return 1; else{ lheight = height(current_node->lchild); rheight = height(current_node->rchild); } int height = lheight>=rheight?lheight+1:rheight+1; cout<<endl<<"height of child tree "<<height<<" "; return height; }
3.查找一个结点
这个也不难想,current_node->data = value,
bool search_node(node* root,int value){ node* current_node = root; bool has = false; if(root==NULL){ return false; }else if(root->data==value){ return true; }else{ if(root->lchild!=NULL){ has = search_node(root->lchild,value); } if(!has && root->rchild!=NULL){ has = search_node(root->rchild,value); } } return has; }
4.求结点之间的最大路径
这道题目需要考虑三种情况:
(1)root->lchild!=NULL && root->rchild!=NULL
那么距离最远的两个结点一定分别位于左右子树
(2)当没有左子树或者没有右子树时,最大距离可能为某一结点到root根结点之间的距离
(3) 也可能为子树内部的两个结点之间的距离
我第一次写这个题目时,没有考虑那么多,只写出了第一种情况下的代码,如下:
int distance_differentChild(node* root){ int distance; if((root==NULL)||(root->lchild==NULL&&root->rchild==NULL)) return 0; else{ distance = height(root->lchild)+height(root->rchild); } return distance; }
当然了,还需要考虑缺了一个子树时的情况,代码如下:
int distance_compare(node* root){ int distance_passroot = height(root); int distance_notpassroot = distance_differentChild(root); return distance_passroot>=distance_notpassroot?distance_passroot:distance_notpassroot; }
最后,汇总一下求最远距离的代码:
int distanceBetweenTwoNodes(node* root){ int distance; if((root==NULL)||(root->lchild==NULL&&root->rchild==NULL)) return 0; else if(root->lchild==NULL || root->rchild==NULL){ if(root->lchild!=NULL){ distance = distance_compare(root->lchild); } if(root->rchild!=NULL){ distance = distance_compare(root->rchild); } } else{ distance = distance_differentChild(root); } return distance; }