定义和实现二叉树

/*

1.节点:节点包含一个数据元素和若干点到其子树分支

2.度节点:节点的数目已成为节点的子树

3.叶节点:为0的节点称为叶结点

4.分支节点:度不为0的节点称为分支节点

5.树的度:树中全部节点的度的最大值

6.二叉树:是n(n>=0)个有限节点构成的集合。n=0的树称为空二叉树。n=1的树仅仅有一个根结点;

n〉1的二叉树由一个根节点和至多两个互不相交的,分别称为左子树和右子树的子二叉树构成

二叉树不是有序树,这是由于,二叉树中某个节点即使仅仅有一个子树也要区分是左子树还是右子树;

而对于有序树来说。假设某个节点仅仅有一个子树就必然是第一个子树

7.二叉树全部结点的形态有5种:空节点,无左右子树节点,仅仅有左子树节点。仅仅有右子树节点和左右子树均存在的节点

8.满二叉树:在一棵二叉树中。假设全部分支节点都存在左子树和右子树,而且全部叶子节点都在同一层,则这种二叉树称作满二叉树

9.全然二叉树:假设一颗具有n个节点的二叉树的结构与满二叉树的前n个节点的结构同样,这种二叉树称为全然二叉树

10二叉树的性质:

(1):若规定根节点的层数为0,则一棵非空二叉树的第i层上最多有2^i(i>=0)个节点

(2):

若规定仅仅有根节点的二叉树的深度为0,则深度为k的二叉树的最大节点数是2^(k+1)-1(k>=-1)

(3):

对于一棵非空的二叉树。假设叶节点个数为n0,度为2的节点个数为n2。则有n0=n2+1

(4):

具有n个节点的全然二叉树的深度k为大于或等于ln(n+1)-1的最小整数

(5):

对于具有n个节点的全然二叉树,假设依照从上至下和从左至右的顺序对全部节点序号从0開始顺序编号,则对于序号为i(0<=i<n)的节点有:

假设i〉0。则序号为i节点的双亲节点的序号为(i-1)/2(/为整除);假设i=0。则序号为i节点为根节点,无双亲节点

假设2i+1<n,则序号为i节点的左孩子节点的序号为2i+1;假设2i+1>=n,则序号为i节点无左孩子

假设2i+2<n,则序号为i节点的右孩子节点的序号为2i+2;假设2i+2>=n。则序号为i节点无右孩子

11.二叉树的存储结构

1.二叉树的顺序存储结构

利用性质5,对于全然二叉树能够利用一维数组存储,假设不是全然二叉树。则能够补空节点,使成为全然二叉树在进行存储,

可是对于非全然二叉树,可能要浪费非常多的空间。

2.二叉树的链式存储结构

二叉树的链式存储结构就是用指针建立二叉树中节点之间的关系,二叉树最经常使用的链式存储结构是二叉链。二叉树的二叉链存储结构是一种经常使用的

二叉树存储结构。

二叉链存存储结构的长处时。结构简单。能够方便的构造不论什么形状的二叉树。并能够方便的实现二叉树的大多数操作。

二叉链存储结构的缺点是,查找当前节点的双亲节点操作实现比較麻烦

3.二叉树的仿真指针存储结构

利用一维数组和结构体实现。利用数组的下标进行仿真指针进行二叉树的操作

*/

<span style="font-size:18px;">#include<stdio.h>
#include<malloc.h>
typedef char DataType;

typedef struct Node{

	DataType data;//数据域
	struct Node *leftChild;//左子树指针
	struct Node *rightChild;//右子树指针
}BiTreeNode;//节点的结构体定义

//初始化
void Initiate(BiTreeNode **root){

	*root=(BiTreeNode *)malloc(sizeof(BiTreeNode));
	(*root)->leftChild=NULL;
	(*root)->rightChild=NULL;
}

//左插入节点
//若当前节点curr非空。则在curr的左子树插入元素值为x的新节点
//原curr所指节点的左子树成为新插入节点的左子树
//若插入成功。则返回新插入节点的指针,否则返回空指针
BiTreeNode *InsertLeftNode(BiTreeNode *curr,DataType x){

	BiTreeNode *s,*t;
	if(curr==NULL){//推断当前节点是否为空

		return NULL;//是空则返回NULL
	}

	t=curr->leftChild;//保存原curr所指节点的左子树
	s=(BiTreeNode *)malloc(sizeof(BiTreeNode));//创建节点空间
	s->data=x;//赋值
	s->leftChild=t;//新插入节点的左子树为原curr的左子树
	s->rightChild=NULL;//右子树为空

	curr->leftChild=s;//新节点成为curr的左子树
	return curr->leftChild;//返回新插入节点的指针
}

