笛卡尔树

笛卡尔树又称笛卡儿树,在数据结构中属于二叉树的一种。

笛卡尔树结构由Vuillmin在解决范围搜索的几何数据结构问题时提出的,从数列中构造一棵笛卡尔树可以线性时间完成,需要采用基于栈的算法来找到在该数列中的所有最近小数。由此可知,笛卡尔树是一种特定的二叉树数据结构,可由数列构造,在范围最值查询、范围top k查询(range top k queries)等问题上有广泛应用。它具有堆的有序性,中序遍历可以输出原数列。

笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为key,一个为value。光看key的话,笛卡尔树是一棵二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大;光看value的话,笛卡尔树有点类似堆,根节点的value是最小(或者最大)的,每个节点的value都比它的子树要大。

构造笛卡尔树的过程:

使用数据结构栈,栈中保存的始终是右链,即根结点、根结点的右儿子、根结点的右儿子的右儿子……组成的链
并且栈中从栈顶到栈底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]上

代码:

View Code
 1 #include <iostream>

 2 #include <queue>

 3 using namespace std;

 4 const int maxnum=10;

 5 

 6 int a[maxnum];

 7 struct node

 8 {

 9     int key;

10     int parent;

11     int l;

12     int r;

13 }tree[maxnum];

14 

15 

16 void Init()

17 {

18     int i;

19     for(i=0;i<maxnum;i++)

20         tree[i].parent=tree[i].l=tree[i].r=-1;  //初始化

21 }

22 

23 int Build_Tree()

24 {

25     int i,top,k;

26     int stack[maxnum];

27     top=-1;

28     for(i=0;i<maxnum;i++)

29     {

30         k=top;

31         while(k>=0 && a[stack[k]]>a[i])  //栈中比当前元素大的都出栈

32             k--;

33 

34         if(k!=-1)  //find it,栈中元素没有完全出栈,当前元素为栈顶元素的右孩子

35         {

36             tree[i].parent=stack[k];

37             tree[stack[k]].r=i;

38         }

39         if(k<top)    //出栈的元素为当前元素的左孩子

40         {

41             tree[stack[k+1]].parent=i;

42             tree[i].l=stack[k+1];

43         }

44 

45         stack[++k]=i;//当前元素入栈

46         top=k;//top指向栈顶元素

47     }

48     tree[stack[0]].parent=-1;//遍历完成后的栈顶元素就是根

49     return stack[0];

50 }

51 

52 void inorder(int node)

53 {

54    if(node!=-1)

55    {

56        inorder(tree[node].l);

57        cout<<tree[node].key<<endl;

58        inorder(tree[node].r);

59    }

60 }

61 

62 void levelorder(int node)

63 {

64     queue<int> q;

65     q.push(node);

66     while(!q.empty())

67     {

68         int k=q.front();

69         q.pop();

70         cout<<tree[k].key<<endl;

71         if(tree[k].l!=-1)

72             q.push(tree[k].l);

73         if(tree[k].r!=-1)

74             q.push(tree[k].r);

75     }

76 }

77 

78 int main()

79 {

80     int i;

81     Init();

82     for(i=0;i<maxnum;i++)

83     {

84         cin>>a[i];

85         tree[i].key=a[i];

86     }

87 

88     int root=Build_Tree();

89 

90     //inorder(root);

91     //levelorder(root);

92     return 0;

93 }

94 

95 /*

96 3 2 4 5 6 8 1 9 10 7

97 */

 

你可能感兴趣的:(树)