您的位置:首页 > 其它

C 二叉树

2015-09-16 09:53 218 查看
二叉树表示法
P127页
/*
typedef struct BiTNode
{
int        data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
*/

struct BiTNode
{
int        data;
struct BiTNode *lchild, *rchild;
};

typedef struct BiTNode BiTNode;
typedef struct BiTNode * BiTree;

树的三叉链表表示


//三叉链表
typedef struct TriTNode
{
int data;
//左右孩子指针
struct TriTNode *lchild, *rchild;
struct TriTNode *parent;
}TriTNode, *TriTree;

双亲链表法
//双亲链表
#define MAX_TREE_SIZE 100
typedef struct BPTNode
{
int data;
int parentPosition; //指向双亲的指针 //数组下标
char LRTag; //左右孩子标志域
}BPTNode;

typedef struct BPTree
{
BPTNode nodes[100]; //因为节点之间是分散的,需要把节点存储到数组中
int num_node;  //节点数目
int root; //根结点的位置 //注意此域存储的是父亲节点在数组的下标
}BPTree;
//用这个数据结构能表达出一颗树,为什么?
4.4.3二叉树的遍历


二叉树编程实践
基本操作
typedef struct node{
int  data;
struct node *lchild,*rchild;
} NODE;
NODE *root;

DLR(NODE *root )
{
if (root) //非空二叉树
{
printf(“%d”,root->data); //访问D
DLR(root->lchild); //递归遍历左子树
DLR(root->rchild); //递归遍历右子树
}
}

中序遍历算法
LDR(NODE *root)
{ if(root !=NULL)
{  LDR(root->lchild);
printf(“%d”,root->data);
LDR(root->rchild);
} }

后序遍历算法
LRD (NODE *root)
{if(root !=NULL)
{LRD(root->lchild);
LRD(root->rchild);
printf(“%d”,root->data);
} }


计算二叉树中叶子结点的数目
int sum = 0; //全局变量
DLR_CountLeafNum(NODE *root)//采用中序遍历的递归算法
{
if ( root)  //非空二叉树条件,还可写成if(root !=NULL )
{   if(!root->lchild&&!root->rchild)  //是叶子结点则统计并打印
{   sum++;     printf("%d\n",root->data);  }
DLR_CountLeafNum(root->lchild); //递归遍历左子树,直到叶子处;
DLR_CountLeafNum(root->rchild);}//递归遍历右子树,直到叶子处;
} return(0);
}
思想:    1)求根结点左子树的叶子结点个数,累计到sum中,求根结点右子树的叶子结点个数累计到sum中。
2)若左子树还是树,重复步骤1;若右子树还是树,重复步骤1。
3)全局变量转成函数参数
4)按照先序、中序、后序方式计算叶子结点,
===》三种遍历的本质思想强化:访问结点的路径都是一样的,计算结点的时机不同。


求二叉树的深度
思想:    1)求根结点左子树高度,根结点右子树高度,比较的子树最大高度,再+1。
2)若左子树还是树,重复步骤1;若右子树还是树,重复步骤1。


完全Copy二叉树
思想:    1)malloc新结点,
2)拷贝左子树,拷贝右子树,让新结点连接左子树,右子树
3)若左子树还是树,重复步骤1、2;若右子树还是树,重复步骤1、2。


树的非递归遍历(中序遍历)
中序 遍历的几种情况
分析1:什么时候访问根、什么时候访问左子树、什么访问右子树
当左子树为空或者左子树已经访问完毕以后,再访问根
访问完毕根以后,再访问右子树。
分析2:非递归遍历树,访问结点时,为什么是栈,而不是其他模型(比如说是队列)。
先走到的后访问、后走到的先访问,显然是栈结构
分析3:结点所有路径情况
步骤1:
如果结点有左子树,该结点入栈;
如果结点没有左子树,访问该结点;
步骤2:
如果结点有右子树,重复步骤1;
如果结点没有右子树(结点访问完毕),根据栈顶指示回退,访问栈顶元素,并访问右子树,重复步骤1
如果栈为空,表示遍历结束。
注意:入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。
分析4:有一个一直往左走入栈的操作,中序遍历的起点


3、#号法编程实践
利用前序遍历来建树(结点值陆续从键盘输入,用DLR为宜)
Bintree createBTpre( )
{
Bintree T;
char ch;
scanf(“%c”,&ch);
if(ch==’#’)
T=NULL;
else
{   T=( Bintree )malloc(sizeof(BinTNode));
T->data=ch;
T->lchild=createBTpre();
T->rchild=createBTpre();
}
return T;
}

//后序遍历销毁一个树
void  BiTree_Free(BiTNode* T)
{
BiTNode *tmp = NULL;
if (T!= NULL)
{
if (T->rchild != NULL) BiTree_Free(T->rchild);
if (T->lchild != NULL) BiTree_Free(T->lchild);
if (T != NULL)
{
free(T);
T = NULL;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: