二叉树的简单操作(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 ...
随机推荐
- 图像旋转与图像缩放及Matlab代码实现
本周的作业是自己通过公式编写图像旋转与缩放的代码.今天先通过调用函数的方法来实现. 图像的旋转: A=imread('2.jpg'); J=imrotate(A, 30); subplot(1,2,1 ...
- 读《流畅的python》第一天
1.跟运算符无关的特殊方法了解: 2.跟运算符相关的特殊方法了解: 3.内置的序列类型分类: 容器序列 list.tuple 和 collections.deque 这些序列能存放不同类型的数据. 扁 ...
- 7.20 Codeforces Beta Round #8
链接:codeforces.com/contest/8 A 原因:RE,fantasy 的字符串的长度可能大于原字符串. B 题意:上下左右走,可能要避让障碍,问是否存在一个地图使得给定的路径为当前最 ...
- 王之泰201771010131《面向对象程序设计(java)》第十二周学习总结
第一部分:理论知识学习部分 第10章 图形程序设计 10.1 AWT与Swing简介 1.用户界面(User Interface) 的概念:用户与计算机系统(各种程序)交互的接口2.图形用户界面(Gr ...
- Python3 tkinter基础 Tk quit 点击按钮退出窗体
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- LINQ更新提示找不到行或行已更改的解决一例
LINQ对一行数据进行更改,怎么都无法提交,所有字段值都不是空值,后来看了实体,我发现更改的数据是主键,去数据库看这个字段却不是主键,原来是数据库取消主键了,实体代码没取消,因为更改了主键,所以无法更 ...
- excel 常用函数和实现功能经验总结积累
0.判断一个文本字符串中是否包含数字!/判断一个文本字符串是否是纯汉字! 公式=IF(LENB(A1)=2*LEN(A1),”都是汉字“,“含有非汉字字符”) 解释函数: LEN(A1)#返回文本字符 ...
- Vue-admin工作整理(二):项目结构个人配置
通过上一篇文章(Vue-admin工作整理(一):项目搭建)操作完毕后,基础项目已经搭建,下面就要对项目本身进行一下项目结构调整来符合自己的项目要求 1.首先要对package.json文件进行调整, ...
- 使用JSR-303进行校验
package com.ieou.comac.module.web.dto.employee; import lombok.Data; import javax.validation.constrai ...
- DAY 23 面向对象(二)
一.对象独有的名称空间 在产生对象时就赋初值 class Student: def __init__(self,name,sex): self.name = name self.sex = sex # ...