二叉树的存储结构有两种。第一种是顺序存储结构。若对一棵具有n个结点的完全二叉树的所有结点按层从上到下,每层从左到右的顺序依次对结点从1开始编号,则编号为i的结点具有以下性质:
1.i=1的结点为二叉树的根结点。
2.如果i>1,则结点i的双亲结点编号为i/2(向下取整)。
3.如果2i<=n,则编号为i的结点的左孩子结点编号为2i;如果2i>n,则该结点没有左孩子。
4.如果2i+1<=n,则编号为i的结点的右孩子结点编号为2i+1;如果2i+1>n,则该结点没有右孩子。
利用以上的性质,我们可以开辟一块连续的储存空间(ie.数组),将结点编号与数组下标对应,主要对于非完全二叉树,不存在的结点在数组中也要相应地留空,尽管这会导致空间的浪费。
代码如下:
1 //顺序存储实现二叉树,结点编号与数组下标对应 2 template <typename Type> class SeqBT{ 3 private: 4 int max_size; 5 Type *data; 6 public: 7 SeqBT(int input_size){ 8 max_size=input_size; 9 data=new Type[max_size]; 10 } 11 ~SeqBT(){ 12 delete[] data; 13 } 14 };
第二种存储结构是链式存储结构,即结点中包括两个指针指向左右孩子结点。在这种结构下,二叉树的遍历可以通过递归实现,根据输出顺序可分为先序、中序、后序和层序遍历。这里先介绍前三种以及如何通过先序和中序遍历的结果建立二叉树。代码如下:
1 //链式存储实现二叉树 2 //结点的定义 3 template <typename Type> class Node{ 4 public: 5 Type data; 6 Node<Type> *lchild; 7 Node<Type> *rchild; 8 Node(Type _data){ 9 data=_data; 10 lchild=NULL; 11 rchild=NULL; 12 } 13 ~Node(){ 14 if(lchild!=NULL){ 15 delete lchild; 16 } 17 if(rchild!=NULL){ 18 delete rchild; 19 } 20 } 21 //先序遍历 22 void preorder(){ 23 cout<<data<<" "; 24 if(lchild!=NULL){ 25 lchild->preorder(); 26 } 27 if(rchild!=NULL){ 28 rchild->preorder(); 29 } 30 } 31 //中序遍历 32 void inorder(){ 33 if(lchild!=NULL){ 34 lchild->inorder(); 35 } 36 cout<<data<<" "; 37 if(rchild!=NULL){ 38 rchild->inorder(); 39 } 40 } 41 //后序遍历 42 void postorder(){ 43 if(lchild!=NULL){ 44 lchild->postorder(); 45 } 46 if(rchild!=NULL){ 47 rchild->postorder(); 48 } 49 cout<<data<<" "; 50 } 51 52 //用先序和中序遍历建立二叉树 53 Node* build(const string &pre_str,const string &in_str, int len){ 54 //先序遍历的第一位一定是当前树的根节点 55 Node *p=new Node(pre_str[0]-'0'); 56 //找到根节点在中序遍历中的位置 57 //根的左边就是左子树,右边的就是右子树 58 int pos=in_str.find(pre_str[0]); 59 //若左子树不为空,递归建立左子树 60 if(pos>0){ 61 p->lchild=build(pre_str.substr(1,pos),in_str.substr(0,pos),pos); 62 } 63 //若右子树不为空,递归建立右子树 64 if(len-pos-1>0){ 65 p->rchild=build(pre_str.substr(pos+1),in_str.substr(pos+1),len-pos-1); 66 } 67 //返回根节点 68 return p; 69 } 70 }; 71 72 template <typename Type> class BinaryTree{ 73 private: 74 Node<Type> *root; 75 public: 76 BinaryTree(){ 77 root=NULL; 78 } 79 ~BinaryTree(){ 80 delete root; 81 } 82 83 //利用先序和中序建树的构造函数 84 BinaryTree(const string &pre_str, const string &in_str, int len){ 85 root=root->build(pre_str,in_str,len); 86 } 87 88 //for testing 89 void build_demo() { 90 root = new Node<int>(1); 91 root->lchild = new Node<int>(2); 92 root->rchild = new Node<int>(3); 93 root->lchild->lchild = new Node<int>(4); 94 root->lchild->rchild = new Node<int>(5); 95 root->rchild->rchild = new Node<int>(6); 96 } 97 void preorder(){ 98 if(root!=NULL){ 99 root->preorder(); 100 } 101 } 102 void inorder(){ 103 if(root!=NULL){ 104 root->inorder(); 105 } 106 } 107 void postorder(){ 108 if(root!=NULL){ 109 root->postorder(); 110 } 111 } 112 113 }; 114 115 //for testing 116 int main() { 117 BinaryTree<int> binarytree1; 118 binarytree1.build_demo(); 119 binarytree1.preorder(); 120 cout<<endl; 121 binarytree1.inorder(); 122 cout<<endl; 123 binarytree1.postorder(); 124 cout<<endl; 125 126 string pre_str = "136945827"; 127 string in_str = "963548127"; 128 BinaryTree binarytree2(pre_str,in_str,in_str.length()); 129 binarytree2.postorder(); 130 cout<<endl; 131 132 return 0; 133 }