• POJ 1785 Binary Search Heap Construction(裸笛卡尔树的构造)


    笛卡尔树:

      每个节点有2个关键字key、value。从key的角度看,这是一颗二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大;从value的角度看,这是一个堆。

    题意:以字符串为关键字key,数字为关键字value,构造一个二叉搜索大堆,最后按要求中序遍历 笛卡尔树的构造。

    建立笛卡尔树的O(n)的算法:

      从别人博客里拷贝过来的,这里给出链接:http://hi.baidu.com/yy17yy/item/cd4edcf963944f6a3d148553

      首先按key关键字进行排序,这样建树的时候从左下角往右下角建。根据定义可知,每个数组的末尾节点必是位于树的最右路上且不可能有右孩子。 在建立树的过程中每次加入一个元素A[X],则该节点一定位于此时的树的最右路上且无右孩子。所以只要沿着A[X-1]节点向上走, 找到比A[X]大的第一个节点A[K],则A[X]是A[K]的右孩子,且A[K]原来的右孩子此时将成为A[X]的左孩子。 若找不到A[K]则此时的树的根将作为A[X]的左孩子,A[X]将成为树的新的根节点。

      可以模拟一个虚根,其priority设为无穷,这样最后构造出来的树即为虚根的右子树,方便编写程序。

    我原来排序时,是自己写了比较器,传给sort方法,969MS。后来在Node结构体中重载运算符<,625MS。

    代码中scanf的用法,详见:http://blog.csdn.net/wesweeky/article/details/6439777

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <queue>
    #include <algorithm>
    #include <string>
    
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=1<<16;
    int fa[maxn];  //存储父节点的编号
    int son[maxn][2]; //son[i][0]存储i的左儿子编号,son[i][1]存储i的右儿子编号
    int n;
    
    struct Node{
        char s[110];  //字符串
        int p;  //优先级
        bool operator<(const Node tmp)const{
            return strcmp(s,tmp.s)<0;
        }
    }node[maxn];
    /*
    bool cmp(const Node tmp1,const Node tmp2){
        if(strcmp(tmp1.s,tmp2.s)<0)
            return 1;
        else
            return 0;
    }
    */
    void treap(int i){
        int tmp=i-1;
        //直到找到一个tmp,使得tmp的优先级大于i
        while(node[tmp].p<node[i].p){
            tmp=fa[tmp];
        }
        //tmp的原先的右儿子即为i的左儿子,i成为tmp的右儿子
        son[i][0]=son[tmp][1];
        son[tmp][1]=i;
        fa[i]=tmp;
    }
    //中序遍历
    void dfs(int i){
        if(i==0)
            return;
        printf("(");
        //递归左儿子
        dfs(son[i][0]);
        printf("%s/%d",node[i].s,node[i].p);
        //递归右儿子
        dfs(son[i][1]);
        printf(")");
    }
    int main()
    {
        //这里为方便起见,设立了一个优先级很大的虚根,之后建的树为虚根的右子树
        node[0].p=INF;
        while(scanf("%d",&n),n){
            memset(son,0,sizeof(son));
            memset(fa,-1,sizeof(fa));
            for(int i=1;i<=n;i++){
                //[a-z]表示读取的字符串由a-z中的字符组成,其余的字符为定界符
                scanf(" %[a-z]/%d",node[i].s,&node[i].p);
            }
            //sort(node+1,node+n+1,cmp);
            sort(node+1,node+n+1);
            for(int i=1;i<=n;i++){
                treap(i);
            }
            //从虚根的右儿子开始dfs
            dfs(son[0][1]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    regsvr32.exe使用详解
    Windows默认文件操作(SHFileOperation)
    远程唤醒
    delphi事务
    rar行命令
    命令前加./ ,在后台运行程序 linux批处理 linux自动运行程序
    javascript基础知识(1)
    (三) MySQL事务与锁机制
    代码风格 java
    一切之始 java
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3354647.html
Copyright © 2020-2023  润新知