基本数据结构之二叉树
2015-07-13 19:47
537 查看
C语言实现二叉树的遍历
二叉树结点的定义/* 先序,中序,后序的遍历时间复杂度为O(n),每个结点只访问一次。 层序的时间复杂度最差为O(n^2),当二叉树基本平衡时,时间复杂度为O(n) n为结点个数 */ typedef int tree_node_element; /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的结点数据结构 * */ typedef struct binary_tree_node { binary_tree_node* left; //左孩子 binary_tree_node* right; //右孩子 tree_node_element element; //数据节点 //构造函数 binary_tree_node(tree_node_element x) : element(x), left(NULL), right(NULL) {} }binary_tree_node;
二叉树递归遍历
/** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的前序遍历,递归 根-左-右 * @param root根节点 * @param visit 访问根节点的函数指针 * @return 无返回 * */ void pre_order_r(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { if (root == NULL) return; visit(root); pre_order_r(root->left, visit); pre_order_r(root->right, visit); } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的中序遍历 ,递归版 左-根-右 * @param root根节点 * @param visit 访问根节点的函数指针 * @return 无 * */ void in_order_r(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { if (root == NULL) return; in_order_r(root->left, visit); visit(root); in_order_r(root->right, visit); } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的后序遍历 ,递归版 左-右-根 * @param root根节点 * @param visit 访问根节点的函数指针 * @return 无 * */ void post_order_r(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { if (root == NULL) return; post_order_r(root->left, visit); post_order_r(root->right, visit); visit(root); }
二叉树的非递归遍历
/** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的前序遍历,非递归版 -- 使用栈完成,递归的本质也是栈 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void pre_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp = root; std::stack<const binary_tree_node*> avgSatck; //首先根节点入栈 if (temp != NULL) avgSatck.push(temp); while (!avgSatck.empty()) { temp = avgSatck.top(); //在这里改变temp avgSatck.pop(); visit(temp); //第一步打印出根节点之后,栈是空的。 if (temp->right != NULL) avgSatck.push(temp->right); if (temp->left != NULL) avgSatck.push(temp->left); } } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的中序遍历,非递归版 -- 使用栈完成,递归的本质也是栈 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void in_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp; std::stack<const binary_tree_node*> avgSatck; temp = root; while (!avgSatck.empty() || temp != NULL) { if (temp != NULL) { avgSatck.push(temp); temp = temp->left; } else { temp = avgSatck.top(); avgSatck.pop(); visit(temp); temp = temp->right; } } } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的后序遍历,非递归版 -- 使用栈完成,递归的本质也是栈 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void post_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp1,*temp2; std::stack<const binary_tree_node*> avgSatck; temp1 = root; do { while (temp1 != NULL) { avgSatck.push(temp1); temp1 = temp1->left; } temp2 = NULL; while (!avgSatck.empty()) { temp1 = avgSatck.top(); avgSatck.pop(); if (temp1->right == temp2) { visit(temp1); temp2 = temp1; } else { avgSatck.push(temp1); temp1 = temp1->right; break; } } } while (!avgSatck.empty()); }
二叉树的层次遍历
层次遍历个非递归的前序遍历代码一样,只不过要将辅助的存储结构改为队列
/** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的层次遍历 和前序遍历一模一样,不过改用队列存储 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void level_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp = root; std::queue<const binary_tree_node*> avgQueue; if (temp != NULL) avgQueue.push(temp); while (!avgQueue.empty()) { temp = avgQueue.front(); avgQueue.pop(); visit(temp); if (temp->left != NULL) avgQueue.push(temp->left); if (temp->right != NULL) avgQueue.push(temp->right); } }
完整的工程
#include <iostream>
#include <stack>
#include <queue>
#include <math.h>
/* 先序,中序,后序的遍历时间复杂度为O(n),每个结点只访问一次。 层序的时间复杂度最差为O(n^2),当二叉树基本平衡时,时间复杂度为O(n) n为结点个数 */ typedef int tree_node_element; /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的结点数据结构 * */ typedef struct binary_tree_node { binary_tree_node* left; //左孩子 binary_tree_node* right; //右孩子 tree_node_element element; //数据节点 //构造函数 binary_tree_node(tree_node_element x) : element(x), left(NULL), right(NULL) {} }binary_tree_node;
/* 二叉树的遍历,包括递归和非递归版本 */
/** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的前序遍历,递归 根-左-右 * @param root根节点 * @param visit 访问根节点的函数指针 * @return 无返回 * */ void pre_order_r(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { if (root == NULL) return; visit(root); pre_order_r(root->left, visit); pre_order_r(root->right, visit); } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的中序遍历 ,递归版 左-根-右 * @param root根节点 * @param visit 访问根节点的函数指针 * @return 无 * */ void in_order_r(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { if (root == NULL) return; in_order_r(root->left, visit); visit(root); in_order_r(root->right, visit); } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的后序遍历 ,递归版 左-右-根 * @param root根节点 * @param visit 访问根节点的函数指针 * @return 无 * */ void post_order_r(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { if (root == NULL) return; post_order_r(root->left, visit); post_order_r(root->right, visit); visit(root); }
/*二叉树遍历的非递归版*/
/** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的前序遍历,非递归版 -- 使用栈完成,递归的本质也是栈 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void pre_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp = root; std::stack<const binary_tree_node*> avgSatck; //首先根节点入栈 if (temp != NULL) avgSatck.push(temp); while (!avgSatck.empty()) { temp = avgSatck.top(); //在这里改变temp avgSatck.pop(); visit(temp); //第一步打印出根节点之后,栈是空的。 if (temp->right != NULL) avgSatck.push(temp->right); if (temp->left != NULL) avgSatck.push(temp->left); } } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的中序遍历,非递归版 -- 使用栈完成,递归的本质也是栈 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void in_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp; std::stack<const binary_tree_node*> avgSatck; temp = root; while (!avgSatck.empty() || temp != NULL) { if (temp != NULL) { avgSatck.push(temp); temp = temp->left; } else { temp = avgSatck.top(); avgSatck.pop(); visit(temp); temp = temp->right; } } } /** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的后序遍历,非递归版 -- 使用栈完成,递归的本质也是栈 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void post_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp1,*temp2; std::stack<const binary_tree_node*> avgSatck; temp1 = root; do { while (temp1 != NULL) { avgSatck.push(temp1); temp1 = temp1->left; } temp2 = NULL; while (!avgSatck.empty()) { temp1 = avgSatck.top(); avgSatck.pop(); if (temp1->right == temp2) { visit(temp1); temp2 = temp1; } else { avgSatck.push(temp1); temp1 = temp1->right; break; } } } while (!avgSatck.empty()); }
/** * @author 韦轩 * @time 2015/07/11 * @brief 二叉树的层次遍历 和前序遍历一模一样,不过改用队列存储 * @param root根节点 * @param visit 访问根节点的函数指针 * @return * */ void level_order(const binary_tree_node *root, int(*visit)(const binary_tree_node*)) { const binary_tree_node *temp = root; std::queue<const binary_tree_node*> avgQueue; if (temp != NULL) avgQueue.push(temp); while (!avgQueue.empty()) { temp = avgQueue.front(); avgQueue.pop(); visit(temp); if (temp->left != NULL) avgQueue.push(temp->left); if (temp->right != NULL) avgQueue.push(temp->right); } }
/**
* @author 韦轩
* @time 2015/07/12
* @brief 实现二叉树的高度
* @param
* @return 高度
*
*/
int getHeight(const binary_tree_node *root)
{
if (root == NULL)
return 0;
return getHeight(root->left)>getHeight(root->right) ? getHeight(root->left) : getHeight(root->right) + 1;
}
/**
* @author 韦轩
* @time 2015/07/12
* @brief visit 函数
*
*/
int visit(const binary_tree_node* node)
{
if (node != NULL)
{
printf_s("%d ", node->element);
return node->element;
}
}
int main()
{
binary_tree_node root(1);
binary_tree_node n1(2);
binary_tree_node n2(3);
binary_tree_node n3(4);
binary_tree_node n4(5);
binary_tree_node n5(6);
binary_tree_node n6(7);
binary_tree_node* proot = &root;
binary_tree_node* pn1 = &n1;
binary_tree_node* pn2 = &n2;
binary_tree_node* pn3 = &n3;
binary_tree_node* pn4 = &n4;
binary_tree_node* pn5 = &n5;
binary_tree_node* pn6 = &n6;
proot->left = pn1;
proot->right = pn2;
pn1->left = pn3;
pn1->right = pn4;
pn2->left = pn5;
pn2->right = pn6;
pn3->left = NULL;
pn3->right = NULL;
pn4->left = NULL;
pn4->right = NULL;
pn5->left = NULL;
pn5->right = NULL;
pn6->left = NULL;
pn6->right = NULL;
pre_order_r(proot, visit);
puts("\n");
pre_order(proot, visit);
puts("\n");
in_order_r(proot, visit);
puts("\n");
in_order(proot, visit);
puts("\n");
post_order_r(proot, visit);
puts("\n");
post_order(proot, visit);
puts("\n");
level_order(proot,visit);
puts("\n");
int h = getHeight(proot);
return 0;
}
二叉树的特点
三种遍历算法中,基本的结点都只访问一次,时间复杂度是O(n),同时,空间复杂度也是O(n)层次遍历的时间复杂度和二叉树的平衡有关,极端情况下,时间复杂度是O(N^2),平衡二叉树的时间复杂度是O(n)
相关文章推荐
- AVL树-自平衡二叉查找树(Java实现)
- C语言二叉树的非递归遍历实例分析
- C++非递归队列实现二叉树的广度优先遍历
- C#使用前序遍历、中序遍历和后序遍历打印二叉树的方法
- C++非递归建立二叉树实例
- C语言实现找出二叉树中某个值的所有路径的方法
- C++实现二叉树遍历序列的求解方法
- C语言实现二叉树遍历的迭代算法
- C++实现二叉树非递归遍历方法实例总结
- C++二叉树结构的建立与基本操作
- 深入遍历二叉树的各种操作详解(非递归遍历)
- JavaScript数据结构和算法之二叉树详解
- java使用归并删除法删除二叉树中节点的方法
- python数据结构之二叉树的建立实例
- python数据结构树和二叉树简介
- python数据结构之二叉树的统计与转换实例
- Python中的二叉树查找算法模块使用指南
- python二叉树的实现实例
- python数据结构之二叉树的遍历实例
- 平衡二叉树