二叉树的构建、遍历--纯C代码

二叉树的构建:

1.通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树

二叉树的声明:

typedef char BTDataType;
struct BinaryTreeNode
{
BTDataType _Data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
};
typedef struct BinaryTreeNode BTNode;
**

图例:

**
在这里插入图片描述

思路:

前序遍历:根节点->左子树节点->右子树节点
数组的第一个元素就是根节点,然后构建左子树,在构建右子树。我们可以采用递归的方式
结束的条件是根节点为’#’。

代码实现:

BTNode* BinaryTreeCreate(BTDataType* a, int* Index)
{
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (a[*Index] == '#')
		return NULL;
	
	root->_Data = a[*Index];
	++(*Index);
	root->left = BinaryTreeCreate(a, Index);
	++(*Index);
	root->right = BinaryTreeCreate(a, Index);
	return root;
}

2.输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字

图例:

在这里插入图片描述

思路:

根据前序遍历确定根节点,在中序遍历的数组中找到根节点的位置,从而可以知道左子树的节点个数和右子树的节点个数,,只要节点个数大于0,就可以递归构建二叉树。

 struct TreeNode {
      int val;
    struct TreeNode *left;
     struct TreeNode *right;
  };
  typedef  struct TreeNode Node;

代码实现:

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize)
{

  if(preorder==NULL||inorder==NULL||preorderSize<=0||inorderSize<=0)
  {
    return NULL;
  }
  //前序遍历的第一个元素为根节点,设置好根节点
   Node* root=(Node*)malloc(sizeof(Node));
    root->val=*preorder;
    root->left=root->right=NULL;
    if(preorder[0]==preorder[preorderSize-1])
    return root;
    //在中序遍历中寻找根节点的位置,找出左子树和右子树的节点
    int Index=0;
    while(Index<inorderSize&&inorder[Index]!=root->val)
    ++Index;
    //确定左、右子树节点个数
    int leftlength=Index;
    int rightlength=preorderSize-1-Index;
    if(leftlength>0)
    {
        root->left=buildTree(preorder+1,leftlength,inorder,leftlength);
    }
    if(rightlength>0)
    {
       root->right=buildTree(preorder+Index+1,rightlength,inorder+Index+1,rightlength);
    }
return root;
}

3.返回与给定的前序和后序遍历匹配的任何二叉树。

代码实现:

struct TreeNode* constructFromPrePost(int* pre, int preSize, int* post, int postSize){
    if(pre==NULL||preSize<=0||post==NULL||postSize<=0)
    return NULL;
    struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=pre[0];
    root->right=root->left=NULL;
    if(preSize==1)
    return root;
    int Index=0;
    while(post[Index]!=pre[1]&&Index<postSize)
      ++Index;
    int leftlength=Index+1;
    int rightlength=postSize-leftlength-1;
    if(leftlength>0)
    {
        root->left=constructFromPrePost(pre+1,leftlength,post,leftlength);
    }
      if(rightlength>0)
    {
        root->right=
        constructFromPrePost(pre+leftlength+1,rightlength,post+Index+1,rightlength);
    }
    return root;

}

4.根据一棵树的中序遍历与后序遍历构造二叉树

代码实现:

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
    if(inorder==NULL||inorderSize<=0||postorder==NULL||postorderSize<=0)
    return NULL;
    //寻找二叉树的根节点
    Node* root=(Node*)malloc(sizeof(Node));
    root->val=postorder[postorderSize-1];
    root->right=root->left=NULL;
   //求左、右子树节点个数
    int Index=0;
    while(Index<inorderSize&&inorder[Index]!=root->val)
    {
      ++Index;
     
    }
    int leftlength=Index;
    int rightlength=inorderSize-Index-1;
    //构建左、右子树
    if(leftlength>0)
    {
        root->left=buildTree(inorder,leftlength,postorder,leftlength);
       
    }
    if(rightlength>0)
    {
        root->right=buildTree(inorder+Index+1,rightlength,postorder+leftlength,rightlength);
       
    }
return root;
}

二叉树的遍历:

前序遍历:

在这里插入图片描述
思路:将二叉树看成左子树,根,右子树三部分。所以,根不是空节点的情况下,先打印根节点,再递归访问左子树,和右子树。

代码实现(递归):

void  preorderTraversal_(struct TreeNode* root,int* a,int* Index)
{
    if(root==NULL)
    return ;
    a[(*Index)++]=root->val;
    preorderTraversal_(root->left,a,Index);
    preorderTraversal_(root->right,a,Index);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret=(int*)malloc(sizeof(int)*(1000));
    int Index=0;
   preorderTraversal_(root,ret,&Index);
    *returnSize=Index;
   return ret;
    

}

迭代:

图解:

在这里插入图片描述
思路:利用栈先进后出原则,现将根节点放入栈,再出栈,之后将右节点压进栈,再将左节点压进栈。将左节点作为根节点,迭代遍历完左子树。再将右节点作为根节点,迭代遍历完右子树。即完成前序遍历。

代码实现(迭代):

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int* ret = (int*)malloc(sizeof(int) * 100);
    int top = 0;
    struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 100);
    *returnSize = 0;
    if(!root) return NULL;
    stack[++top] = root;
    while(top >0)
    {
        root = stack[top--];
         ret[(*returnSize)++] = root->val;
        if(root->right)
        {
            stack[++top] = root->right;
        }
        if(root->left)
        {
            stack[++top] = root->left;
        }
    }
    return ret;
}

中序遍历、后序遍历思想和前序遍历相同。

层序遍历:

思路:

利用队列先进先出的性质,将结点一层一层的放入。
每一次打印一个节结的时候,如果该结点有子结点,则把该结点的子结点放到队列的末尾。到队列头部取出一个节点,重复操作,直到队列中所有结点全部被打印。
这样说,可能不太好理解,可以跟着代码理解思路,使用的队列函数都是自己实现的接口。

代码实现:

void BinaryTreeLevelOrder(BTNode* root)
{   //定义一个队列变量,并初始化
	Queue q;
	QueueInit(&q);
	//如果不是空树,将根节点入队
	if (root != NULL)
		QueuePush(&q, root);
		
	while (!QueueEmpty(&q))
	{
	//让队内的第一个元素出队并打印
		BTNode* front = QueueFront(&q);
		printf("%c ", front->_Data);
		QueuePop(&q);
	//如果出队的元素子树不为空,则入队。
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	//队内元素为0时层序遍历完整棵树。



}
发布了52 篇原创文章 · 获赞 6 · 访问量 1357

猜你喜欢

转载自blog.csdn.net/weixin_43519514/article/details/104863526
今日推荐