二叉树的简单操作(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 ...
随机推荐
- JS引擎的执行机制:探究EventLoop(含Macro Task和Micro Task)
在我看来理解好JS引擎的执行机制对于理解JS引擎至关重要,今天将要好好梳理下JS引擎的执行机制. 首先解释下题目中的名词:(阅读本文后你会对这些概念掌握了解) Event Loop:事件循环Micro ...
- 本地Git仓库和Github仓库的关联
1.我们首先创建一个文件夹(用于保存本地仓) 在我们想要创建的路径下右键鼠标打开Git Bash Here(创建一个文件夹,并进入文件夹) 2.通过命令git init把我们刚才创建的文件夹变成Git ...
- 【SSL Certificates】什么是数字证书(Certificates)?
本文涉及的相关问题,如果你的问题或需求有与下面所述相似之处,请阅读本文 ssl certificate 什么是ssl certificates? SSL Certificates 是一种使用数字加密技 ...
- HTTP之gRPC
gRPC 官方文档 gRPC 是一个高性能.开源和通用的 RPC 框架,面向移动和 HTTP/2 设计. gRPC 基于 HTTP/2 标准设计,带来诸如双向流.流控.头部压缩.单 TCP 连接上的多 ...
- <抽象工厂>比<工厂方法>多了啥
前言:仅当复习讨论,写得不好,多多指教! 上一篇文章<比多了啥>介绍了简单工厂模式和工厂方法模式.本篇文章则讲最后一个工厂----抽象工厂.如果对工厂方法比较模糊的,可以返回上一篇文章复习 ...
- 常看本地是否安装Git和maven工具
打开cmd命令行工具: 查看git where git C:\Users\jasqia>where gitC:\Program Files\Git\cmd\git.exe 安装maven后需要到 ...
- conda命令简单使用
Anaconda是一种Python语言的免费增值开源发行版,用于进行大规模数据处理.预测分析,和科学计算,致力于简化包的管理和部署.Anaconda使用软件包管理系统Conda进行包管理. 1.查看系 ...
- LayaAir引擎开发HTML5最简单教程(面向JS开发者)
LayaAir引擎开发HTML5最简单教程(面向JS开发者) 一.总结 一句话总结:开发游戏还是得用游戏引擎来开发,其实很简单啦 切记:开发游戏还是得用游戏引擎来开发,其实很简单,引擎很多东西都帮你做 ...
- snakemake使用小结
首先在linux 里配置conda 下载 wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.3.1-Linu ...
- iphone上mitmproxy证书设置
PC端安装mitmproxy并添加证书后,基本问题不大,都能正常运行起来 手机端iphone上下载安装mitmproxy证书: 1.手机和PC在同一个局域网中,设置wifi代理为PC端的ip,端口为m ...