数据结构-树相关算法

来源:互联网 发布:淘宝卖家能给差评吗 编辑:程序博客网 时间:2024/05/01 01:10

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

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,直接返回NULL2.给定节点有右子树,则返回右子树中序遍历的第一个节点,也就是左下角那个节点3.给定节点没有右子树,如果是根节点则说明没有下一个节点了返回NULL4.不是根节点,如果该节点是其父节点的左孩子,则下一个节点就是其父节点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;}
0 0