树是一种用于描述一对多的数据结构,比如文件目录结构就可以用树来描述。树的定义如下:
树是n(n≥0)个结点的有限集合,n=0时称为空树,在任意一棵非空树中:
注意两点,根结点是唯一的,子树互不相交。
二叉树是一种常用的树,它只有两个子结点,除此外多叉树也可能用到,如果一个集合里包含不止一颗树,则称为森林。
树的存储分为顺序存储和链式存储。顺序存储是指通过数组来存储树,分为双亲表示法,孩子表示法,双新孩子表示法,如下:
链式存储使用链表来存储树,分为孩子链表表示法和孩子兄弟表示法,如下:
使用孩子兄弟表示法,长子当左结点,兄弟当右结点。
左结点作为长子,右斜线作为兄弟。
把森林中的每棵树的根当成兄弟结点,先把每个树转换成二叉树,然后再将每棵树的根连接在右斜线上。
右斜线上的每个结点作为一棵树的根,将每棵二叉树还原为树。
2k-1
个结点。2k-1
个结点。n0
,度为2的结点数为n2
,则n0 = n2 + 1
。log2n+1
。i
的结点,其左孩子编号必为2i
,右孩子编号必为2i+1
,其父结点编号必为i/2
,应用:二叉树的遍历按照根、左子树、右子树的访问先后顺序不同,一共有6种访问方案。但实际使用时,一般都固定先访问左子树再访问右子树,在这个前提下,根据根结点的访问顺序,一共有三种访问方案:前序遍历(中-左-右),中序遍历(左-中-右),后序遍历(左-右-中)。
接下来以下面这个二叉树定义来进行遍历:
struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode() : val(0), left(nullptr), right(nullptr) {} TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} }; |
递归方式:
void preorder(TreeNode *root) { if(!root) return; cout << root->val << " "; preorder(root->left); preorder(root->right); } |
非递归方式:
void preorder(TreeNode *root) { stack<TreeNode*> stk; TreeNode *cur = root; while(cur || !stk.empty()) { while(cur) { cout << cur->val << " "; stk.push(cur); cur = cur->left; } cur = stk.top(); stk.pop(); cur = cur->right; } } |
递归方式:
void inorder(TreeNode *root) { if(!root) return; preorder(root->left); cout << root->val << " "; preorder(root->right); } |
非递归方式:
void inorder(TreeNode *root) { stack<TreeNode*> stk; TreeNode *cur = root; while(cur || !stk.empty()) { while(cur) { stk.push(cur); cur = cur->left; } cur = stk.top(); stk.pop(); cout << cur->val << " "; cur = cur->right; } } |
递归方式:
void postorder(TreeNode *root) { if(!root) return; preorder(root->left); preorder(root->right); cout << root->val << " "; } |
非递归方式:
void postorder(TreeNode *root) { stack<TreeNode*> stk; TreeNode *cur = root; TreeNode *prev = nullptr; while(cur || !stk.empty()) { while(cur) { stk.push(cur); cur = cur->left; } cur = stk.top(); if(cur->right && cur->right != prev) { cur = cur->right; } else { stk.pop(); cout << cur->val << " "; prev = cur; cur = nullptr; } } } |
void levelorder(TreeNode *root) { if(!root) return; queue<TreeNode*> q; q.push(root); while(!q.empty()) { int size = q.size(); for(int i = 0; i < size; i++) { TreeNode *node = q.front(); q.pop(); cout << node->val << " "; if(node->left) { q.push(node->left); } if(node->right) { q.push(node->right); } } } } |