二叉树的简单操作(Binary Tree)
树形结构应该是贯穿整个数据结构的一个比较重要的一种结构,它的重要性不言而喻!
讲到树!一般都是讨论二叉树,而关于二叉树的定义以及概念这里不做陈诉,可自行搜索。
在C语言里面需要实现一个二叉树,我们需要申明一个结构体,而关于其结构体的多种方法
这里也不一一列出,我采用比较通用的方法:
struct TreeNode{
ElementType Element;
struct TreeNode *Left;
struct TreeNode *RIght;
};
BinaryTree.h:
#ifndef TREE_H
#define TREE_H typedef char TreeElementType; typedef struct TreeNode *PtrToNode;
typedef PtrToNode BinTree; struct TreeNode
{
TreeElementType Element;
struct TreeNode *Left;
struct TreeNode *Right;
}; BinTree CreateTree();//先序遍历创建二叉树
BinTree IterationCreateTree();//先序非递归创建二叉树 void PreOrderTraversal(BinTree BT);
void IterationPreOrderTraversal(BinTree BT); void InOrderTraversal(BinTree BT);
void IterationInOrderTraversal(BinTree BT); void PostOrderTraversal(BinTree BT);
void IterationPostOrderTraversal(BinTree BT); void LevelTraversal(BinTree BT); int SumNode(BinTree BT);
int SumLeafNode(BinTree BT);
int Depth(BinTree BT);//输出整个二叉树的深度 #endif
整个关于二叉树的操作函数都写了它的递归和迭代版本(层次遍历没有写递归版本),为了保持文件的封装性,将整个关于二叉树的简单操作都封装在一个.c文件里
TreeOperate.c:
#include"BinaryTree.h"
#include"Stack.c"
#include"Queue.c"
#include<stdio.h>
#include<stdlib.h> #define MaxSize 50//栈和队列的大小 //先序递归创建二叉树
BinTree CreateTree()
{
TreeElementType ch;
BinTree BT;
ch = getchar();
if(ch == '')
BT = NULL;
else
{
BT = (BinTree)malloc(sizeof(struct TreeNode));
if(NULL == BT)
{
printf("Out of space!!!");
return NULL;
}
BT->Element = ch;
BT->Left = CreateTree();
BT->Right = CreateTree();
}
return BT;
} void PreOrderTraversal(BinTree BT)
{
if(BT)
{
printf("%c ", BT->Element);
PreOrderTraversal(BT->Left);
PreOrderTraversal(BT->Right);
}
} void InOrderTraversal(BinTree BT)
{
if(BT)
{
InOrderTraversal(BT->Left);
printf("%c ", BT->Element);
InOrderTraversal(BT->Right);
}
} void PostOrderTraversal(BinTree BT)
{
if(BT)
{
PostOrderTraversal(BT->Left);
PostOrderTraversal(BT->Right);
printf("%c ", BT->Element);
}
} /*-------------------下面是非递归写法------------------------*/
//先序非递归创建二叉树
BinTree IterationCreateTree()
{
int Flag[MaxSize] = {};
Stack S;
S = CreatStack(MaxSize);
TreeElementType ch;
BinTree Root;
PtrToNode NewCell, T;
printf("请输入简单二叉树的元素类似:222003004500600:\n");
do{
ch = getchar();
if(ch == '')
NewCell = NULL;
else
{
NewCell = (BinTree)malloc(sizeof(struct TreeNode));
if(NULL == NewCell)
{
printf("Alloc is fairure!!");
return NULL;
}
else
{
NewCell->Element = ch;
NewCell->Left = NewCell->Right = NULL;
}
}
//根节点入栈
if(IsEmpty(S) && NewCell)
{
Push(S, NewCell);
Root = NewCell;//第一个进栈的为根节点
Flag[S->TopOfStack] = ;
}
//如果当前(栈顶)节点已经连接左节点,现在连接右节点
else if(Flag[S->TopOfStack] == )
{
T = TopAndPop(S);
T->Right = NewCell;
if(NewCell)
{
Push(S, NewCell);
Flag[S->TopOfStack] = ;//元素进栈后都要置为0,清除隐患
}
}
//该左孩子节点入栈,并连接父亲节点
else
{
Flag[S->TopOfStack] = ;//父亲结点标记为1,表示已经连接左结点
//下面是连接左结点的代码
T = Top(S);
T->Left = NewCell;
if(NewCell)
{
Push(S, NewCell);
Flag[S->TopOfStack] = ;//元素进栈后都要置为0,清除隐患
}
}
}while(!IsEmpty(S)); return Root;
}
//先序
void IterationPreOrderTraversal(BinTree BT)
{
Stack S;
S = CreatStack(MaxSize);
BinTree T = BT;
while(T || !IsEmpty(S))
{
while(T)
{
Push(S, T);
//注意printf的顺序,因为他是在访问左孩子节点时就已经处理了!
printf("%c ", T->Element);
T = T->Left;
}
if(T == NULL)
{
T = TopAndPop(S);
T = T->Right;
}
}
}
//中序
void IterationInOrderTraversal(BinTree BT)
{
Stack S;
S = CreatStack(MaxSize);
BinTree T = BT;
while(T || !IsEmpty(S))
{
while(T)
{
Push(S, T);
T = T->Left;
}
if(T == NULL)
{
T = TopAndPop(S);
//printf在访问右孩子之前就处理的当前元素
printf("%c ", T->Element);
T = T->Right;
}
}
}
//后序
//void IterationPostOrderTraversal(BinTree BT)
//{
// int Flag[MaxSize];
// Stack S;
// S = CreatStack(MaxSize);
// BinTree T = BT;
// while(T || !IsEmpty(S))
// {
// while(T)
// {
// Push(S, T);
// Flag[S->TopOfStack] = 0;//未处理的标记为0
// T = T->Left;
// }
// while(Flag[S->TopOfStack] == 1)
// {
// T = TopAndPop(S);
// printf("%c ", T->Element);
// T = NULL;//该节点被处理后,父亲节点的右孩子置空
// }
// if(!IsEmpty(S))
// {
// T = Top(S);
// T = T->Right;
// Flag[S->TopOfStack] = 1;
// }
// }
//}
//第二种版本
void IterationPostOrderTraversal(BinTree BT)
{
int Flag[MaxSize] = {};
Stack S;
S = CreatStack(MaxSize);
BinTree T = BT;
while(T || !IsEmpty(S))
{
/*将左结点全部入栈*/
if(T)
{
Push(S, T);
Flag[S->TopOfStack] = ;//未处理的标记为0
T = T->Left;
}
/*如果已经访问了该结点的右孩子,将它出队并打印*/
else if(Flag[S->TopOfStack] == )
{
T = TopAndPop(S);
printf("%c ", T->Element);
T = NULL;//该节点被处理后置空,否则会被识别入栈
}
/*如果左孩子为空,则访问它的右孩子*/
else
{
T = Top(S);
T = T->Right;
Flag[S->TopOfStack] = ;//访问了右孩子,标记为1
}
}
}
//层次
void LevelTraversal(BinTree BT)
{
Queue Q;
Q = CreatQueue(MaxSize);
BinTree T = BT;
Enqueue(Q, T);
while(!QIsEmpty(Q))
{
T = FrontAndDequeue(Q);
printf("%c ", T->Element);
if(T->Left)
Enqueue(Q, T->Left);
if(T->Right)
Enqueue(Q, T->Right);
}
} int SumNode(BinTree BT)
{
if(NULL == BT)
return ;
else if(BT->Left == NULL && BT->Right == NULL)
return ;
else
return SumNode(BT->Left) + SumNode(BT->Right) + ;//加1等于是每次返回 加一个根结点
} int SumLeafNode(BinTree BT)
{
if(NULL == BT)
return ;
else if(BT->Left == NULL && BT->Right == NULL)
return ;
else
return SumLeafNode(BT->Left) + SumLeafNode(BT->Right);
} int Depth(BinTree BT)//输出的是整个二叉树的深度
{
int DepthOfLeft = ;
int DepthOfRight = ;
if(NULL == BT)
return ;
else
{
DepthOfLeft = Depth(BT->Left);
DepthOfRight = Depth(BT->Right);
return (DepthOfLeft > DepthOfRight) ? DepthOfLeft + : DepthOfRight + ;
}
}
上文用到的栈的操作和队列的操作出自https://www.cnblogs.com/Crel-Devi/p/9460945.html和https://www.cnblogs.com/Crel-Devi/p/9600940.html,需修改栈和队列同名的函数名称以及Element的名字以及栈和队列的元素类型!!!!!!!(非常重要)
下面给出一个简单的测试代码main.c:
#include"BinaryTree.h"
#include<stdio.h>
#include<stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) {
BinTree BT;
printf("请输入二叉树的元素:");
BT = CreateTree();
//BT = IterationCreateTree(); printf("先序遍历(递归):\t");
PreOrderTraversal(BT);
printf("\n");
printf("先序遍历(迭代):\t");
IterationPreOrderTraversal(BT);
printf("\n\n"); printf("中序遍历(递归):\t");
InOrderTraversal(BT);
printf("\n");
printf("中序遍历(迭代):\t");
IterationInOrderTraversal(BT);
printf("\n\n"); printf("后序遍历(递归):\t");
PostOrderTraversal(BT);
printf("\n");
printf("后序遍历(迭代):\t");
IterationPostOrderTraversal(BT);
printf("\n\n"); printf("层次遍历(迭代):\t");
LevelTraversal(BT);
printf("\n\n"); int allnode, leafnode, treedepth;
allnode = SumNode(BT);
leafnode = SumLeafNode(BT);
treedepth = Depth(BT);
printf("二叉树结点总数:%d\t\n", allnode);
printf("二叉树叶节点总数:%d\t\n", leafnode);
printf("二叉树深度:%d\t\n", treedepth);//输出整棵树的深度
printf("\n"); return ;
}

