树
树形结构一对多
基础知识
- 节点的度:一个节点含有的子树的个数
- 树的度:最大节点的度
- 叶节点或终端节点:度为0
- 非终端节点或分支节点:度不为0
- 兄弟节点:相同父节点
- 深度:对于任意节点n,n的深度为跟到n的唯一路径长,根的深度为0
- 祖先:从根节点到该节点所经分支上的都是该节点的祖先
- 森林:由m(m>=0)颗互相不相交的属的集合称为森林
- 树中任意节点的子节点之间没有顺序关系,称为无序树,也称自由树,反之时有序树
二叉树
定义
一棵二叉树是节点的一个有限集合该集合或者为空,或者由一个根节点加上两颗分别为左子树和右子树,互不相交的二叉树组成。
性质
- 层次从0 ,开始第i层最多有2^i.
- 高度为k
- 度为0的个数n0,度为2的个数n2, n0= n2 +1
- 满二叉树:每一层的节点个数均达到最大值
- 完全二叉树:高度h,0-h-1层均达到最大值,h层从右向左一次缺省
二叉树的存储
顺序存储-满二叉树、链式存储(二叉链表,三叉链表(指向子节点,指向父节点))、二叉链表的静态结构
二叉链表静态存储
二叉树遍历
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
中序遍历:
若二叉树为空,退出
否则:
中序遍历左子树
访问根节点
中序遍历右子树
递归程序
typedef char ElemType;
typedef struct BTNode{
struct BTNode *leftchild;
struct BTNode *rightchild;
ElemType data;
}BTNode, *BinarryTree;
void InOrder(BTNode *ptr){
if(ptr != nullptr){
InOrder(ptr->leftchild);
cout << ptr->data << " ";
InOrder(ptr->rightchild);
}
}
void PreOrder(BTNode *ptr){
if(ptr != nullptr){
cout << ptr->data << " ";
PreOrder(ptr->leftchild);
PreOrder(ptr->rightchild);
}
}
void PastOrder(BTNode *ptr){
if(ptr != nullptr){
PastOrder(ptr->leftchild);
PastOrder(ptr->rightchild);
cout << ptr->data << " ";
}
}
BTNode* BuyNode(){
BTNode* s = ((BTNode*)malloc(sizeof(BTNode)));
if(nullptr == s) exit(1);
memset(s, 0, sizeof(BTNode));
return s;
}
//字符序列创建二叉树
BTNode* CreateBt(const char * &str){
BTNode* s = nullptr;
if(*str != '#'){
s = BuyNode();
s->data = *str;
s->leftchild = CreateBt(++str);
s->rightchild = CreateBt(++str);
}
return s;
}
BTNode * CreateTree(const char *str)
{
if(nullptr == str || strlen(str) <= 0) return nullptr;
else return CreateBt(str);
}
int main(){
//ABCDEFAGH
//CBEDFAGH
//CEFDBHGA
const char* str = "ABC##DE##F##G#H##";
BinarryTree root = CreateTree(str);
PreOrder(root);
return 0;
}
//非递归中序遍历
void NiceInOrder(BTNode * root){
if(nullptr == root) return;
stack<BTNode*> st;
while(root || !st.empty()){
while(root){
st.push(root);
root = root->leftchild;
}
root =st.top();
st.pop();
cout << root->data << " ";
root = root->rightchild;
}
cout << endl;
}
//非递归后序遍历
void NicePastOrder(BTNode * root){
if(root == nullptr) return;
BTNode *pre = nullptr, *p = root;
stack<BTNode*> st;
while(p || !st.empty()){
while(p){
st.push(p);
p = p ->leftchild;
}
p = st.top();
st.pop();
if(p->rightchild == nullptr || p->rightchild == pre){
cout << p ->data <<" ";
pre = p;
p = nullptr;
}
else{
st.push(p);
p = p->rightchild;
}
}
cout << endl;
}
//非递归先序遍历
void NicePreOrder(BTNode* root){
if(nullptr == root){
return;
}
stack<BTNode*> st;
st.push(root);
while(!st.empty()){
root = st.top();
st.pop();
cout << root->data << " ";
if(root ->rightchild ) st.push(root->rightchild);
if(root ->leftchild) st.push(root->leftchild);
}
cout << endl;
}
int main(){
const char* str = "ABC##DE##F##G#H##";
BinarryTree root = CreateTree(str);
NicePreOrder(root);
return
使用先序和中序遍历构建二叉树
思想:中序是左根右,根节点左右是子节点。先序是根左右,序列中第一个是根。所以可以根据先序确定根节点,在中序中找到根节点,其左右两边就是他的左右子树。
使用后序和中序构建二叉树
思想:后序是左右根,所以最后一个节点是根节点。
int FindPos(const char *pstr, int n, char ch){
int pos= -1;
for(int i = 0; i < n; ++i){
if( pstr[i] == ch){
pos = i;
break;
}
}
return pos;
}
BTNode * CreatePITree (const char* p_str, const char *in_str, int n){
BTNode * s = nullptr;
if(n > 0) {
s= BuyNode();
s->data = p_str[0];
int pos = FindPos(in_str, n, p_str[0]);
s ->leftchild = CreatePITree(p_str + 1, in_str , pos);
s ->rightchild = CreatePITree(p_str + pos + 1, in_str + pos + 1, n - pos - 1);
}
return s;
}
//使用先序和中序遍历构建二叉树
BTNode* Pre_In_Order(const char *pre_str, const char *in_str){
int n = strlen(pre_str), m = strlen(in_str);
if(nullptr == pre_str || nullptr == in_str || n < 1 || m < 1) return nullptr;
return CreatePITree(pre_str, in_str,n);
}
BTNode* CreateIPO_Tree(const char * in_str, const char * po_str, int n){
BTNode* s = nullptr;
if(n > 0){
s = BuyNode();
s->data = po_str[n - 1];
int pos = FindPos(in_str, n, po_str[n - 1]);
s->leftchild = CreateIPO_Tree(in_str, po_str, pos);
s->rightchild = CreateIPO_Tree(in_str + pos + 1, po_str + pos, n - pos - 1);
}
return s;
}
//使用hou序和中序遍历构建二叉树
BTNode* IN_Post_Order(const char* in_str, const char * po_str){
int n = strlen(in_str), m = strlen(po_str);
if( nullptr == in_str || nullptr == po_str || n < 1 || m < 1){
return nullptr;
}
return CreateIPO_Tree(in_str, po_str, n);
}
int main(){
const char * pstr = "ABCDEFGH";
const char *istr = "CBEDFAGH";
const char *poststr = "CEFDBHGA";
//BTNode * s = IN_Post_Order(istr, poststr);
BTNode * s = Pre_In_Order(pstr, poststr);
PreOrder(s);
cout << endl;
return 0;
}
用顺序存储表示二叉树,给一个顺序表,写一个中序遍历
void InOrder_arr(vector<int> ar, int i, int n){
if(i < n && ar[i] != -1){
InOrder_arr(ar, i * 2 + 1, n);
cout << ar[i] << " ";
InOrder_arr(ar, i * 2 + 2, n);
}
}
int main(){
vector<int> ar = {31,23,12,66,-1,5,17,70, 62, -1, -1, 88, -1, 55};
InOrder_arr(ar, 0, ar.size());
cout <<endl;
return 0;
}
非递归后序方法二:
使用静态存储结构,每个数据是0-3,0是第一次入栈,1是左孩子入栈,2是有孩子入栈,3是该数据出栈。
struct StNode{
BTNode* node;
int num;
};
void NicePastOrder2(BTNode* root){
if(nullptr == root) return;
stack<StNode> st;
st.push({root, 0});
while(!st.empty()){
StNode node = st.top();
st.pop();
++node.num;
if(node.num == 3){
cout << node.node->data << " ";
}
else{
st.push(node);
if(node.num == 2 && node.node->rightchild ){
st.push({node.node->rightchild, 0});
}
else if (node.num == 1 && node.node->leftchild){
st.push({node.node->leftchild, 0});
}
}
}
cout << endl;
}
int main(){
const char* str = "ABC##DE##F##G#H##";
BinarryTree root = CreateTree(str);
NicePastOrder2(root);
LevelOrder(root);
return 0;
}