1. 程式人生 > >笛卡爾樹簡介(分類到treap裡面)

笛卡爾樹簡介(分類到treap裡面)

構造笛卡爾樹的過程:

使用資料結構棧,棧中儲存的始終是右鏈,即根結點、根結點的右兒子、根結點的右兒子的右兒子……組成的鏈
並且棧中從棧頂到棧底key依次減小


如果按照從後到前的順序判斷一個元素是否大於A[i],則每次插入的時間複雜度為O(k+1)
k為本次插入中移除的右鏈元素個數。因為每個元素最多進出右鏈各一次,所以整個過程的時間複雜度為O(N)。

從前往後遍歷A[i],
1.對於每一個A[i],從棧中找出(從棧頂往棧底遍歷,或者從陣列後往前遍歷)第一個小於等於A[i]的元素
2.如果找到,i.parent為sta[k],同時sta[k].r=i,即i為sta[k]的右子樹,
3.如果棧中存在比A[i]大的元素 這些元素肯定是出棧了,這個問題最後的程式碼統一表示。
同時,sta[k+1].parent=i; i.l=sta[k+1] 即sta[K+1]為i的左子樹
4.最後i入棧,比i大的A[i]都自動出棧了。


例子如下。
0 1 2 3 4 5 6 7 8  9      .....key
3 2 4 5 6 8 1 9 10 7      .....A,value

stack
0 1 2 3 4 5 6 7 8  ...num
0
1 2 3 4 5
6 7 8
6 9
最後sta[0].parent=-1;  為根節點 即 6 為根節點。

這裡給出的是索引從0開始的[0,n-1]
如果題目給出的是[1,n],可以減一回到[0,n-1]上。

#include <iostream>
#include <queue>
using namespace std;
const int maxnum=10;

int a[maxnum];
struct node
{
    int key;
    int parent;
    int l;
    int r;
}tree[maxnum];


void Init()
{
    int i;
    for(i=0;i<maxnum;i++)
        tree[i].parent=tree[i].l=tree[i].r=-1;  //初始化
}

int Build_Tree()
{
    int i,top,k;
    int stack[maxnum];
    top=-1;
    for(i=0;i<maxnum;i++)
    {
        k=top;
        while(k>=0 && a[stack[k]]>a[i])  //棧中比當前元素大的都出棧
            k--;

        if(k!=-1)  //find it,棧中元素沒有完全出棧,當前元素為棧頂元素的右孩子
        {
            tree[i].parent=stack[k];
            tree[stack[k]].r=i;
        }
        if(k<top)    //出棧的元素為當前元素的左孩子
        {
            tree[stack[k+1]].parent=i;
            tree[i].l=stack[k+1];
        }

        stack[++k]=i;//當前元素入棧
        top=k;//top指向棧頂元素
    }
    tree[stack[0]].parent=-1;//遍歷完成後的棧頂元素就是根
    return stack[0];
}

void inorder(int node)
{
   if(node!=-1)
   {
       inorder(tree[node].l);
       cout<<tree[node].key<<endl;
       inorder(tree[node].r);
   }
}

void levelorder(int node)
{
    queue<int> q;
    q.push(node);
    while(!q.empty())
    {
        int k=q.front();
        q.pop();
        cout<<tree[k].key<<endl;
        if(tree[k].l!=-1)
            q.push(tree[k].l);
        if(tree[k].r!=-1)
            q.push(tree[k].r);
    }
}

int main()
{
    int i;
    Init();
    for(i=0;i<maxnum;i++)
    {
        cin>>a[i];
        tree[i].key=a[i];
    }

    int root=Build_Tree();

    //inorder(root);
    //levelorder(root);
    return 0;
}

/*
3 2 4 5 6 8 1 9 10 7
*/