二叉树的定义和实现

/*

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>

二叉树的定义和实现,布布扣,bubuko.com

时间: 2024-11-04 19:46:52

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

二叉树节点定义

树是一种比较重要的数据结构,尤其是二叉树.二叉树是一种特殊的树,在二叉树中每个节点最多有两个子节点,一般称为左子节点和右子节点(或左孩子和右孩子),并且二叉树的子树有左右之分,其次序不能任意颠倒.二叉树是递归定义的,因此,与二叉树有关的题目基本都可以用递归思想解决,当然有些题目非递归解法也应该掌握,如非递归遍历节点等等.本文努力对二叉树相关题目做一个较全的整理总结,希望对找工作的同学有所帮助. 二叉树节点定义如下:struct BinaryTreeNode{ int m_nValue; Bina

数据结构--二叉树(定义与存储结构)

什么是二叉树 是具有n个节点的有限集合,由一个根节点和两棵互不相交二叉树组成.如图 从名字简单理解,就是具有2个树叉的树形结构,当然这不是绝对的,正如上图所示,我也可以只有一个树叉. 二叉树具有五种基本形态: (1)空二叉树 (2)只有一个根结点的二叉树 (3)只有左子树 (4)只有右子树 (5)既有左子树又有右子树 完全二叉树 这种二叉树,是二叉树中常用的专业术语,不是说一个完整的二叉树就是完全二叉树,这种二叉树叫满二叉树,如图 简单理解就像图片中,完全二叉树中每个节点的编号,都能映射到满二叉

-----下面是二叉树的定义-----储存---

说了那么多,下面该上正货了. 二叉树的定义:一个有穷的节点的集合 这个集合可以为空 若不为空,则它是有根节点和称为其左子树Tl和右子树的两个不相交的二叉树组成. 特殊的二叉树这个就不是完全二叉树

二叉树的定义

/** class for nodes used in a binary tree */ package dataStructures; public class BinaryTreeNode { // package visible data members Object element; BinaryTreeNode leftChild; // left subtree BinaryTreeNode rightChild; // right subtree // constructors p

树和二叉树

以下的内容做为学习笔记,复制别人的,感觉总结的比较好: 第5章 树和二叉树 本章中主要介绍下列内容:  1.树的定义和存储结构  2.二叉树的定义.性质.存储结构  3.二叉树的遍历.线索算法  4.树和二叉树的转换  5.哈夫曼树及其应用课时分配:     1.2两个学时,3四个学时,4两个学时, 5两个学时,上机两个学时重点.难点:     二叉树的遍历.线索算法.哈夫曼树及其应用 第一节 树 1.树的定义和基本运算1.1 定义    树是一种常用的非线性结构.我们可以这样定义:树是n(n≥

数据结构学习笔记(树、二叉树)

树(一对多的数据结构) 树(Tree)是n(n>=0)个结点的有限集.n=0时称为空树.在任意一颗非空树种: (1)有且仅有一个特定的称为根(Root)的结点: (2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1.T2........Tn,其中每一个集合本身又是一棵树,并且称为根的子树. 对于树的定义还需要强调两点:1.n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点.2.m>0时,子树的个数没有限制,但它们一定是互不相交的. 结点

数据结构——二叉树概述及其数组(顺序存储)表达法

树与二叉树: 什么是树呢?就是一个节点上会有很多分叉的数据结构.一般的,对于一棵树,我们需要的结构体为一个数据块和几个指针块,这就相当于很多个链表交织在了一起,实际上,链表也可以算是一种特殊的树,而我要讲的,也是一种特殊的树--二叉树. 对于树的各个节点,都有两个属性,称为度(degree),他的意思就是这个节点所拥有的子节点的数量.还有一个属性,称为深度(depth),指节点到根的距离. 什么是二叉树呢?顾名思义,就是度为二的树,它长这样: 如图所示,在链表中我们需要头(head),而在树中我

【数据结构】之二叉树的java实现

二叉树的定义: 二叉树是树形结构的一个重要类型.许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要. 二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成. 这个定义是递归的.由于左.右子树也是二叉树, 因此子树也可为空树.下图中展现了五种不同基本形态的二叉树. 其中 (a) 为空树, (b

Java数据结构-二叉树及其遍历

二叉树的定义:n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互相不相交的.分别称为根结点的左子树和右子树的二叉树组成. 二叉树的特点: 0<=度<=2: 左右子树是有顺序的,不能颠倒: 不论有几棵子树,也要区分它是左子树还是右子树. 二叉树的五种基本形态: 空二叉树: 只有一个根结点: 根结点只有左子树: 根结点只有右子树: 根结点既有左子树又有右子树. 举例3个结点的二叉树的形态有: 下面说一些特殊的二叉树. 斜树:所有的结点都只有左子树的二叉