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)
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-12 16:29:57