来源:互联网 发布:梭哈游戏c 算法实现 编辑:程序博客网 时间:2024/05/16 11:12

树的表示法


#include<stdio.h>#include<stdlib.h>#include<string.h>typedef struct BiTNode{int data;struct BiTNode *lchild, *rchild;}BitNode, *BiTree;void Pre(BiTNode *root)                                     //树的先序遍历     
{if (root != NULL)                                             /*  递归遍历的思考{                                                                 1.打印结点printf("%d", root->data);                                 2.lchild!=NULL 则找到左孩子  重复步骤一,   否则,继续执行                                                                          3.rchild!=NULL 则找到右孩子  重复步骤一     否则,继续执行Pre(root->lchild);                                    */Pre(root->rchild);}}//树的二叉链表示法void main(){BitNode t1,t2,t3,t4,t5;memset(&t1,0, sizeof(BiTNode));memset(&t2, 0, sizeof(BiTNode));memset(&t3, 0, sizeof(BiTNode));memset(&t4, 0, sizeof(BiTNode));memset(&t5, 0, sizeof(BiTNode));t1.data = 1;t2.data = 2;t3.data = 3;t4.data = 4;t5.data = 5;t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;Pre(&t1);system("pause");}void main22(){BitNode * t1;BitNode * t2;BitNode * t3;BitNode * t4;BitNode * t5;t1 = (BitNode *)malloc(sizeof(BitNode));t2 = (BitNode *)malloc(sizeof(BitNode));t3 = (BitNode *)malloc(sizeof(BitNode));t4 = (BitNode *)malloc(sizeof(BitNode));t5 = (BitNode *)malloc(sizeof(BitNode));t1->lchild = t2;t1->rchild = t3;t2->lchild = t4;t3->lchild = t5;system("pause");}//树的三叉链表示法typedef struct SBiTNode{int data;struct BiTNode *lchild, *rchild;struct BiTNode *parent;}SBitNode, *SBiTree;//树的双亲链表表示法#define MAX_TREE_SIZE 100typedef struct BPTNode{int data;int parentPosition;    //指向双亲的指针   //数组下标char LRTag;            //左右孩子标志域   1代表左孩子,0代表右孩子}BPTNode;typedef struct BPTree{BPTNode nodes[100];    //因为节点之间是分散的,所以把节点存在数组中int num_node;          //节点数目int root;              //根节点的位置 //注意此域存储的是父亲节点在数组的下标}BPTree;void main33(){BPTree T;//AT.nodes[0].data = 1;T.nodes[0].parentPosition = -1;T.nodes[0].LRTag = -1;//BT.nodes[1].data = 2;T.nodes[1].parentPosition = 0;T.nodes[1].LRTag = 1;//CT.nodes[2].data = 3;T.nodes[2].parentPosition = 0;T.nodes[2].LRTag = 2;//DT.nodes[0].data = 4;T.nodes[0].parentPosition = 1;T.nodes[0].LRTag = 1;//ET.nodes[0].data = 5;T.nodes[0].parentPosition = 2;T.nodes[0].LRTag = 1;system("pause");}






计算树叶子节点的个数

思考:(中序遍历)

1.打印结点
2.判断左右结点是否为空,如果为空,则代表叶子节点,sum++,否则,继续执行3.lchild!=NULL 则找到左孩子  重复步骤一,   否则,继续执行4.rchild!=NULL 则找到右孩子  重复步骤一     否则,继续执行

#include<stdio.h>#include<stdlib.h>#include<string.h>typedef struct BiTNode{int data;struct BiTNode *lchild, *rchild;}BitNode, *BiTree;int sum = 0;                    放在里面每次都会被初始化为0int CountLeaf(BiTNode *root)               //计算树的叶子节点数目{if (root != NULL){if (root->lchild == NULL&&root->rchild == NULL){sum++;}if (root->lchild)          i       //如果root->lchild==NULL则不执行,所以不要写成!root->lchild{CountLeaf(root->lchild);}if (root->rchild){CountLeaf(root->rchild);}}return sum;}//树的二叉链表示法void main(){BitNode t1,t2,t3,t4,t5;memset(&t1,0, sizeof(BiTNode));memset(&t2, 0, sizeof(BiTNode));memset(&t3, 0, sizeof(BiTNode));memset(&t4, 0, sizeof(BiTNode));memset(&t5, 0, sizeof(BiTNode));t1.data = 1;t2.data = 2;t3.data = 3;t4.data = 4;t5.data = 5;t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;int sum=CountLeaf(&t1);printf("%d", sum);system("pause");}



计算树的高度    :通过递归求出左右子树的高度,然后比较左右子树,谁高就是树的高度

思想概述:(中序遍历)
首先,先判断第一层结点是否为空,若为空,则返回。若不为空,则先访问左子树,重新判断是否为空。结束后,再访问右子树,判断是否为空。
      通过递归到最后的叶子结点开始,判断左右子树的高度,并加1,返回给上一层。
int Depth(BitNode *T){int deptleft=0;int deptright=0;int deptval=0;if (T == NULL){deptval = 0;return deptval;}deptleft = Depth(T->lchild);deptright = Depth(T->rchild);return deptval = 1 + (deptleft > deptright ? deptleft : deptright);}


求copy树(中序遍历)

1.访问左子树,判断是否为空,然后返回给拟造的左结点,若不为空重复步骤1

2.访问右子树,判断是否为空,然后返回给拟造的右结点,若不为空重复步骤1

3.为拟造的结点分配内存,然后将拟造的左右节点复制给它

