zoukankan      html  css  js  c++  java
  • 算法笔记(树专题)

    树专题

    1.DFS模板

    //伪代码
    void DFS(一个结点){
        访问该结点;
        for(遍历该结点的相邻未访问过的结点){
            选此结点;
            DFS(这个邻接结点);
            去掉刚刚选的结点;   //****(勿忘)
        }
    }

    2.BFS模板

    //BFS使用队列
    void BFS(int s){
        queue<int> q;
        q.push(s);  //起始点入队
        while(!q.empty()){
            取出队首元素top;
            访问队首元素top;
            将队首元素出队;
            将top的下一层结点中未曾入队的结点全部入队,并设置为已入队;
        }
    }
    for(结点未被访问){
        BSF(该结点);
    }

    3.二叉树的动态实现(指针)

    struct node{
        int data;
        int layer;//层次遍历需要
        node* lchild;
        node* rchild;
    };
    //由于在二叉树建树前根节点不存在,因此其地址一般设为NULL ********
    node* root = NULL;
    //生成一个新结点
    node* newNode(int v){
        node* Node = new node;
        Node->data = v;
        Node->lchild = Node->rchild = NULL;
        return Node;
    }
    //insert函数将在二叉树中插入一个数据域为x的新结点
    void insert(node* &root, int x){ //(注意root要使用引用)****
        if(root == NULL){
            //root = newNode(x);
            root = new node;
            root->data = x;
            root->lchild = root->rchild = NULL;
            return;
        }
        if(由二叉树性质,x应该插在左子树){
            insert(root->lchild, x);
        } else{
            insert(root->rchild, x);
        }
    }
    //层序遍历
    void LayerOrder(node* root){
        queue<node*> q;  //******(注意)
        q.push(root);
        while(!q.empty()){
            node* now = q.front();
            q.pop();
            printf("%d ", now->data);
            if(now->lchild != NULL) {
                now->lchild->layer = now->layer + 1;
                q.push(now->lchild);
            }
            if(now->rchild != NULL) {
                now->rchild->layer = now->layer + 1;
                q.push(now->rchild);
            }
        }
    }

    4.二叉树的静态实现

    struct Node{
        int data;
        int lchild;
        int rchild;
    } node[maxn];
    //先序遍历
    void preorder(int root){
        if(root == -1) return;  //到达空树,递归边界,一般空树设为-1
        printf("%d
    ", node[root].data);
        preorder(node[root].lchild);
        preorder(node[root].rchild);
    }
    //中序遍历
    void inorder(int root){
        if(root == -1) return;
        inorder(node[root].lchild);
        printf("%d
    ", node[root].data);
        inorder(node[root].rchild);
    }
    //后序遍历
    void postorder(int root){
        if(root == -1) return;
        postorder(node[root].lchild);
        postorder(node[root].rchild);
        printf("%d
    ", node[root].data);
    }
    struct Node{
        int data;
        int lchild;
        int rchild;
    } node[maxn];
    //先序遍历
    void preorder(int root){
        if(root == -1) return;  //到达空树,递归边界,一般空树设为-1
        printf("%d
    ", node[root].data);
        preorder(node[root].lchild);
        preorder(node[root].rchild);
    }
    //中序遍历
    void inorder(int root){
        if(root == -1) return;
        inorder(node[root].lchild);
        printf("%d
    ", node[root].data);
        inorder(node[root].rchild);
    }
    //后序遍历
    void postorder(int root){
        if(root == -1) return;
        postorder(node[root].lchild);
        postorder(node[root].rchild);
        printf("%d
    ", node[root].data);
    }

    5.树的遍历、树的静态写法

    ​ 树:即子结点个数不确定且子结点没有先后次序的树。推荐使用静态写法

    struct Node{
        int data;  //数据域
        int layer; //用于树的层次遍历
        vector<int> child;   //*****指针域,存放所有子结点的下标
    } node[maxn];  //结点数组,maxn为结点上限个数
    //树的先根遍历 或 DFS
    void PreOrder(int root){
        printf("%d ", node[root].data);   //访问当前结点
        for(int i=0; i<node[root].child.size(); i++){
            PreOrder(node[root].child[i]);   //递归访问结点root的所有子结点
        }
    }
    //树的层次遍历 或 BFS
    void BFS(int root){
        queue<int> Q;
        Q.push(root); //将根结点入队
        node[root].layer = 0; //记根结点的层号为0
        while(!Q.empty()){
            int front = Q.front();
            Q.pop();  //取出队首元素
            printf("%d ", node[front].data); //操作,如打印当前结点的数据域
            for(int i=0; i<node[front].child.size(); i++){
                int child = node[front].child[i];  //当前结点的第i个子结点的编号
                node[child].layer = node[front].layer + 1; //子结点层号为当前结点层号+1
                Q.push(child);   //将当前结点的所有子结点入队
            }
        }
    }

    6.知道二叉树的先序和中序遍历,建立该二叉树

    struct Node{
        int data;
        Node *lchild, rchild;
    };
    int pre[MAXN], in[MAXN], post[MAXN];  //先序、中序及后序
    //当前二叉树的先序序列区间为[preL, preR],中序序列区间为[inL, inR]
    //create函数返回构建出的二叉树的根节点地址
    Node* create(int preL, int preR, int inL, int inR){
        if(preL > preR)  return NULL;
        Node* root = new Node;
        root->data = pre[preL];
        int k;
        for(k = inL; k<=inR; k++){
            if(in[k] == pre[preL]){  //在中序序列中找到in[k] == pre[L]的结点
                break;
            }
        }
        int numLeft = k - inL;  //左子树的结点个数
        //返回左子树的根结点地址,赋值给root的左指针
        root->lchild = create(preL+1, preL+numLeft, inL, k-1);   //****注意参数怎么表示
        //返回右子树的根结点地址,赋值给root的右指针
        root->rchild = create(preL+numLeft+1, preR, k+1, inR);
        return root;
    }

    7.二叉树查找(BST)

    //****search函数查找二叉查找树中数据域为x的结点
    void search(node* root, int x){
        if(root == NULL){ //空树,查找失败
            printf("search failed
    ");
            return;
        }
        if(x == root->data){
            printf("%d
    ", root->data);
        }else if(x < root->data){//如果x比根节点的数据域小,说明x在左子树
            search(root->lchild, x);  //往左子树搜索
        }else{
            search(root->rchild, x);
        }
    }
    //****insert函数将在二叉树中插入一个数据域为x的新结点(注意参数root要加引用 &)
    void insert(node* &root, int x){
        if(root == NULL){ //空树,查找失败,也即插入位置
            root = newNode(x);   //新建结点,权值为x
            return;
        }
        if(x == root->data){  //查找成功,说明结点已存在,直接返回
            printf("%d
    ", root->data);
        }else if(x < root->data){//如果x比根节点的数据域小,说明x需要插在左子树
            insert(root->lchild, x);  //往左子树搜索
        }else{
            insert(root->rchild, x);
        }
    }
    //****二叉查找树的建立
    node* create(int data[], int n){
        node* root = NULL;  //新建根节点root
        for(int i=0; i<n; i++){
            insert(root, data[i]);  //将data[0]~data[n-1]插入二叉查找树
        }
        return root;  //返回根节点
    }
    //寻找以root为根结点的树中最大权值结点
    node* findMax(node* root){
        while(root->rchild != NULL){
            root = root->rchild;   //不断往右,直到没有右孩子
        }
        return root;
    }
    node* findMin(node* root){
        while(root->data !=NULL){
            root = root->lchild;
        }
        return root;
    }
    //删除以root为根结点的树中权值为x的结点(****)
    void deletNode(node* &root, int x){
        if(root == NULL) return;  //不存在权值为x的结点
        if(root->data == x){//找到欲删除的结点
            if(root->lchild == NULL && root->rchild == NULL){ //叶子结点直接删除
                root = NUUL; //把root地址设为NULL,父结点就引用不到它了
            }else if(root->lchild != NULL){ //左子树不空时
                node* pre = findMax(root->lchild);  //找root前驱
                root->data = pre->data;  //用前驱覆盖root
                deleteNode(root->lchild, pre->data);  //在左子树中删除结点pre
            }else{//右子树不为空时
                node* next = findMin(root->rchild);  //找root后继
                root->data = next->data;  //用后继覆盖root
                deleteNode(root->rchild, next->data);  //在右子树中删除结点next
            }else if(root->data > x){
                deleteNode(root->lchild, x); //在左子树中删除x
            }else{
                deleteNode(root->rchild, x);  //在右子树中删除x
            }
        }
    }

    8.平衡二叉树 AVL

    struct node{
        int v, height; //v为结点权值,height为当前子树高度
        node *lchild;
        node *rchild;
    } *root;
    //生成一个新结点
    node* newNode(int v){
        node* Node = new node;
        Node->v = v;
        Node->height = 1;  //AVL需要
        Node->lchild = Node->rchild = NULL;
        return Node;
    }
    //获取以root为根结点的子树的当前height
    int getHeight(node* root){
        if(root == NULL) return 0;
        return root->height;
    }
    /更新结点root的height
    void updateHeight(node* root){
        //max(左孩子结点的height, 右孩子结点的height)+1
        root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
    }
    //计算结点的平衡因子
    int getBalanceFactor(node* root){
        //左子树高度减右子树高度
        return getHeight(root->lchild) - getHeight(root->rchild);
    }
    //左旋
    void L(node* &root){
        node* temp = root->rchild;
        root->rchild= temp->lchild;
        temp->lchild= root;
        updateHeight(root);
        updateHeight(temp);
        root = temp;
    }
    //右旋
    void R(node* &root){
        node* temp = root->lchild;
        root->lchild = temp->rchild;
        temp->rchild = root;
        updateHeight(root);
        updateHeight(temp);
        root = temp;
    }
    void insert(node* &root, int v){
        if(root == NULL){  //到达空结点
            root = newNode(v);
            return;
        }
        if(v < root->v){  //v比根结点权值小
            insert(root->lchild, v);  //往左子树插入
            updateHeight(root);  //更新树高
            if(getBalanceFactor(root) == 2){
                if(getBalanceFactor(root->lchild) == 1){  //LL型
                    R(root);
                } else if(getBalanceFactor(root->lchild) == -1){  //LR型
                    L(root->lchild);
                    R(root);
                }
            }
        } else{  //v比根结点权值大
            insert(root->rchild, v);  //往右子树插入
            updateHeight(root);  //更新树高
            if(getBalanceFactor(root) == -2){
                if(getBalanceFactor(root->rchild) == -1){  //LL型
                    L(root);
                } else if(getBalanceFactor(root->rchild) == 1){  //RL型
                    R(root->rchild);
                    L(root);
                }
            }
        }
    }
    //AVL树的建立
    node* Create(int data[], int n){
        node* root = NULL;
        for(int i=0; i<n; i++){
            insert(root, data[i]);
        }
        return root;
    }
  • 相关阅读:
    Excel 向程序发送命令时出现问题
    JavaScript中undefined,null,NaN的区别
    MYSQL查询优化(一)
    win7 去除任务栏上出现的过期图标
    InnoDB与MyISAM区别
    form表单 按回车自动提交 实现方式
    多线程下载图片
    MySQL启动不了,InnoDB: autoextending data file .\ibdata1 is of a different size 78592 pages (rounded down to MB) than specified in the .cnf file: initial 131072 pages, max 0 (relevant if nonzero) pages!
    Net EF to MySQL生成edmx文件时报错:StrongTypingException:表“TableDetails"中列“IsPrimaryKey"的值为DBNull
    DataTable转置
  • 原文地址:https://www.cnblogs.com/dear_diary/p/8616204.html
Copyright © 2011-2022 走看看