赞
踩
1、二叉查找树的特征
二叉查找树(BST)也称为二叉搜索树或二叉排序树。二叉查找树的节点包含键值key。二叉查找树或者是一棵空树,否则要求:
1. 若它的左子树不为空,那么左子树上所有节点的key都小于根节点的key。
2. 若它的右子树不为空,那么右子树上所有节点的key都大于根节点的key。
. 它的左右子树也分别为二叉排序树。
2、二叉查找树的建立、查找、插入和删除
1)递归建立二叉查找树
- btree creat_tree(btree root, int val)
- {
- if (root == nullptr)//如果为空的二叉树,便将新的节点设定为根节点
- {
- root = new Binary_tree;
- root->data = val;
- root->left = nullptr;
- root->right = nullptr;
- }
- else if (root->data < val)//如果新值比节点值大,递归地建立右子树
- root->right = creat_tree(root->right, val);
- else if (root->data > val)//如果新值比节点值小,递归地建立左子树
- root->left = creat_tree(root->left, val);
- else
- exit(-1);
- return root;
- }
(2)查找节点
- btree search_tree(btree ptr, int val)
- {
- while(1)
- {
- if(ptr == nullptr)//没找到就返回NULL
- return nullptr;
- if(ptr->data == val)//节点值等于查找值
- return ptr;
- else if(ptr->data > val)//查找值比节点值小,向左子树搜索
- ptr = ptr->left;
- else
- ptr = ptr->right;//查找值比节点值大,向右子树搜索
- }
- }
-
- //查找值最小的节点
- btree findmin_tree(btree root)
- {
- if (root == nullptr)//首先判断是否为空树
- return nullptr;
- if (root->left == nullptr)
- return root;
- else
- return findmin_tree(root->left);//使用递归判断
- }
-
- //查找值最大的节点
- btree findmax_tree(btree root)
- {
- if (root != nullptr)//首先判断是否为空树
- while (root->right != nullptr)//通过循环判断
- root = root->right;
- return root;
- }
(3)插入节点
- btree insert_tree(btree root, int val)
- {
- if (search_tree(root, val) == nullptr)
- {
- if (root == nullptr)
- creat_tree(root, val);//如果树为空,则创建树
- else if (val < root->data)
- //递归插入到左子树
- root->left = insert_tree(root->left, val);
- else if (val > root->data)
- //递归插入到右子树
- root->right = insert_tree(root->right, val);
- }
- }
(4)删除节点
- btree remove_tree(btree root, int val)
- {
- btree bt = search_tree(root, val);
- if (bt != nullptr)
- {
- if (val < root->data)//只有左子树
- root->left = remove_tree(root->left, val);
- else if (val > root->data)//只有右子树
- root->right = remove_tree(root->right, val);
- //左右子树都有
- else if (root->left != nullptr && root->right != nullptr)
- {
- //把右子树的最小值复制到当前节点
- root->data = findmin_tree(root->right)->data;
- //把最小值节点删除
- root->right = remove_tree(root->right, root->data);
- }
- else
- {
- //只有左子树或者右子树
- root = (root->left != nullptr)? root->left : root->right;
- }
- }
- }
遍历二叉树,就是以某种方式逐个“访问”二叉树的每一个节点。“访问”是指对节点的进行某种操作,例如输出节点的值。根据访问树根的顺序,我们有三种方式遍历二叉树:
1. 前序遍历:树根->左子树->右子树
2. 中序遍历:左子树->树根->右子树
3. 后序遍历:左子树->右子树->树根
1、前序遍历
先访问根节点,再遍历左子树,最后遍历右子树;并且在遍历左右子树时,仍需先访问根节点,然后遍历左子树,最后遍历右子树。
例如下图中二叉树前序遍历节点访问顺序为ABDGHCEIF:
2、中序遍历
先遍历左子树、然后访问根节点,最后遍历右子树;并且在遍历左右子树的时候。仍然是先遍历左子树,然后访问根节点,最后遍历右子树。
例如前图中二叉树中序遍历节点访问顺序为GDHBAEICF:
3、后序遍历
先遍历左子树,然后遍历右子树,最后访问根节点;同样,在遍历左右子树的时候同样要先遍历左子树,然后遍历右子树,最后访问根节点。前图后序遍历结果如下。
例如前图中二叉树后序遍历节点访问顺序为GHDBIEFCA:
4、确定唯一的二叉树
在二叉树的三种遍历方式中,如果有中序与前序的遍历结果或者中序与后序的遍历结果,即可从这些结果中得到唯一的二叉树。
确定唯一二叉树的方式:
1. 首先根据前序遍历的首元素或者后序遍历的尾元素,在中序遍历确定根节点。
. 随后根据该根节点在中序遍历中确定左右子树。
三、前序、中序、后序遍历的递归和非递归实现
1、递归实现
void inorder(btree ptr)//中序(输出根节点次序)遍历(递归实现) { if (ptr != nullptr) { inorder(ptr->left); cout << ptr->data << " "; inorder(ptr->right); } } void preorder(btree ptr)//前序遍历(递归实现) { if (ptr != nullptr) { cout << ptr->data << " "; preorder(ptr->left); preorder(ptr->right); } } void postorder(btree ptr)//后序遍历(递归实现) { if (ptr != nullptr) { postorder(ptr->left); postorder(ptr->right); cout << ptr->data << " "; } }
2、非递归实现(使用栈)
- //非递归中序遍历(左节点->根节点->右节点)思想:即用栈实现
- // 因为中序遍历二叉树的特点,所以在当前节点cur不为空或栈不为空的条件下(在该条件下的原因:该条件说明
- // 未遍历完二叉树),开始执行循环体,进行遍历:
- //(1)从当前节点cur开始,以cur为循环条件,当cur不为空时,将cur入栈,然后以cur=cur->_left跟进,直至
- // 将该二叉树的最左节点入栈后,入栈操作结束
- //(2)取栈顶节点:先保存该节点(用top保存该节点的原因:还要考虑该节点的右孩子)并输出该节点的值,
- // 然后执行栈的pop操作。
- //(3)继续以top->_right为cur值,转(1)操作.
-
- void inorder2(btree ptr)//中序遍历的非递归实现
- {
- stack<btree> st;
- while (ptr != nullptr || !st.empty())
- {
- while (ptr != nullptr)
- {
- st.push(ptr);
- ptr = ptr -> left;
- }
- btree tp = st.top();
- cout << tp -> data << " ";
- st.pop();
- ptr = tp -> right;
- }
- }
-
- //非递归先序遍历(根节点->左节点->右节点)思想:即用栈实现
- //遍历二叉树的前提条件是:该二叉树不为空。在满足该条件的情况下,进行以下步骤:
- //1.先将二叉树的根节点push进栈。
- //2.在该栈不为空的条件下,执行一个循环(先用top保存栈顶元素,再对栈进行pop操作,因为栈具有后进先出的特点
- // ,所以先对top->_right进行判断是否入栈,再对top->_left进行判断是否入栈)。
- //3.当栈为空时,先序遍历该二叉树结束。
-
- void preorder2(btree ptr)//前序遍历的非递归实现
- {
- stack<btree> st;
- if (ptr != nullptr)
- {
- st.push(ptr);
- }
- while (!st.empty())
- {
- btree tp = st.top();
- st.pop();
- cout << tp -> data << " ";
- if (tp->right != nullptr)
- st.push(tp->right);
- if (tp->left != nullptr)
- st.push(tp->left);
- }
- }
-
- //非递归后序遍历(左节点->右节点->根节点)思想:即用栈实现
- //(1)在当前节点cur不为空或栈不为空的条件下(在该条件下的原因:该条件说明未遍历完二叉树)。
- //(2)从当前节点cur开始,以cur为循环条件,当cur不为空时,将cur入栈,然后以cur=cur->_left跟进,直至
- // 将该二叉树的最左节点入栈后,入栈操作结束。取栈顶节点top:先保存该节点(用top保存该节点的原因:
- // 还要考虑该节点的右孩子),
- //(3)若top->_right==NULL || lastVisited == top->_right,则输出top->_value,执行栈的pop操作,并执行lastVisited = top(
- // 用lastVisited保存最近一个所输出的节点,待到下一次同样的操作时,若lastVisited == top->_right,则
- // 说明top的右节点已经访问过了,可以访问top了,否则会陷在cur = top->_right这步操作里);
- //(4)若条件(3)不满足,则继续以top->_right为cur值,转(1)操作.
- void postorder2(btree ptr)//后序遍历的非递归实现
- {
- stack<btree> st;
- btree lastVisited = nullptr;
- while (ptr != nullptr || !st.empty())
- {
- while (ptr != nullptr)
- {
- st.push(ptr);
- ptr = ptr -> left;
- }
- btree tp = st.top();
- if (tp->right == nullptr || lastVisited == tp->right)
- {
- st.pop();
- cout << tp -> data << " ";
- lastVisited = tp;
- }
- else
- ptr = tp->right;
- }
- }
参考:
https://blog.csdn.net/xiaotan2011929/article/details/61427919
http://www.cnblogs.com/QG-whz/p/5168620.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。