C语言基本数据结构之二(二叉树的三种遍历,节点数以及深度算法)

关于二叉树的定义,网上有比较好的介绍,在这里就简单介绍二叉树的一些性质

二叉树的基本性质

1)二叉树的第i层上至多有 2^(i-1)(i ≥1)个结点;
2)深度为 h 的二叉树中至多含有 2^h – 1 个结点;
3)若在任意一棵二叉树中,有 n0 个叶子结点,有 n2 个度为 2 的结点,则:n0 = n2 + 1。

特殊形式的二叉树

1)满二叉树
特点:深度为h且含有2h-1个结点的二叉树,为满二叉树。图示满二叉树,结点编号为自上而下,自左而右。
2)完全二叉树(左图)
特点:指深度为k的,有n个结点的,且每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应,完全一致,则为完全二叉树。(右图)


3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为0,-1,1。

关于二叉树的存储方式(顺序和链式存储)

(1) 顺序存储结构

用一组连续的存储单元存放二叉树的数据元素。结点在数组中的相对位置蕴含着结点之间的关系。
其所需的存储单元数为:2^h-1= 24-1 = 15,若父结点在数组中i下标处,其左孩子在2*i处,右孩子在2*i+1处。


(2)链式存储结构
链式存储结构的每个结点由数据域、左指针域和右指针域组成。左指针和右指针分别指向下一层的二叉树
              

放二叉树的数据元素。结点在数组中的相对位置蕴含着结点之间的关系

关于二叉树的三种遍历方式

(1)先序遍历(D L R): 访问根结点,按先序遍历左子树,按先序遍历右子树。
(2)中序遍历(L D R): 按中序遍历左子树,访问根结点,按中序遍历右子树。
(3)后序遍历(L R D): 按后序遍历左子树,按后序遍历右子树,访问根结点。

还是直接上代码吧~~这里用的是链式存储结构,相对顺序存储结构,前者所需存储容量更小,更易于理解~~

二叉树的结构体
struct Tree{
	int data;//这里可以改成你想要的数据类型
	tree *left;
	tree *right;
};

初始化二叉树,添加数据
tree *initTree(tree* H){
	H = NULL;
	int data = 0;
	printf(" 输入data \n ");
	scanf("%d",&data);
	if(data!=0){
		H = (tree *)malloc(sizeof(tree));
		H->data = data;
		printf(" t data is %d \n",H->data);
		printf(" 请输入左字树data \n");
		H->left = initTree(H->left);
		printf(" 请输入右字树data \n");
		H->right = initTree(H->right);
	}
	return H;
}

先序,中序,后序遍历的递归算法( ps:递归真是个好东西~~,写出来的代码就是简洁~~)
/*
先序遍历
*/
void DLR(tree* T){
	if(NULL!=T){
		printf(" data is %5d \n ",T->data);
		DLR(T->left);
		DLR(T->right);
	}
}
/*
中序遍历
*/
void LDR(tree* T){
	if(NULL!=T){
		LDR(T->left);
		printf(" data is %5d \n",T->data);
		LDR(T->right);
	}
}
/*
后序遍历
*/
void LRD(tree* T){
	if(NULL!=T){
		LRD(T->left);
		LRD(T->right);
		printf(" data is %5d \n",T->data);
	}
}

二叉树的层次遍历
void LOrder(tree* T) /* 层次遍历二叉树T */
{ treeQ[MAXNODE];     /* 辅助队列,MAXNODE为最大的队列容量 */ 
  int f,r;               /* 队列的首、尾指针 */
  if (T == NULL) return; /* 空树,直接返回 */
  f = -1;                /* 队首,队尾指针初始化 */ 
  r = 0;
  Q[r] = T;              /* 树根进队 */
  while( f != r )
   { f++;
     printf(“%d”,Q[f]->data);   /* 访问队首结点的数据域 */
     if (Q[f]->left!= NULL)  /* 将队首结点的左孩子入队列 */
      { r++;
        Q[r] = Q[f]->left;  }
     if (Q[f]->right!= NULL)  /* 将队首结点的右孩子入队列 */
      { r++;
        Q[r] = Q[f]->right;  }
   } 
}


计算二叉树的深度;
/*计算树的深度*/
int deep(tree* H){
	int d1 = 0;
	int d2 = 0;
	if(NULL!=H){
		d1 = deep(H->left) +1;
		d2 = deep(H->right) +1;
	}
	return d1>=d2? d1:d2;
}

计算总的节点数和叶子数
//计算总的节点数
int node(tree* H){
	int n = 0;
	if(NULL!=H){
		n = node(H->left)+node(H->right) +1;
	}
	return n;
}
//计算叶子节点
int CountLeaf(tree* H){
	if(NULL==H) return 0;
	if((NULL==H->left)&&(NULL==H->right)){
		return 1;
	}
	return CountLeaf(H->left) + CountLeaf(H->right);
}

全部代码如下
#include <stdio.h>
#include <malloc.h>
typedef  struct Tree tree ;
/*
定义二叉树的结构体
*/
struct Tree{
	int data;
	tree *left;
	tree *right;
};
tree *p[100];
/*
初始化二叉树
*/
tree *initTree(tree* H){
	H = NULL;
	int data = 0;
	printf(" 输入data \n ");
	scanf("%d",&data);
	if(data!=0){
		H = (tree *)malloc(sizeof(tree));
		H->data = data;
		printf(" t data is %d \n",H->data);
		printf(" 请输入左字树data \n");
		H->left = initTree(H->left);
		printf(" 请输入右字树data \n");
		H->right = initTree(H->right);
	}
	return H;
}
/*
先序遍历
*/
void DLR(tree* H){
	if(NULL!=H){
		printf(" data is %5d \n ",H->data);
		DLR(H->left);
		DLR(H->right);
	}
}

/*
中序遍历
*/
void LDR(tree* H){
	if(NULL!=H){
		LDR(H->left);
		printf(" data is %5d \n",H->data);
		LDR(H->right);
	}
}

/*
后序遍历
*/
void LRD(tree* H){
	if(NULL!=H){
		LRD(H->left);
		LRD(H->right);
		printf(" data is %5d \n",H->data);
	}
}

/*
计算树的深度
*/
int deep(tree* H){
	int d1 = 0;
	int d2 = 0;
	if(NULL!=H){
		d1 = deep(H->left) +1;
		d2 = deep(H->right) +1;
	}
	return d1>=d2? d1:d2;
}
//计算总的节点数
int node(tree* H){
	int n = 0;
	if(NULL!=H){
		n = node(H->left)+node(H->right) +1;
	}
	return n;
}
//计算叶子节点
int CountLeaf(tree* H){
	if(NULL==H) return 0;
	if((NULL==H->left)&&(NULL==H->right)){
		return 1;
	}
	return CountLeaf(H->left) + CountLeaf(H->right);
}
void main(){
	tree *H = (tree*)malloc(sizeof(tree)) ;
	 H = initTree(H);
	 printf("DLR : \n");
	 DLR(H);
	 printf("LDR : \n");
	 LDR(H);
	 printf("LRD : \n");
	 LRD(H);
	 printf("\n deep is %5d \n ",deep(H));
	 printf(" CountLeaf is %5d \n",CountLeaf(H));
	 printf(" node number is %5d  \n",node(H));
}


大概就这么多了。想起了在补充吧~~




3)平衡二叉树

特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为0,-1,1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值