BitNode *CopyTree(BitNode *T){BitNode *newNode = NULL;BitNode *newLp = NULL;BitNode *newRp = NULL;if (T == NULL){return NULL;}if (T->lchild != NULL){newLp = CopyTree(T->lchild);}else{newLp = NULL;}if (T->rchild != NULL){newRp = CopyTree(T->rchild);}else{newRp = NULL;}newNode = (BitNode *)malloc(sizeof(BitNode)); if (newNode == NULL){return NULL;}newNode->lchild = newLp;newNode->rchild = newRp;newNode->data = T->data;return newNode;}



树的非递归遍历(中序遍历)


中序遍历的几种情况:
分析1:什么时候访问根,什么时候访问左子树,什么时候访问右子树。                当左子树为空或者左子树已经访问完毕以后,再访问根。访问完根以后,再访问右子树。

分析2:为什么是栈,而不是其他(比如说是队列)。                                          先走到的后访问,后走到的先访问,显然是栈结构

分析3:结点所有路径情况

            步骤1:如果结点有左子树,该结点入栈。

                        如果结点没有左子树,访问该结点。

            步骤2:如果结点有右子树,重复步骤1。

                        如果结点没有右子树(结点访问完毕),根据栈顶指示回退,访问栈顶元素,并访问右子树,重复步骤1.

                        如果栈为空,表示遍历结束。

注意,入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。


BitNode *goleft(BiTNode *T, stack<BitNode *> &s){if (T == NULL){return NULL;}while (T->lchild != NULL)                     //循环判断左子树是否为空,找到左子树的起始结点{s.push(T);T =T->lchild;}return T;}void Inorder2(BitNode *T){BitNode *t = NULL;stack<BiTNode *>s;t = goleft(T, s);while (t){printf("%d", t->data);if (t->rchild != NULL){t = goleft(t->rchild, s);}else if (!s.empty()){t = s.top();s.pop();}else{t = NULL;}}}



二叉树的创建


#法创建树

BiTNode *CreateBiThrTree(){BitNode *node = NULL;BiTNode *pL = NULL;BitNode *pR = NULL;char h;scanf("%c", &h);if (h == '#'){return NULL;}else{node = (BitNode *)malloc(sizeof(BiTNode));memset(node, 0, sizeof(BiTNode));node->data = h;pL = CreateBiThrTree();if (pL != NULL){node->lchild = pL;}else{node->lchild = NULL;}pR = CreateBiThrTree();if (pR != NULL){node->rchild = pR;}else{node->rchild = NULL;}}return node;}


二叉树的线索话(转载)

当二叉树使用链表表示时,用左右两个孩子指针可以找到左右孩子信息。我们可以用先序、中序、后序遍历二叉树,不同的遍历得到不同排列顺序的结点信息。只有在遍历的过程中才能得到某一结点的前驱与后继结点。
在n个结点的二叉树中,有2n个指针域,根节点不用指针域,其他(n-1)个结点只用了(n-1)个指针域,还有(n+1)个指针域空着没用,我们可以利用者空着的指针域来记录某种遍历下结点的前驱与后继。为了区分某个结点的指针域是指向孩子还是指向前驱/后继,要给结点添加的两个指针域添加标志,定义如下:

struct Node{        Node(int d):data(d),left(NULL),right(NULL),ltag(false),rtag(false){}         int data;        Node *left;        Node *right;      bool ltag;      bool rtag;  };  
当ltag=false时,left指向左孩子;当ltag=true时,left指向其前驱
当rtag=false是,right指向其右孩子;当rtag=true时,right指向其后继。
将一颗二叉树n+1个空指针域添加前驱或后继的过程就是线索话二叉树的过程。显然结点的前驱与后继只有在遍历的过程中才能得到,线索话二叉树的过程也就是遍历二叉树的过程。二叉树线索后,就可以通过左右孩子指针直接找到其前驱与后继,以中序线索话为例,当二叉树中序线索话后,
1、找某结点的前驱:
如果该结点的ltag=true,那么left指向的结点就是其前驱结点
如果该结点的ltag=false,那么该结点左子树最右边的结点就是其前驱结点。
2、找某结点后继
如果该结点的rtag=true,那么rtag指向的结点就是其后继结点
如果该结点的rtag=false,那个该结点的右子树的最左边的结点就是其后继结点。
二叉树线索话过程就是遍历过程,递归线索话时,需要一个全局变量来指向上一次遍历的结点(前驱结点)
Node *pre=NULL;//全局变量 ,刚刚遍历的结点   void BinTree::inorderThreading(Node *r)//中序线索话   {      if(r==NULL)          return;      inorderThreading(r->left);//递归线索话左子树       if(r->left==NULL)//如果左子树为空,则定义其前驱       {          r->ltag=true;          r->left=pre;      }      if(r->right==NULL)//右子树为空,先标记其指向后继,后继结点在下一次遍历才能得到,这里只是先标记           r->rtag=true;       if(pre!=NULL&&pre->rtag==true)//上次遍历的结点右子树指针被标记了,这次遍历的就是其后继           pre->right=r;      pre=r;//相当于遍历当前结点      inorderThreading(r->right);//线索话其右子树   }  


线索话后,如果要销毁二叉树,destroy函数要做点修改,当左右指针指向左右孩子时才可以递归销毁//销毁树   void BinTree::destroy(Node *r)  {      if(r==NULL)          return;      if(r->ltag==false)          destroy(r->left);      if(r->rtag==false)          destroy(r->right);      delete r;      r=NULL;  }  





原创粉丝点击