树形结构应该是贯穿整个数据结构的一个比较重要的一种结构,它的重要性不言而喻!

讲到树!一般都是讨论二叉树,而关于二叉树的定义以及概念这里不做陈诉,可自行搜索。

在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)的更多相关文章

  1. [Swift]LeetCode144. 二叉树的前序遍历 | Binary Tree Preorder Traversal

    Given a binary tree, return the preorder traversal of its nodes' values. Example: Input: [1,null,2,3 ...

  2. (二叉树 递归) leetcode 144. Binary Tree Preorder Traversal

    Given a binary tree, return the preorder traversal of its nodes' values. Example: Input: [1,null,2,3 ...

  3. 二叉树叶子顺序遍历 · binary tree leaves order traversal

    [抄题]: 给定一个二叉树,像这样收集树节点:收集并移除所有叶子,重复,直到树为空. 给出一个二叉树: 1 / \ 2 3 / \ 4 5 返回 [[4, 5, 3], [2], [1]]. [暴力解 ...

  4. LeetCode 144. 二叉树的前序遍历(Binary Tree Preorder Traversal)

    144. 二叉树的前序遍历 144. Binary Tree Preorder Traversal 题目描述 给定一个二叉树,返回它的 前序 遍历. LeetCode144. Binary Tree ...

  5. (二叉树 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 ...

  6. [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 ...

  7. [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, ...

  8. [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 ...

  9. [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 ...

随机推荐

  1. java和js中int和String相互转换常用方法整理

    java中int和String的相互转换常用的几种方法: int  > String int i=10;String s="";第一种方法:s=i+""; ...

  2. 629D - Babaei and Birthday Cake

    题意:给定n个圆柱体的半径和高,输入顺序即圆柱体的编号顺序.现在规定,只有编号和体积均大于另一个圆柱体,才能放到另一个圆柱体的体积上面.求能叠加的最大体积是多少. 酝酿了我三天,才理解.自己敲个代码, ...

  3. 从0开始的Hexo主题制作

    从0开始的Hexo主题制作 从零开始制作 Hexo 主题 H2O主题 先坑着

  4. 【做题】ECFinal2018 J - Philosophical … Balance——dp

    原文链接 https://www.cnblogs.com/cly-none/p/ECFINAL2018J.html 题意:给出一个长度为\(n\)的字符串\(s\),要求给\(s\)的每个后缀\(s[ ...

  5. bzoj2131 免费的馅饼——树状数组优化dp

    中文题目,问你最后能最多够得到多少价值的馅饼.因为宽度10^8且个数为10^5.所以不可以用dp[x][y]表示某时间某地点的最大权值. 假设你在x点处接到饼后想去y点接饼.那么需要满足的条件是t[y ...

  6. 微信小程序http连接访问解决方案

    HTTP + 加密 + 认证 + 完整性保护 = HTTPS,小程序考虑到信息安全的问题,选用了更为稳定安全的https 来进行信息传递. HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全 ...

  7. 后台获取POST方式提交的JSON格式数据

    1.直接使用request.getParamater()的方法获取(这种取参方式对于POST和GET的提交方式均适用): 2.通过请求体的IO流获取参数(这种方式只能用于POST,因为GET方式没有请 ...

  8. C#多线程和线程池

    1.概念  1.0 线程的和进程的关系以及优缺点 windows系统是一个多线程的操作系统.一个程序至少有一个进程,一个进程至少有一个线程.进程是线程的容器,一个C#客户端程序开始于一个单独的线程,C ...

  9. If嵌套

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. 雷林鹏分享:jQuery EasyUI 数据网格 - 设置排序

    jQuery EasyUI 数据网格 - 设置排序 本实例演示如何通过点击列表头来排序数据网格(DataGrid). 数据网格(DataGrid)的所有列可以通过点击列表头来排序.您可以定义哪列可以排 ...