//右插入节点
//若当前节点curr非空。则在curr的右子树插入元素值为x的新节点
//原curr所指节点的右子树成为新插入节点的右子树
//若插入成功,则返回新插入节点的指针,否则返回空指针
BiTreeNode *InsertRightNode(BiTreeNode *curr,DataType x){

	BiTreeNode *s,*t;
	if(curr==NULL){//推断当前节点是否为空

		return NULL;//是空则返回NULL
	}

	t=curr->rightChild;//保存原curr所指节点的右子树
	s=(BiTreeNode *)malloc(sizeof(BiTreeNode));//创建节点空间
	s->data=x;//赋值
	s->rightChild=t;//新插入节点的右子树为原curr的右子树
	s->leftChild=NULL;//右子树为空

	curr->rightChild=s;//新节点成为curr的右子树
	return curr->rightChild;//返回新插入节点的指针
}

//左删除子树
//若curr非空,则删除curr所指节点的左子树
//若删除成功,则返回删除节点的双亲节点。否则返回空指针
BiTreeNode *DeleteLeftTree(BiTreeNode *curr){

//假设当前节点为空或者左子树为空则返回NULL
	if(curr==NULL||curr->leftChild==NULL){

		return NULL;
	}
//释放节点
	//Destroy(&curr->leftChild);
	curr->leftChild=NULL;//删除后,当前节点的左子树为NULL
	return curr;//返回删除节点的双亲节点

}

//右删除子树
//若curr非空。则删除curr所指节点的右子树
//若删除成功,则返回删除节点的双亲节点,否则返回空指针
BiTreeNode *DeleteRightTree(BiTreeNode *curr){

//假设当前节点为空或者右子树为空则返回NULL
	if(curr==NULL||curr->rightChild==NULL){

		return NULL;
	}
//释放节点
//	Destroy(&curr->rightChild);
	curr->rightChild=NULL;//删除后,当前节点的右子树为NULL
	return curr;//返回删除节点的双亲节点

}

void Visit(DataType item){

	printf("%c  ",item);
}

//前序遍历
/*
1.訪问根节点
2.前序遍历根节点的左子树
3.前序遍历根节点的右子树
*/
void PreOrder(BiTreeNode *root,void Visit(DataType item)){
//前序遍历二叉树root,訪问操作为Visit()函数
	if(root!=NULL){

		Visit(root->data);//訪问数据
        PreOrder(root->leftChild,Visit);//訪问左子树
		PreOrder(root->rightChild,Visit);//反问右子树
	}
}

//中序遍历
/*
1.中序遍历根节点的左子树
2.訪问根节点
3.中序遍历根节点的右子树
*/
void InOrder(BiTreeNode *root,void Visit(DataType item)){
//中序遍历二叉树root,訪问操作为Visit()函数
	if(root!=NULL){
        InOrder(root->leftChild,Visit);//訪问左子树
		Visit(root->data);//訪问数据
		InOrder(root->rightChild,Visit);//訪问右子树
	}
}

//后序遍历
/*
1.后序遍历根节点的左子树
2.后序遍历根节点的右子树
3.訪问根节点
*/
void PostOrder(BiTreeNode *root,void Visit(DataType item)){
//中序遍历二叉树root,訪问操作为Visit()函数
	if(root!=NULL){
        PostOrder(root->leftChild,Visit);//訪问左子树
		PostOrder(root->rightChild,Visit);//訪问右子树
		Visit(root->data);//訪问根节点数据

	}
}

//撤销二叉树操作
void Destroy(BiTreeNode **root){

	if((*root)!=NULL&&(*root)->leftChild!=NULL){

		Destroy(&(*root)->leftChild);
	}

	if((*root)!=NULL&&(*root)->rightChild!=NULL){

		Destroy(&(*root)->rightChild);
	}

	free(*root);

}

void PrintBiTree(BiTreeNode *root,int n){
//逆时针旋转90度。打印二叉树root。n为缩进层数,初始值为0

	int i;
	if(root==NULL){

		return ;//递归出口
	}
	PrintBiTree(root->rightChild,n+1);//遍历打印右子树
	//訪问根节点
	for(i=0;i<n-1;i++){

		printf("  ");
	}

	if(n>0){

		printf("---");
		printf("%c\n",root->data);
	}

	PrintBiTree(root->leftChild,n+1);//遍历打印右子树

}

//查找数据元素
BiTreeNode *Search(BiTreeNode *root,DataType x){
//查找数据元素x是否在二叉树root中
	//查找到则返回该节点指针。未查找到则返回空指针
	BiTreeNode *find=NULL;
	if(root!=NULL){

		if(root->data==x){

			find=root;
		}else{

			find=Search(root->leftChild,x);//在左子树中找
			if(find==NULL){

				find=Search(root->rightChild,x);//在右子树中找
			}
		}
	}

	return find;//返回查找标志

}