二叉树的简单操作(Binary Tree)的更多相关文章
- [Swift]LeetCode144. 二叉树的前序遍历 | Binary Tree Preorder Traversal
Given a binary tree, return the preorder traversal of its nodes' values. Example: Input: [1,null,2,3 ...
- (二叉树 递归) leetcode 144. Binary Tree Preorder Traversal
Given a binary tree, return the preorder traversal of its nodes' values. Example: Input: [1,null,2,3 ...
- 二叉树叶子顺序遍历 · binary tree leaves order traversal
[抄题]: 给定一个二叉树,像这样收集树节点:收集并移除所有叶子,重复,直到树为空. 给出一个二叉树: 1 / \ 2 3 / \ 4 5 返回 [[4, 5, 3], [2], [1]]. [暴力解 ...
- LeetCode 144. 二叉树的前序遍历(Binary Tree Preorder Traversal)
144. 二叉树的前序遍历 144. Binary Tree Preorder Traversal 题目描述 给定一个二叉树,返回它的 前序 遍历. LeetCode144. Binary Tree ...
- (二叉树 BFS) leetcode 107. Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
- [Swift]LeetCode156.二叉树的上下颠倒 $ Binary Tree Upside Down
Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that ...
- [Swift]LeetCode102. 二叉树的层次遍历 | Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...
- [Swift]LeetCode199. 二叉树的右视图 | Binary Tree Right Side View
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...
- [Swift]LeetCode257. 二叉树的所有路径 | Binary Tree Paths
Given a binary tree, return all root-to-leaf paths. Note: A leaf is a node with no children. Example ...
随机推荐
- .NET EF框架的安装、及三种开发模式
一.EF框架的安装: 要在VS(如Visual Studio 2012)中使用EF框架,就需要先进行安装. 我们需要给这个应用安装EntityFramework包,引入EF框架相关的内容,我们需要引入 ...
- SVN忽略不提交文件夹
eclipse提交经常要同步后再提交或更新,但是这时有很多不需要提交的文件.文件夹比较碍事,这时候就可以在svn上设置不需要关注的文件夹: 1.windows->preferences-> ...
- BZOJ 4259 残缺的字符串
思路 同样是FFT进行字符串匹配 只不过两个都有通配符 匹配函数再乘一个\(A_i\)即可 代码 #include <cstdio> #include <algorithm> ...
- C语言--第2次作业
1.本章学习总结 1.1思维导图 1.2本章学习体会及本章代码量 1.2.1学习体会 不同于前几周简单的条件语句等,这一周开始学习循环结构for,while语句,甚至是多种语句嵌套使用,让我直接感受到 ...
- 全景拍摄,全景视频拍摄,全景VR拍摄,VR全景拍摄,360全景图片拍摄
北京动软专业提供基于手机.VR设备.PC浏览器的全景拍摄和项目展示服务. 承接服务内容包括720°全景拍摄展示.VR虚拟现实全景.全景漫游.全景视频.物体全景.环物全景等. 全景展示主要应用于展览 ...
- Hadoop之运行模式
Hadoop运行模式包括:本地模式.伪分布式以及完全分布式模式. 一.本地运行模式 1.官方Grep案例 1)在hadoop-2.7.2目录下创建一个 input 文件夹 [hadoop@hadoop ...
- window上安装kafka(单机)
1.第一步骤,先安装JDK,请参考:https://www.cnblogs.com/xubao/p/10692861.html 2.第二步骤,安装zookeeper,请参考:https://www.c ...
- 使用vue+iview实现上传文件及常用的下载文件的方法
首先说明一下,我们这次主要用的还是iview的upload上传组件,下面直接上代码 <Upload ref="upload" multiple='true' //是否支持多文 ...
- lua 5.3.5 安装/初体验
安装 官网http://www.lua.org/start.html 参考 https://blog.csdn.net/qq_23954569/article/details/70879672 cd ...
- 【转载】BlockingQueue
前言: 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便 ...