赞
踩
1.二叉树知识点复习
二叉树是不存在度大于2的结点的树,且结点的子树有左右之分
⑴主要性质:
①二叉树的第i层最多有2^(i-1)个结点。
②一颗深度为k的二叉树最多有2^k-1个结点。
③设一颗二叉树的结点数为n,其中度为0,1,2的结点分别为n0,n1,n2,则有n0=n2+1.
(树枝数=n-1=n1+2*n2)
④具有n的结点的完全二叉树,其深度k为logn取下整+1。
⑵满二叉树:一颗k层的具有最多结点数的二叉树。
⑶完全二叉树:一颗k层的二叉树,其中前k-1层是满二叉树,最后一层的结点从左向右依次排列的树。
⑷二叉链表:一种包含三个域的结构体组成的链表,其中包含指向左子树的结点、数据域、指向右子树的结点。另外,一颗具有n的结点的二叉链表,有n+1个空链域 (树枝数=非空链域数=n-1)
⑸线索二叉树:将二叉树的空链域利用起来,存储二叉树在某种遍历次序下,该结点的前驱结点和后继结点的指针。所以,按照遍历方法,线索二叉树可分为前序、中序、后序线索二叉树。
线索二叉树的结点结构是:lchild+ltag+data+rtag+rchild
tag标记为0时,表示两个链域指向孩子
tag标记为1时,对于lchild,指向前驱结点;对于rchild,指向后继结点。
2.二叉树的建立和遍历代码
建立用前序遍历的方法输入二叉树的各个结点值,对于空结点可以指定一个字符来代表,我用的是数字0.
遍历主要有前中后序遍历和层次遍历。
前中后序遍历包含了递归和非递归方法,层次遍历使用队列。
⑴结点结构和二叉树类
struct Node { int data; Node *lchild; Node *rchild; }; class BiTree { private: Node* root; public: BiTree(); Node* getRoot(); Node* buildTree(); void visit(Node* t); void pre_traverse_recursion(Node *pos); void pre_traverse_non_recursion(); void in_traverse_recursion(Node *pos); void in_traverse_non_recursion(); void post_traverse_recursion(Node *pos); void post_traverse_non_recursion(); void level_traverse_queue(); };
⑵二叉树的建立
BiTree::BiTree() { root = buildTree(); } Node* BiTree::buildTree() { Node *cur; int data; cin >> data; if (data==0) { cur= NULL; } else { cur = new Node; //这里要不放在一开始就new 否则会有异常 cur->data = data; cur->lchild = buildTree(); cur->rchild = buildTree(); } return cur; }
⑶前序遍历
void BiTree::visit(Node* t) { cout << t->data << " "; } void BiTree::pre_traverse_recursion(Node *pos) { if (pos) { visit(pos); pre_traverse_recursion(pos->lchild); pre_traverse_recursion(pos->rchild); } } void BiTree::pre_traverse_non_recursion() { /* ①访问节点数据 ②结点入栈 ③访问左子树,重复①②③直至当前结点左子树为空 ④弹出栈顶结点,其右子树作为当前结点,回到① */ stack<Node*> s; s.push(root); Node*pos = root; while (!s.empty()) { while (pos) { visit(pos); pos = pos->lchild; if(pos) s.push(pos); } pos = s.top(); s.pop(); pos = pos->rchild; if (pos) s.push(pos); } }
⑷中序遍历
void BiTree::in_traverse_recursion(Node *pos) { if (pos) { in_traverse_recursion(pos->lchild); visit(pos); in_traverse_recursion(pos->rchild); } } void BiTree::in_traverse_non_recursion() { /* ①将当前结点入栈 ②访问当前结点的左子树,重复①②直至当前结点左子树为空 ③弹出栈顶结点为当前结点,访问结点数据 ④访问当前结点右子树,回到① */ Node* pos = root; stack<Node*> s; s.push(root); while (!s.empty()) { while (pos) { pos = pos->lchild; if(pos) s.push(pos); } pos = s.top(); s.pop(); visit(pos); pos = pos->rchild; if (pos) s.push(pos); } }
⑸后序遍历
void BiTree::post_traverse_recursion(Node *pos) { if (pos) { in_traverse_recursion(pos->lchild); in_traverse_recursion(pos->rchild); visit(pos); } } void BiTree::post_traverse_non_recursion() { /* 双栈法: ①根节点入栈1 ②当栈1非空时,进行以下操作:弹出栈1顶点压入栈2->当前顶点左子树若非空入栈1->当前结点右子树若非空入栈1 ③依次弹出栈2结点并访问 */ Node* pos = root; stack<Node*> s1, s2; s1.push(pos); while (!s1.empty()) { pos = s1.top(); s1.pop(); s2.push(pos); if (pos->lchild) s1.push(pos->lchild); if (pos->rchild) s1.push(pos->rchild); } while (!s2.empty()) { pos = s2.top(); s2.pop(); visit(pos); } }
⑹层次遍历
void BiTree::level_traverse_queue() { /* 队列 ①根节点入队 ②当队列非空时:访问队首结点并出队->结点的左子树(若非空)入队->结点的右子树(若非空)入队 */ queue<Node*> q; Node* pos = root; q.push(pos); while (!q.empty()) { pos = q.front(); q.pop(); visit(pos); if (pos->lchild) q.push(pos->lchild); if (pos->rchild) q.push(pos->rchild); } }
⑺测试
int main() { cout << "请按前序遍历的方式输入二叉树,空结点用0表示:" << endl; BiTree myTree; cout << "前序遍历(递归)"; myTree.pre_traverse_recursion(myTree.getRoot()); cout << endl; cout << "前序遍历(非递归)"; myTree.pre_traverse_non_recursion(); cout << endl; cout << "中序遍历(递归)"; myTree.in_traverse_recursion(myTree.getRoot()); cout << endl; cout << "中序遍历(非递归)"; myTree.in_traverse_non_recursion(); cout << endl; cout << "后序遍历(递归)"; myTree.post_traverse_recursion(myTree.getRoot()); cout << endl; cout << "后序遍历(非递归)"; myTree.post_traverse_non_recursion(); cout << endl; cout << "层次遍历"; myTree.level_traverse_queue(); cout << endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。