void main(){

	BiTreeNode *root,*p,*find;
	char x='E';
	Initiate(&root);//初始头指针
	p=InsertLeftNode(root,'A');//在头结点插入左子树
	p=InsertLeftNode(p,'B');//给'A'插入左子树
	p=InsertLeftNode(p,'D');//
	p=InsertRightNode(p,'G');//
	p=InsertRightNode(root->leftChild,'C');//给'A'插入右子树
    InsertLeftNode(p,'E');//
	InsertRightNode(p,'F');//

    PrintBiTree(root,0);//旋转90度打印树
    printf("前序遍历:");
    PreOrder(root->leftChild,Visit);
	printf("\n中序遍历:");
	InOrder(root->leftChild,Visit);
	printf("\n后序遍历:");
	PostOrder(root->leftChild,Visit);
	find=Search(root,x);
	if(find!=NULL){

		printf("\n数据元素%c在二叉树中\n",x);
	}else{

		printf("\n数据元素%c不在二叉树中\n",x);
	}

    Destroy(&root);

}</span>
				
时间: 2024-10-01 08:05:16

定义和实现二叉树的相关文章

重构二叉树

重构二叉树 这是剑指offer中关于二叉树重构的一道题.题目原型为: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 一.二叉树的数据结构 做题之前,我们先熟悉下二叉树的数据结构.其一,定义:二叉树是一个连通的无环图,并且每一个顶点的度不大于3.有根二叉树还要满足根结点的度不大于2.有了根结点之后,每个顶点定

【啊哈!算法】算法10:二叉树

二叉树是一种特殊的树.二叉树的特点是每个结点最多有两个儿子,左边的叫做左儿子,右边的叫做右儿子,或者说每个结点最多有两棵子树.更加严格的递归定义是:二叉树要么为空,要么由根结点.左子树和右子树组成,而左子树和右子树分别是一棵二叉树. 下面这棵树就是一棵二叉树. 二叉树的使用范围最广,一棵多叉树也可以转化为二叉树,因此我们将着重讲解二叉树. 二叉树中还有连两种特殊的二叉树叫做满二叉树和完全二叉树.如果二叉树中每个内部结点都有两个儿子,这样的二叉树叫做满二叉树.或者说满二叉树所有的叶结点都有同样的深

二叉树的四种遍历方法(递归、迭代)

一.前序遍历 前序遍历简单来讲,遍历顺序是:根节点-左子树-右子树 1.递归遍历 1 void preorder(BinTree *T) 2 { 3 if(T==NULL) 4 return; 5 cout << T->data; 6 preorder(T->left); 7 preorder(T->right); 8 } 2.迭代遍历(用栈实现) 1 void preorder2(BinTree *T) 2 { 3 //空树,直接返回 4 if(T==NULL) 5 ret

剑指offer——二叉树镜像

操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ 11 9 7 5 代码如下: /** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ imp

完全二叉树、理想二叉树满二叉树

完全二叉树(Complete Binary Tree): 设二叉树的深度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树. 理想二叉树(Perfect Binary Tree): 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的树称为理想二叉树.高度为h(从0开始算起)且包含2^(h+1)-1个节点的 二叉树是理想二叉树. 满二叉树(Full Binary Tree): 在国内实际上指的是上面提到的理想二叉树

数据结构(C实现)------- 遍历二叉树

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 二叉树是另一中树型结构,它的特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒. 根据二叉树的的递归定义可知,二叉树是由3个基本单元组成,根结点.左子树和右子树,因此,若能依次遍历这三部分,便是遍历了整个二叉树.假如以L.D.R分别表示遍历左子树.访问根结点和遍历右子树,则可能有DLR.LDR.LRD.DRL.RD

二叉树性质盘点

========================================================================================= 基础部分 ========================================================================================= 图论中的定义: 二叉树在图论中是这样定义的:二叉树是一个连通的无环图,并且每一个顶点的度不大于3.有根二叉树还要满足根结点的度不大

基本数据结构学习笔记——树与二叉树

1.树的形式化定义: 树(Tree)是由一个或多个结点组成的有限集合T,其中有一个特定的称为根的结点:其余结点可分为m(m≥0)个互不相交的有限集T1,T2,T3 ,…,Tm,每一个集合本身又是一棵树,且称为根的子树. 2.有关树的基本术语: 1.结点(Node):树中的元素,包含数据项及若干指向其子树的分支. 2.结点的度(Degree):结点拥有的子树数. 3.结点的层次:从根结点开始算起,根为第一层. 4.叶子(Leaf):度为零的结点,也称端结点. 5.孩子(Child):结点子树的根称

第十章 基本数据结构——二叉树

摘要 书中第10章10.4小节介绍了有根树,简单介绍了二叉树和分支数目无限制的有根树的存储结构,而没有关于二叉树的遍历过程.为此对二叉树做个简单的总结,介绍一下二叉树基本概念.性质.二叉树的存储结构和遍历过程,主要包括先根遍历.中根遍历.后根遍历和层次遍历. 1.二叉树的定义 二叉树(Binary Tree)是一种特殊的树型结构,每个节点至多有两棵子树,且二叉树的子树有左右之分,次序不能颠倒. 由定义可知,二叉树中不存在度(结点拥有的子树数目)大于2的节点.二叉树形状如下下图所示: 2.二叉树的