二叉树的建立和遍历(总结)

来源:互联网 发布:科比季后赛数据统计 编辑:程序博客网 时间:2024/04/27 23:32

通过递归和非递归的方法建立、遍历二叉树。遍历分为深度优先遍历和广度优先遍历,前者包涵先序遍历、中序遍历和后序遍历三种。对于递归创建和遍历二叉树,两者很类似,注意什么时候返回上一层。如我这里的返回条件是达到最大深度和树的最大尺寸。
非递归创建二叉树,采用线性结构如数组、队列存储。采用数组比较好处理root及其左右孩子之间的关系。非递归遍历二叉树,由于需要处理好返回到根节点的时刻,采用栈先进后出的原则,将根节点及其所有左孩子按先后顺序压入栈,等到没有左孩子时,再从栈顶弹出最底层的根节点,一层层往上。对于宽度优先遍历,也是通过线性结构按顺序存储需要遍历的节点。
特别需要注意的是:数组越界问题!!!在给出的源代码中,有5处地方是我已经犯过错误的,都是segment fault。原因在于:即使数组的元素下标超界,该元素会覆盖栈的其他内存,即其有内存地址和数值,很多时候不注意避免却用该元素是否为空来做判断,往往出错,一旦覆盖掉了需要跳转的下一个指令的内存地址,程序就会崩溃。这5个地方分别是:
(1)GetValue()中尽量避免使用scanf函数为变量输入数值,改用cin,如1。因为这里明明只能输入5个值,scanf却要求输入6个值,多余的这个数值会影响其他数组。
(2)CreateLoop()中采用数组存储各节点,在各根节点连接其左右孩子时,为了防止数组越界,限制左右孩子下标的双重评判标准,左孩子下标正常,则连接左孩子,然后再看右孩子的下标是否正常,如21, 22。
(3)PreorderLoop()采用栈存储根节点和左孩子,为防止数组越界,采用ptr是否为空和栈是否为空作为双重标准,如3。
(4)CreateRecursive为了防止数组越界给多余元素以内存,而妨碍到后续的遍历,如41,42,会给不满足条件的节点空值的决定。
(5)WidePriority()中为了防止 数组越界,采用三重标准如5。

<上述的1,21,22,3,41,42,5都在源程序中有标注>

源代码如下:

#include <iostream>#include <stdio.h>#include <stack>#include<math.h>using namespace std;typedef struct BINODE //BINODE structure{   char data;   BINODE *lchild, *rchild;}*BITREE;BINODE* NewNode(char i){    BINODE *newnode = new BINODE;    newnode->data = i;    newnode->lchild=NULL;    newnode->rchild=NULL;    return newnode;}class bitree{  BINODE *root;  //default as private  int TREE_SIZE, DEPTH; public:   bitree(int n)   {    TREE_SIZE = n;        int tmp = log10(TREE_SIZE+1)/log10(2);        DEPTH = (tmp<(float)(log10(TREE_SIZE+1)/log10(2)))?(tmp+1):tmp;  }   char *GetValue( );   void CreateLoop();   void CreateRecursive(BITREE &node, int dep);   void PreorderLoop();//as stack   void PreorderRecursive(BITREE &node);   //... delete mid-order and postorder functions   void WidePriority();};char* bitree::GetValue(){   char arr[TREE_SIZE];   printf("Please input %d numbers for the bitree:\n",TREE_SIZE);   for(int i=0; i<TREE_SIZE; i++)//input numbers with enter to end   //  scanf("%c\t",&arr[i]);       cin>>&arr[i];       //1,避免使用scanf输入函数,因为会占用后一位内存   return &arr[0];  //return the head of array}void bitree::CreateLoop(){   char *arr=GetValue();   printf("array value: %s %c \n",arr, arr[2]);   /* tree */   BINODE *tree[TREE_SIZE];   for(int i=0; i<TREE_SIZE; i++)   {        tree[i]= NewNode(arr[i]);   }   for(int i=0, j=1; j<TREE_SIZE; i++,j=2*i+1) //21, get left and right childs for root    {       tree[i]->lchild = tree[j];       if(j<(TREE_SIZE-1)) //22           tree[i]->rchild = tree[j+1];   }     root = tree[0];}void bitree::PreorderLoop(){    stack<BINODE*> tree; //push each root to stack, FILO     BINODE *ptr = root;    while(ptr||!tree.empty()) //3    {    while(ptr)    {        printf("%c\t",ptr->data);        tree.push(ptr);        ptr = ptr->lchild;    }    if(!tree.empty())    {        ptr= tree.top();        tree.pop();        ptr=ptr->rchild;    }    }} void bitree::CreateRecursive(BITREE &node, int dep){    static int count=0; //41     if(count==TREE_SIZE)     {  node=NULL;  return;}  //42in case of index in arr extend     if(dep>DEPTH)     {  node=NULL;  //43    return;}     node = new BINODE;     cin>>node->data;     count++;     if(root==NULL)    root=node;     CreateRecursive(node->lchild,dep+1);     CreateRecursive(node->rchild,dep+1);}void bitree::PreorderRecursive(BITREE &node){    if(node)    {    printf("%c\t",node->data);    PreorderRecursive(node->lchild);    PreorderRecursive(node->rchild);    }}void bitree::WidePriority(){   BINODE *tree[TREE_SIZE];//ignore root   BINODE *ptr=root;   int i=1;   int j=1;   while(ptr&&(i<TREE_SIZE||j<=i)) //5,in case of index in arr extends   {      printf("%c\t",ptr->data);      if(ptr->lchild)    tree[i++]=ptr->lchild;      if(ptr->rchild)    tree[i++]=ptr->rchild;      ptr = tree[j++];   }   printf("  Wide Priority Transerval finished!\n");}int main(){   bitree tree1(5), tree2(5);   tree1.CreateLoop();   tree1.PreorderLoop();   printf("TREE1 finished!\n");   tree1.WidePriority();   BINODE *node;   tree2.CreateRecursive(node,1);   tree2.PreorderRecursive(node);   printf("TREE2 finished!\n");   tree2.WidePriority();   return 0;}
0 0
原创粉丝点击