数据结构-树相关算法

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

void preOrder(TreeNode* root) {
    if(root == NULL) {
        return;
    }
    stack<TreeNode*> st;
    st.push(root);
    while(!st.empty()) {
        TreeNode* p = st.top();
        st.pop();
        cout<<p->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<TreeNode*> st;
    TreeNode* p = root;
    do {
        //左节点一直进栈
        while(p != NULL) {
            st.push(p);
            p = p->left;
        }
        //栈顶元素如果存在就是下一个访问节点
        if(!st.empty()) {
            p = st.top();
            st.pop();
            cout<<p->val<<" ";
            p = p->right;
        }
    } while(p != NULL || !st.empty());
}

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

void postOrder(TreeNode* root) {
    if(root == NULL) {
        return;
    }
    stack<TreeNode*> st;
    TreeNode* p = NULL;
    TreeNode* pre = NULL;//保存上一次访问的节点
    st.push(root);

    while(!st.empty()) {
        p = st.top();
        //访问某一节点有两种情况:1.该节点是叶子节点  2.该节点的左右子树都已经访问过了
        if((p->left == NULL && p->right == NULL)
            || (pre != NULL && (pre == p->left || pre == p->right))) {
            st.pop();
            cout<<p->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;
            //转化为删除p节点
            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,递归
处理即可;情况234可以代码中统一处理,就是把左子树(或者右子树)代替被删除节点。

二叉树层次遍历算法:

void levelOrder(const TreeNode* root) {

    if(root == NULL) {
        return;
    }
    queue<const TreeNode*> q;
    q.push(root);
    while(!q.empty()) {
        const TreeNode* p = q.front();
        q.pop();
        cout<<p->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<int> &v) {
    if(root == NULL) {
        return;
    }
    if(root->val == x) {
        int size = v.size();
        for(int i = 0; i < size; i++) {
            cout<<v[i]<<" ";
        }
        cout<<root->val<<endl;
    } else if(root->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<int> pre, int preStart, int preEnd, 
                vector<int> 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<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > v;
if(pRoot == NULL) {
    return v;
}
stack<TreeNode*> st1, st2;
st2.push(pRoot);
while(!st1.empty() || !st2.empty()) {
    vector<int> 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<int> 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<TreeNode*> 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;
}

本博客已停止更新,转移到微信公众号上写文章,欢迎关注:Android进阶驿站
Android进阶驿站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值