数据结构 - 树相关算法

二叉树前序遍历非递归算法:

void preOrder(TreeNode* root) {
    if(root == NULL) {
        return;
    }
    stack
     st;
    st.push(root);
    while(!st.empty()) {
        TreeNode* p = st.top();
        st.pop();
        cout<
    
     val<<" ";="" if(p-="">right != NULL) { st.push(p->right); } if(p->left != NULL) { st.push(p->left); } } } 
     
    

二叉树中序遍历非递归算法:

void inOrder(TreeNode* root) {
    if(root == NULL) {
        return;
    }
    stack
     st;
    TreeNode* p = root;
    do {
        
        while(p != NULL) {
            st.push(p);
            p = p->left;
        }
        
        if(!st.empty()) {
            p = st.top();
            st.pop();
            cout<
    
     val<<" ";="" p="p-">right; } } while(p != NULL || !st.empty()); } 
     
    

二叉树后序遍历非递归算法:

void postOrder(TreeNode* root) {
    if(root == NULL) {
        return;
    }
    stack
    
      st; TreeNode* p = NULL; TreeNode* pre = NULL; st.push(root); while(!st.empty()) { p = st.top(); if((p->left == NULL && p->right == NULL) || (pre != NULL && (pre == p->left || pre == p->right))) { st.pop(); cout<
     
      val<<" ";="" pre="p;" }="" else="" {="" if(p-="">right != NULL) { st.push(p->right); } if(p->left != NULL) { st.push(p->left); } } } } 
      
     
    

二叉搜索树删除节点算法:

void remove(TreeNode * & root, int x) {
    if(root == NULL) {
        return;
    }

    if(x < root->val) {
        remove(root->left, x);
    } else if(x > root->val) {
        remove(root->right, x);
    } else {
        if(root->left != NULL && root->right != NULL) {
            
            TreeNode* p = root->right;
            while(p->left != NULL) {
                p = p->left;
            }
            root->val = p->val;
            
            remove(p, x);
        } else {
            TreeNode* temp = root;
            if(root->left != NULL) {
                root = root->left;
            } else {
                root = root->right;
            }
            delete temp;
        }
    }
}

说明:二叉搜索树删除一个节点,如果该节点存在,删除该节点后需要进行相应的调整保证删除后该树还是二叉搜索树,分为四种情况:
1.被删除有左子树也有右子树 
2.被删除节点只有左子树
3.被删除节点只有右子树 
4.被删除节点既没有左子树也没有右子树。 
情况1的调整方法就是寻找右子树中序遍历序列的第一个节点A,用该节点代替被删除节点,然后现在问题就转化为删除这个节点A,递归
处理即可;情况2,3,4可以代码中统一处理,就是把左子树(或者右子树)代替被删除节点。

二叉树层次遍历算法:

void levelOrder(const TreeNode* root) {

    if(root == NULL) {
        return;
    }
    queue
     q;
    q.push(root);
    while(!q.empty()) {
        const TreeNode* p = q.front();
        q.pop();
        cout<
    
     val<<" ";="" if(p-="">left != NULL) { q.push(p->left); } if(p->right != NULL) { q.push(p->right); } } } 
     
    

求二叉树叶子节点数算法:

int getLeafNum(const TreeNode* root) {
    if(root == NULL) {
        return 0; 
    }
    if(root->left == NULL && root->right == NULL) {
        return 1;
    }
    return getLeafNum(root->left) + getLeafNum(root->right);
}

求二叉树深度算法:

