二叉树
二叉树的定义是递归的,一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两颗分别称为左子树和右子树、互不相交的二叉树组成。
该数据结构的难点有两个:
1、理解在递归算法中根结点指针保持不变,所以可以把该指针作为参数传入。变的事root->lNode及其下一个递归定义结点的指针值。
2、递归算法的执行流程。
二叉树的设计和实现:
1、二叉树采用链式存储,结点包含三个域,左结点链接域,右结点链接域,数据域。
2、分别用结构体和类来表示二叉树的结点和抽象数据类型。
3、重要的方法有:
1)二叉树的建立。
2)二叉树的输出。
3)前序、中序和后序遍历输出。
4、二叉树的定义是递归的,所以递归算法在儿叉树的程序中很有用。
二叉树的结点包含一个数据域和两个链接域,代码如下:
struct BTNode { int data; //数据域 BTNode *lNode,*rNode; //左右子女链接域 BTNode() { lNode=NULL; rNode=NULL; } BTNode(int x,BTNode *l=NULL,BTNode *r=NULL) { data=x; lNode=l; rNode=r; } };
二叉树的抽象数据类型由类来表示,代码如下:
class BinaryTree{ protected: BTNode * r; //定义根结点指针,Caution,注意这个指针的变化 int endValue; public: BinaryTree(){ r=NULL; //初始化根结点 endValue=0; } //构造函数 ~BinaryTree(){} //析构函数 //二叉树的建立 void InitBT(BTNode *&subTree); //建立二叉树 //二叉树的前序、中序和后序遍历输出 void POrderBT(BTNode *subTree); //前序遍历输出 void MOrderBT(BTNode *subTree); //中序遍历输出 void LOrderBT(BTNode *subTree); //后序遍历输出 //辅助函数 BTNode *getRTree()const{return r;} //获取根指针 };
二叉树的难点在于建立二叉树和对递归算法的理解,二叉树的建立,遍历算法如下:
void BinaryTree::InitBT(BTNode *&subTree) //subTree保持不变,subTree->lNode这个指针在变化 { int data; //值域 if(!cin.eof()) //结束标记Ctrl+Z,记住 { cin>>data; if(data!=endValue)//如果数值不为结束标记 { subTree=new BTNode(data); if(subTree==NULL)cout<<"内存分配错误"; InitBT(subTree->lNode); //递归建立左子树,深刻理解递归的含义 InitBT(subTree->rNode); //递归建立右子树 } else { subTree=NULL; //如果data==endValue,则结束创建 } } }
三种递归算法:
void BinaryTree::POrderBT(BTNode *subTree) { if(subTree!=NULL) { cout<<subTree->data<<endl; POrderBT(subTree->lNode); POrderBT(subTree->rNode); } } void BinaryTree::MOrderBT(BTNode *subTree) { if(subTree!=NULL) { MOrderBT(subTree->lNode); cout<<subTree->data<<endl; MOrderBT(subTree->rNode); } } void BinaryTree::LOrderBT(BTNode *subTree) { if(subTree!=NULL) { LOrderBT(subTree->lNode); LOrderBT(subTree->rNode); cout<<subTree->data<<endl; } }
测试数据为:
1 2 0 0 3 0 0
前序遍历结果为:
1 2 3
中序遍历结果为:
2 1 3
后序遍历结果为:
2 3 1
总结:
1、当一个问题比较复杂时,先在纸上画图,在纸上执行几步,可以很快找到思路。
2、断点调试技术很重要。