• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            ACM___________________________

            ______________白白の屋
            posts - 182, comments - 102, trackbacks - 0, articles - 0
            <2010年10月>
            262728293012
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(24)

            隨筆分類(lèi)(332)

            隨筆檔案(182)

            FRIENDS

            搜索

            積分與排名

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            MiYu原創(chuàng), 轉(zhuǎn)帖請(qǐng)注明 : 轉(zhuǎn)載自 ______________白白の屋    

             

            伸展樹(shù)(Splay Tree)是AVL樹(shù)不錯(cuò)的替代,它有以下幾個(gè)特點(diǎn):
            (1)它是二叉查找樹(shù)的改進(jìn),所以具有二叉查找樹(shù)的有序性。
            (2)對(duì)伸展樹(shù)的操作的平攤復(fù)雜度是O(log2n)。
            (3)伸展樹(shù)的空間要求、編程難度非常低。

            提到伸展樹(shù),就不得不提到AVL樹(shù)和Read-Black樹(shù),雖然這兩種樹(shù)能夠保證各種操作在最壞情況下都為logN,但是兩都實(shí)現(xiàn)都比較復(fù)雜。而在實(shí)際情況中,90%的訪問(wèn)發(fā)生在10%的數(shù)據(jù)上。因此,我們可以重構(gòu)樹(shù)的結(jié)構(gòu),使得被經(jīng)常訪問(wèn)的節(jié)點(diǎn)朝樹(shù)根的方向移動(dòng)。盡管這會(huì)引入額外的操作,但是經(jīng)常被訪問(wèn)的節(jié)點(diǎn)被移動(dòng)到了靠近根的位置,因此,對(duì)于這部分節(jié)點(diǎn),我們可以很快的訪問(wèn)。這樣,就能使得平攤復(fù)雜度為logN。

            1、自底向上的伸展樹(shù)
            伸展操作Splay(x,S)是在保持伸展樹(shù)有序性的前提下,通過(guò)一系列旋轉(zhuǎn)操作將伸展樹(shù)S中的元素x調(diào)整至樹(shù)的根部的操作。
            在旋轉(zhuǎn)的過(guò)程中,要分三種情況分別處理:
            (1)Zig 或 Zag
            (2)Zig-Zig 或 Zag-Zag
            (3)Zig-Zag 或 Zag-Zig
            1.1、Zig或Zag操作
            節(jié)點(diǎn)x的父節(jié)點(diǎn)y是根節(jié)點(diǎn)。

            1.2、Zig-Zig或Zag-Zag操作
            節(jié)點(diǎn)x的父節(jié)點(diǎn)y不是根節(jié)點(diǎn),且x與y同時(shí)是各自父節(jié)點(diǎn)的左孩子或者同時(shí)是各自父節(jié)點(diǎn)的右孩子。

            1.3、Zig-Zag或Zag-Zig操作
            節(jié)點(diǎn)x的父節(jié)點(diǎn)y不是根節(jié)點(diǎn),x與y中一個(gè)是其父節(jié)點(diǎn)的左孩子而另一個(gè)是其父節(jié)點(diǎn)的右孩子。

            2、自頂向下的伸展樹(shù)
                在自底向上的伸展樹(shù)中,我們需要求一個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)和祖父節(jié)點(diǎn),因此這種伸展樹(shù)難以實(shí)現(xiàn)。因此,我們可以構(gòu)建自頂向下的伸展樹(shù)。
                當(dāng)我們沿著樹(shù)向下搜索某個(gè)節(jié)點(diǎn)X的時(shí)候,我們將搜索路徑上的節(jié)點(diǎn)及其子樹(shù)移走。我們構(gòu)建兩棵臨時(shí)的樹(shù)──左樹(shù)和右樹(shù)。沒(méi)有被移走的節(jié)點(diǎn)構(gòu)成的樹(shù)稱(chēng)作中樹(shù)。在伸展操作的過(guò)程中:
            (1)當(dāng)前節(jié)點(diǎn)X是中樹(shù)的根。
            (2)左樹(shù)L保存小于X的節(jié)點(diǎn)。
            (3)右樹(shù)R保存大于X的節(jié)點(diǎn)。
            開(kāi)始時(shí)候,X是樹(shù)T的根,左右樹(shù)L和R都是空的。和前面的自下而上相同,自上而下也分三種情況:
            2.1、Zig操作

            如上圖,在搜索到X的時(shí)候,所查找的節(jié)點(diǎn)比X小,將Y旋轉(zhuǎn)到中樹(shù)的樹(shù)根。旋轉(zhuǎn)之后,X及其右子樹(shù)被移動(dòng)到右樹(shù)上。很顯然,右樹(shù)上的節(jié)點(diǎn)都大于所要查找的節(jié)點(diǎn)。注意X被放置在右樹(shù)的最小的位置,也就是X及其子樹(shù)比原先的右樹(shù)中所有的節(jié)點(diǎn)都要小。這是由于越是在路徑前面被移動(dòng)到右樹(shù)的節(jié)點(diǎn),其值越大。

            2.2、Zig-Zig操作

            這種情況下,所查找的節(jié)點(diǎn)在Z的子樹(shù)中,也就是,所查找的節(jié)點(diǎn)比X和Y都小。所以要將X,Y及其右子樹(shù)都移動(dòng)到右樹(shù)中。首先是Y繞X右旋,然后Z繞Y右旋,最后將Z的右子樹(shù)(此時(shí)Z的右子節(jié)點(diǎn)為Y)移動(dòng)到右樹(shù)中。

            2.3、Zig-Zag操作

            這種情況中,首先將Y右旋到根。這和Zig的情況是一樣的,然后變成上圖右邊所示的形狀。此時(shí),就與Zag(與Zig相反)的情況一樣了。

            最后,在查找到節(jié)點(diǎn)后,將三棵樹(shù)合并。如圖:


            2.4、示例:
            下面是一個(gè)查找節(jié)點(diǎn)19的例子。在例子中,樹(shù)中并沒(méi)有節(jié)點(diǎn)19,最后,距離節(jié)點(diǎn)最近的節(jié)點(diǎn)18被旋轉(zhuǎn)到了根作為新的根。節(jié)點(diǎn)20也是距離節(jié)點(diǎn)19最近的節(jié)點(diǎn),但是節(jié)點(diǎn)20沒(méi)有成為新根,這和節(jié)點(diǎn)20在原來(lái)樹(shù)中的位置有關(guān)系。

            3、實(shí)現(xiàn)
            3.1、splay操作

            代碼
            tree_node * splay (int i, tree_node * t) {
                tree_node N, 
            *l, *r, *y;
                
            if (t == NULL) 
                    
            return t;
                N.left 
            = N.right = NULL;
                l 
            = r = &N;

                
            for (;;)
                {
                    
            if (i < t->item) 
                    {
                        
            if (t->left == NULL) 
                            
            break;
                        
            if (i < t->left->item) 
                        {
                            y 
            = t->left;                           /* rotate right */
                            t
            ->left = y->right;
                            y
            ->right = t;
                            t 
            = y;
                            
            if (t->left == NULL) 
                                
            break;
                        }
                        r
            ->left = t;                               /* link right */
                        r 
            = t;
                        t 
            = t->left;
                    } 
            else if (i > t->item)
                    {
                        
            if (t->right == NULL) 
                            
            break;
                        
            if (i > t->right->item) 
                        {
                            y 
            = t->right;                          /* rotate left */
                            t
            ->right = y->left;
                            y
            ->left = t;
                            t 
            = y;
                            
            if (t->right == NULL) 
                                
            break;
                        }
                        l
            ->right = t;                              /* link left */
                        l 
            = t;
                        t 
            = t->right;
                    } 
            else {
                        
            break;
                    }
                }
                l
            ->right = t->left;                                /* assemble */
                r
            ->left = t->right;
                t
            ->left = N.right;
                t
            ->right = N.left;
                
            return t;
            }

            Rotate right(查找10):

            Link right:

            Assemble:

            Rotate left(查找20):

            Link left:

            3.2、插入操作

            代碼
              /*
              **將i插入樹(shù)t中,返回樹(shù)的根結(jié)點(diǎn)(item值==i)
              */
              tree_node* ST_insert(int i, tree_node *t) {
                  /* Insert i into the tree t, unless it's already there.    */
                  /* Return a pointer to the resulting tree.                 */
                  tree_node* node;
                  
                  node = (tree_node *) malloc (sizeof (tree_node));
                 if (node == NULL){
                     printf("Ran out of space\n");
                     exit(1);
                 }
                 node->item = i;
                 if (t == NULL) {
                     node->left = node->right = NULL;
                     size = 1;
                     return node;
                 }
                 t = splay(i,t);
                 if (i < t->item) {  //令t為i的右子樹(shù)
                     node->left = t->left;
                     node->right = t;
                     t->left = NULL;
                     size ++;
                     return node;
                 } else if (i > t->item) { //令t為i的左子樹(shù)
                     node->right = t->right;
                     node->left = t;
                     t->right = NULL;
                     size++;
                     return node;
                 } else { 
                     free(node); //i值已經(jīng)存在于樹(shù)t中
                     return t;
                 }
             }

            3.3、刪除操作

            代碼
              /*
             **從樹(shù)中刪除i,返回樹(shù)的根結(jié)點(diǎn)
             */
             tree_node* ST_delete(int i, tree_node* t) {
                 /* Deletes i from the tree if it's there.               */
                 /* Return a pointer to the resulting tree.              */
                 tree_node* x;
                 if (t==NULL) 
                     return NULL;
                 t = splay(i,t);
                 if (i == t->item) {               /* found it */
                     if (t->left == NULL) { //左子樹(shù)為空,則x指向右子樹(shù)即可
                       x = t->right;
                     } else {
                         x = splay(i, t->left); //查找左子樹(shù)中最大結(jié)點(diǎn)max,令右子樹(shù)為max的右子樹(shù)
                         x->right = t->right;
                     }
                     size--;
                     free(t);
                     return x;
                 }
                 return t;                         /* It wasn't there */
             }

            完整代碼:

            代碼
            #include <stdio.h>
            #include <stdlib.h>

            int     size; //結(jié)點(diǎn)數(shù)量

            #define        NUM        20

            typedef struct tree_node{
                struct tree_node*    left;
                struct tree_node*    right;
                int        item;
            }tree_node;

            tree_node* splay (int i, tree_node* t) {
                tree_node N, *l, *r, *y;

                if (t == NULL) 
                    return t;

                N.left = N.right = NULL;
                 l = r = &N;
             
                 for (;;)
                 {
                     if (i < t->item) 
                     {
                         if (t->left == NULL) 
                             break;
                         if (i < t->left->item) 
                         {
                             y = t->left;                           /* rotate right */
                             t->left = y->right;
                             y->right = t;
                             t = y;
                             if (t->left == NULL) 
                                 break;
                         }
                         r->left = t;                               /* link right */
                        r = t;
                         t = t->left;
                     } else if (i > t->item)
                     {
                         if (t->right == NULL) 
                             break;
                         if (i > t->right->item) 
                         {
                             y = t->right;                          /* rotate left */
                             t->right = y->left;
                             y->left = t;
                             t = y;
                             if (t->right == NULL) 
                                 break;
                         }
                         l->right = t;                              /* link left */
                         l = t;
                         t = t->right;
                     } else {
                         break;
                     }
                 }
                 l->right = t->left;                                /* assemble */
                 r->left = t->right;
                 t->left = N.right;
                 t->right = N.left;
                 return t;
             }
             
             /*
             **將i插入樹(shù)t中,返回樹(shù)的根結(jié)點(diǎn)(item值==i)
             */
             tree_node* ST_insert(int i, tree_node *t) {
                 /* Insert i into the tree t, unless it's already there.    */
                 /* Return a pointer to the resulting tree.                 */
                 tree_node* node;
                 
                 node = (tree_node *) malloc (sizeof (tree_node));
                 if (node == NULL){
                     printf("Ran out of space\n");
                     exit(1);
                 }
                 node->item = i;
                 if (t == NULL) {
                     node->left = node->right = NULL;
                     size = 1;
                     return node;
                 }
                 t = splay(i,t);
                 if (i < t->item) {  //令t為i的右子樹(shù)
                     node->left = t->left;
                     node->right = t;
                     t->left = NULL;
                     size ++;
                     return node;
                 } else if (i > t->item) { //令t為i的左子樹(shù)
                     node->right = t->right;
                     node->left = t;
                     t->right = NULL;
                     size++;
                     return node;
                } else { 
                     free(node); //i值已經(jīng)存在于樹(shù)t中
                     return t;
                 }
             }
             
             
             /*
             **從樹(shù)中刪除i,返回樹(shù)的根結(jié)點(diǎn)
             */
             tree_node* ST_delete(int i, tree_node* t) {
                 /* Deletes i from the tree if it's there.               */
                 /* Return a pointer to the resulting tree.              */
                 tree_node* x;
                 if (t==NULL) 
                     return NULL;
                 t = splay(i,t);
                 if (i == t->item) {               /* found it */
                     if (t->left == NULL) { //左子樹(shù)為空,則x指向右子樹(shù)即可
                         x = t->right;
                     } else {
                         x = splay(i, t->left); //查找左子樹(shù)中最大結(jié)點(diǎn)max,令右子樹(shù)為max的右子樹(shù)
                         x->right = t->right;
                     }
                     size--;
                     free(t);
                     return x;
                 }
                 return t;                         /* It wasn't there */
             }
             
             void ST_inoder_traverse(tree_node*    node)
             {
                 if(node != NULL)
                 {
                     ST_inoder_traverse(node->left);
                     printf("%d ", node->item);
                     ST_inoder_traverse(node->right);
                 }
             }
             
             void ST_pre_traverse(tree_node*    node)
             {
                 if(node != NULL)
                {
                     printf("%d ", node->item);
                     ST_pre_traverse(node->left);
                     ST_pre_traverse(node->right);
                 }
             }
             
             
             void main() {
                 /* A sample use of these functions.  Start with the empty tree,         */
                 /* insert some stuff into it, and then delete it                        */
                 tree_node* root;
                 int i;
             
                 root = NULL;              /* the empty tree */
                 size = 0;
             
                 for(i = 0; i < NUM; i++)
                     root = ST_insert(rand()%NUM, root);
             
                 ST_pre_traverse(root);
                 printf("\n");
                 ST_inoder_traverse(root);
             
                 for(i = 0; i < NUM; i++)
                     root = ST_delete(i, root);
             
                 printf("\nsize = %d\n", size);
             }
             

             

            亚洲欧洲精品成人久久曰影片 | 欧美激情精品久久久久| 久久99精品久久久久久动态图| 久久久久99精品成人片欧美 | 亚洲国产成人久久综合一区77| 91精品国产综合久久香蕉| 国产高潮久久免费观看| 精品无码人妻久久久久久| 女同久久| 亚洲午夜久久久影院| 99久久婷婷免费国产综合精品| 久久久久免费视频| 2021久久精品国产99国产精品| 久久久久亚洲AV无码专区网站| 无码人妻久久一区二区三区| 91麻精品国产91久久久久| 久久婷婷色综合一区二区| 国产精品免费久久久久电影网| 亚洲欧美日韩中文久久| 久久精品国产99国产精品| 国产国产成人精品久久| 人人狠狠综合久久88成人| 亚洲а∨天堂久久精品9966| 伊人久久大香线蕉影院95| 精品久久久久香蕉网| 久久婷婷五月综合色奶水99啪| 亚洲精品久久久www| 久久国产免费| 成人精品一区二区久久久| 久久香蕉国产线看观看99| 亚洲国产精品无码久久一线| 思思久久精品在热线热| 亚洲国产成人精品91久久久| 久久久中文字幕日本| 久久精品国产一区二区电影| 99精品久久久久久久婷婷| 99久久伊人精品综合观看| 国产精品日韩深夜福利久久| 国产精品狼人久久久久影院| 精品无码久久久久久久久久| 久久伊人中文无码|