int depth(const TreeNode* root) {
    if(root == NULL) {
        return 0;
    }
    if(root->left == NULL && root->right == NULL) {
        return 1;
    }
    int leftDepth = depth(root->left);
    int rightDepth = depth(root->right);
    return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

生成二叉树镜像算法:

void mirror(TreeNode* root) {
    if(root == NULL) {
        return;
    }
    TreeNode* p = root->right;
    root->right = root->left;
    root->left = p; 
    mirror(root->left);
    mirror(root->right);
}

打印二叉树中从根节点出发且和为某一定值的所有路径算法:


void printPaths(const TreeNode* root, int x, vector
     &v) {
    if(root == NULL) {
        return;
    }
    if(root->val == x) {
        int size = v.size();
        for(int i = 0; i < size; i++) {
            cout<
    
     val<
     
      val < x) { v.push_back(root->val); printPaths(root->left, x - root->val, v); printPaths(root->right, x - root->val, v); v.pop(); } } 
     
    

由前序遍历序列和中序遍历序列重建二叉树算法:

TreeNode* build(vector
     pre, int preStart, int preEnd, 
                vector
     in, int inStart, int inEnd) {

    if(preStart > preEnd || inStart > inEnd) {
        return NULL;
    }

    TreeNode* p = new TreeNode(pre[preStart]);
    int i = inStart;
    for(; i <= inend;="" i++)="" {="" if(in[i]="=" pre[prestart])="" break;="" }="" p-="">left = build(pre, preStart + 1, preStart + i - inStart, in, inStart, i - 1);
    p->right = build(pre, preStart + i - inStart + 1, preEnd, in, i + 1, inEnd);
    return p;
}

    

二叉搜索树转有序双向链表算法:

TreeNode* Convert(TreeNode* pRootOfTree){
    if(pRootOfTree == NULL) {
        return NULL;
    }

    TreeNode* p = Convert(pRootOfTree->left);
    TreeNode* q = Convert(pRootOfTree->right);
    TreeNode* temp = p;
    if(p != NULL) {
         while(p->right != NULL) {
            p = p->right;
        }   
        p->right = pRootOfTree;
    } else {
        temp = pRootOfTree;
    }
    if(q != NULL) {
        q->left = pRootOfTree;
    }
    pRootOfTree->left = p;
    pRootOfTree->right = q;

    return temp;
}

判断一颗树是否为平衡二叉树算法:

bool isAVL(TreeNode* pRoot, int &depth) {
    if(pRoot == NULL) {
        depth = 0;
        return true;
    }
    int leftDepth = 0;
    int rightDepth = 0;
    if(isAVL(pRoot->left, leftDepth) && isAVL(pRoot->right, rightDepth)) {
        int temp = leftDepth - rightDepth;
        if(temp >= -1 && temp <= 1)="" {="" depth="leftDepth"> rightDepth ? leftDepth + 1 : rightDepth + 1;
            return true;
        }
    }
    return false;
    }

说明:使用depth保存左右子树的深度,避免重复计算。

    

寻找二叉树中序遍历的下一个节点算法:


TreeLinkNode* GetNext(TreeLinkNode* pNode){
    if(pNode == NULL) {
        return NULL;
    }
    if(pNode->right != NULL) {
        pNode = pNode->right;
        while(pNode->left != NULL) {
            pNode = pNode->left;
        }
        return pNode;
    }
    if(pNode->next == NULL) {
        return NULL;
    }
    if(pNode == pNode->next->left) {
        return pNode->next;
    }
    while(pNode->next != NULL && pNode != pNode->next->left) {
        pNode = pNode->next;
    }
    return pNode->next;
    }

分步判断:
1.给定节点为NULL,直接返回NULL
2.给定节点有右子树,则返回右子树中序遍历的第一个节点,也就是左下角那个节点
3.给定节点没有右子树,如果是根节点则说明没有下一个节点了返回NULL
4.不是根节点,如果该节点是其父节点的左孩子,则下一个节点就是其父节点
5.不是根节点,如果该节点是其父节点的右孩子,则向上寻找直到找到一个节点是其父节点的左孩子,返回其父节点。

判断一棵二叉树是否是对称算法:

bool isSymmetrical(TreeNode* pRoot)
    {
        if(pRoot == NULL) {
            return true;
        }
        return isSymmetrical0(pRoot->left, pRoot->right);
    }

bool isSymmetrical0(TreeNode* left, TreeNode* right) {
    if(left == NULL && right == NULL) {
        return true;
    } else if(left != NULL && right != NULL) {
        return left->val == right->val 
            && isSymmetrical0(left->left, right->right) 
            && isSymmetrical0(left->right, right->left);
    } else {
        return false;   
    }
}

之字形层次打印二叉树算法:


vector
    
      >
     Print(TreeNode* pRoot) {
vector
    
      >
     v;
if(pRoot == NULL) {
    return v;
}
stack
     st1, st2;
st2.push(pRoot);
while(!st1.empty() || !st2.empty()) {
    vector
     vec1;
    while(!st2.empty()) {
        TreeNode* temp = st2.top();
        st2.pop();
        vec1.push_back(temp->val);
        if(temp->left != NULL) {
            st1.push(temp->left);
        }
        if(temp->right != NULL) {
            st1.push(temp->right);
        }
    }
    if(vec1.size() > 0) {
        v.push_back(vec1);   
    }

    vector
     vec2;
    while(!st1.empty()) {
        TreeNode* temp = st1.top();
        st1.pop();
        vec2.push_back(temp->val);
        if(temp->right != NULL) {
            st2.push(temp->right);
        }
        if(temp->left != NULL) {
            st2.push(temp->left);
        }
    }
    if(vec2.size() > 0) {
        v.push_back(vec2);   
    }
}
return v;
}

寻找二叉搜索树第k个节点算法:


TreeNode* KthNode(TreeNode* pRoot, unsigned int k){
    if(pRoot == NULL || k <= 0)="" {="" return="" null;="" }="" unsigned="" int="" count="0;" stack
    
      st; TreeNode* p = pRoot; while(p != NULL || !st.empty()) { while(p != NULL) { st.push(p); p = p->left; } if(!st.empty()) { p = st.top(); count++; if(count == k) { return p; } st.pop(); p = p->right; } } return NULL; } 
     
    
    原文作者:二叉树遍历
    原文地址: https://juejin.im/entry/57dfa545128fe10064d60a94
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