自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺談基礎(chǔ)算法之AVL tree和splay tree(三)

開發(fā) 架構(gòu) 算法
平衡二叉樹:上文我們只實(shí)現(xiàn)了單旋,但是實(shí)際中為了達(dá)到平衡很多是要做雙旋操作的。先來看一張雙旋后的一張圖,明顯右邊的圖查詢的時(shí)候會(huì)更便捷。

承接上文,我們繼續(xù)聊這個(gè)話題。

平衡二叉樹:AVL Tree(1962)

上文我們只實(shí)現(xiàn)了單旋,但是實(shí)際中為了達(dá)到平衡很多是要做雙旋操作的。

先來看一張雙旋后的一張圖,明顯右邊的圖查詢的時(shí)候會(huì)更便捷。

  整個(gè)過程

  下面我們就進(jìn)行代碼實(shí)踐。

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3.  
  4. #define max(a,b)    (((a) > (b)) ? (a) : (b))  
  5.  
  6. typedef struct AvlNode{ 
  7.     int data; 
  8.     struct AvlNode *left_child, *right_child; 
  9. } AvlNode; 
  10.  
  11. AvlNode *root; 
  12.  
  13. /*    旋轉(zhuǎn)動(dòng)作開始        */ 
  14. AvlNode *rotate_LL(AvlNode *parent){ 
  15.     AvlNode *child = parent->left_child; 
  16.     parent->left_child = child->right_child; 
  17.     child->right_child = parent; 
  18.     return child; 
  19.  
  20. AvlNode *rotate_RR(AvlNode *parent){ 
  21.     AvlNode *child = parent->right_child; 
  22.     parent->right_child = child->left_child; 
  23.     child->left_child = parent; 
  24.     return child; 
  25.  
  26. AvlNode *rotate_RL(AvlNode *parent){ 
  27.     AvlNode *child = parent->right_child; 
  28.     parent->right_child = rotate_LL(child); 
  29.     return rotate_RR(parent); 
  30.  
  31. AvlNode *rotate_LR(AvlNode *parent){ 
  32.     AvlNode *child = parent->left_child; 
  33.     parent->left_child = rotate_RR(child); 
  34.     return rotate_LL(parent); 
  35. /*    旋轉(zhuǎn)動(dòng)作結(jié)束    */ 
  36.  
  37. int get_height(AvlNode *node){ 
  38.     int height = 0; 
  39.     if(node != NULL){ 
  40.         height = 1 + max(get_height(node->left_child), get_height(node->right_child)); 
  41.     } 
  42.     return height; 
  43.  
  44. int get_balance(AvlNode *node){ 
  45.     if(node == NULL) return 0; 
  46.     return get_height(node->left_child) - get_height(node->right_child); 
  47.  
  48. /*    平衡二叉樹    */ 
  49. AvlNode *balance_tree(AvlNode **node){ 
  50.     int height_diff = get_balance(*node); /* 平衡因子在-1到1之間*/ 
  51.  
  52.     if(height_diff > 1){ 
  53.         if(get_balance((*node)->left_child) > 0){ 
  54.             *node = rotate_LL(*node); 
  55.         }else
  56.             *node = rotate_LR(*node); 
  57.         } 
  58.     }else if(height_diff < -1){ 
  59.         if(get_balance((*node)->right_child) < 0){ 
  60.             *node = rotate_RR(*node); 
  61.         }else
  62.             *node = rotate_RL(*node); 
  63.         } 
  64.     } 
  65.     return *node; 
  66.  
  67. AvlNode *avl_add(AvlNode **root, int key){ 
  68.     if(*root == NULL){ 
  69.         *root = (AvlNode *)malloc(sizeof(AvlNode)); 
  70.         if(*root == NULL){ 
  71.             printf("內(nèi)存分配失敗!\n"); 
  72.             exit(-1); 
  73.         } 
  74.  
  75.         (*root)->data = key; 
  76.         (*root)->left_child = (*root)->right_child = NULL; 
  77.     }else if(key < (*root)->data){ 
  78.         (*root)->left_child = avl_add(&((*root)->left_child), key); 
  79.         //balance_tree(root); 
  80.     }else if(key > (*root)->data){ 
  81.         (*root)->right_child = avl_add(&((*root)->right_child), key); 
  82.         //balance_tree(root); 
  83.     }else
  84.         printf("復(fù)制%d失敗!\n", key); 
  85.         exit(-1); 
  86.     } 
  87.  
  88.     return *root; 
  89.  
  90. AvlNode *avl_print(AvlNode *node){ 
  91.     if(node == NULL) return NULL; 
  92.  
  93.     printf("%d->", node->data); 
  94.  
  95.     avl_print(node->left_child); 
  96.     avl_print(node->right_child); 
  97.     return node; 
  98.  
  99. int main(){ 
  100.     avl_add(&root, 24); 
  101.     avl_add(&root, 17); 
  102.     avl_add(&root, 40); 
  103.     avl_add(&root, 8); 
  104.     avl_add(&root, 22); 
  105.     avl_add(&root, 18); 
  106.     avl_add(&root, 23); 
  107.  
  108.     printf("打印二叉樹\n"); 
  109.     avl_print(root); 
  110.     printf("\n"); 
  111.  
  112.     balance_tree(&root); 
  113.     printf("打印二叉樹\n"); 
  114.     avl_print(root); 
  115.     printf("\n"); 
  116.     return 0; 

 

                   

讓我們看看伸展樹!     

伸展樹(Splay Tree,1985)

伸展樹的基本原理:

   

 舉例

我抽取一部分lighttpd-1.4.31.tar.gz中的代碼,來講解 

想看具體的代碼實(shí)踐的,可以到如下位置觀看

我的代碼結(jié)構(gòu):

代碼部分

  1. /*~ splaytree.h~*/ 
  2. typedef struct tree_node{ 
  3.     struct tree_node *left, *right; 
  4.     int key;    /*  關(guān)鍵字  */ 
  5.     int size;   /*  結(jié)點(diǎn)數(shù)目    */ 
  6.     void *data; 
  7. } splay_tree; 
  8. /*我現(xiàn)在只寫這兩個(gè)方法*/ 
  9. splay_tree * splaytree_insert(splay_tree *t, int key, void *data); 
  10. splay_tree * splaytree_splay(splay_tree *t, int key); 
  11. #define node_size(x) (((x)==NULL) ? 0 : ((x)->size)) 

這個(gè)沒有必要多講,看注釋和方法名稱自然就知道干嗎的了!

  1. /* splaytree.c */ 
  2. #include "splaytree.h" 
  3. #include <stdio.h> 
  4. #include <stdlib.h> 
  5. #include <assert.h> 
  6. #define compare(i,j) ((i) - (j)) 
  7. splay_tree * splaytree_insert(splay_tree *t, int key, void *data){ 
  8.     splay_tree * new
  9.  
  10.     if (t != NULL) { 
  11.         t = splaytree_splay(t, key); 
  12.         if(compare(key, t->key) == 0){ /*   該結(jié)點(diǎn)已存在    */ 
  13.             return t; 
  14.         } 
  15.     } 
  16.     new = (splay_tree *) malloc (sizeof (splay_tree)); 
  17.     assert(new); 
  18.     if (t == NULL) { 
  19.         new->left = new->right = NULL; 
  20.     } else if (compare(key, t->key) < 0) { 
  21.         new->left = t->left; 
  22.         new->right = t; 
  23.         t->left = NULL; 
  24.         t->size = 1 + node_size(t->right); 
  25.     } else { 
  26.         new->right = t->right; 
  27.         new->left = t; 
  28.         t->right = NULL; 
  29.         t->size = 1 + node_size(t->left); 
  30.     } 
  31.     new->key = key; 
  32.     new->data = data; 
  33. new->size = 1 + node_size(new->left) + node_size(new->right); 
  34.     return new
  35. splay_tree * splaytree_splay(splay_tree *t, int key){ 
  36.     splay_tree N, *l, *r, *child; /*    臨時(shí)變量用于裝配*t使用  */ 
  37.     int cmp, l_size, r_size; 
  38.     if (t == NULL) return t; 
  39.     N.left = N.right = NULL; 
  40.     l = r = &N; 
  41.     l_size = r_size = 0; 
  42.     for (;;) { 
  43.         cmp = compare(key, t->key); 
  44.  
  45.         if (cmp < 0) { 
  46.             if(t->left == NULL) break
  47.             if (compare(key, t->left->key) < 0) { 
  48.                 child = t->left;                        /*  右旋    */ 
  49.                 t->left = child->right; 
  50.                 child->right = t; 
  51.                 t->size = 1 + node_size(t->left) + node_size(t->right); 
  52.                 t = child; 
  53.                 if(t->left == NULL) break
  54.             } 
  55.             r->left = t;                                /*  右鏈    */ 
  56.             r = t; 
  57.             t = t->left; 
  58.             r_size += 1 + node_size(r->right); 
  59.         } else if (cmp > 0) { 
  60.             if(t->right == NULL) break
  61.  
  62.             if (compare(key, t->right->key) > 0) { 
  63.                 child =  t->right; 
  64.                 t->right = child->left; 
  65.                 child->left = t; 
  66.                 t->size = 1 + node_size(t->left) + node_size(t->right); 
  67.                 t = child; 
  68.                 if(t->right == NULL) break
  69.             } 
  70.             l->right = t; 
  71.             l = t; 
  72.             t = t->right; 
  73.             l_size += 1 + node_size(l->left); 
  74.         } else { 
  75.             break
  76.         } 
  77.     } 
  78.     l_size += node_size(t->left); 
  79.     r_size += node_size(t->right); 
  80.     t->size = 1 + l_size + r_size; 
  81.  
  82.     l->right = r->left = NULL; 
  83.  
  84.     /*  校驗(yàn)size數(shù)據(jù)    */ 
  85.     /*右孩子的左結(jié)點(diǎn)不計(jì)算在內(nèi)*/ 
  86.     for(child = N.right; child != NULL; child = child->right){ 
  87.         child->size = l_size; 
  88.         l_size -= 1 + node_size(child->left); 
  89.     } 
  90.     for(child = N.left; child != NULL; child = child->left){ 
  91.         child->size = r_size; 
  92.  r_size -= 1 +node_size(child->right); 
  93.     } 
  94.     /*  裝配數(shù)據(jù)    */ 
  95.     l->right = t->left; 
  96.     r->left = t->right; 
  97.     t->left = N.right; 
  98.     t->right = N.left; 
  99.     return t; 

看到上面一坨代碼估計(jì)大家不知所云了?

我就針對(duì)性的講解一下。

>> 重點(diǎn)講講講核心算法splaytree_splay()方法吧!

這個(gè)if講通,那么另一個(gè)else if也好理解。

  1. if (cmp < 0) { 
  2.             if(t->left == NULL) break
  3.  
  4.             if (compare(key, t->left->key) < 0) { 
  5.                 child = t->left;                        /*  右旋    */ 
  6.                 t->left = child->right; 
  7.                 child->right = t; 
  8.                 t->size = 1 + node_size(t->left) + node_size(t->right); 
  9.                 t = child; 
  10.  
  11.                 if(t->left == NULL) break
  12.             } 
  13.             r->left = t;                                /*  右鏈    */ 
  14.             r = t; 
  15.             t = t->left; 
  16.             r_size += 1 + node_size(r->right); 
  17.         } 

這是一個(gè)右旋的過程。

  child = t->left

t->left = child->right; child->right = t;

 最后:t = child

這是一個(gè)右鏈的過程

 r->left = t;r=t;

 t = t->left

3>main.c

  1. #include <stdio.h> 
  2. #include "splaytree.h" 
  3. splay_tree * splaytree_print(splay_tree *t){ 
  4.     if(t != NULL){ 
  5.         printf("t->data:%d\t t->key:%d t->size:%d\n", *((int *)t->data), t->key, t->size); 
  6.         splaytree_print(t->left); 
  7.         splaytree_print(t->right); 
  8.     } 
  9. int main(){ 
  10.     splay_tree *root; 
  11.     root = NULL; 
  12.     int data1 = 1000; 
  13.     root = splaytree_insert(root, 20, &data1); 
  14.     int data2 = 200; 
  15.     root = splaytree_insert(root, 5, &data2); 
  16.     int data3 = 300; 
  17.     root = splaytree_insert(root, 3, &data3); 
  18.     int data4 = 100; 
  19.     root = splaytree_insert(root, 10, &data4); 
  20.     printf("打印結(jié)果*************\n"); 
  21.     splaytree_print(root); 
  22.  
  23.  
  24.     //這里應(yīng)該有個(gè)數(shù)據(jù)查詢過程,但是我沒有寫。注意在調(diào)用的時(shí)候調(diào)用一下splay方法, 
  25.     //那么熱數(shù)據(jù)自然就跑到頂端了。 
  26.     printf("查詢方法中調(diào)用這個(gè)伸展函數(shù)之后,打印結(jié)果*************\n"); 
  27.     root = splaytree_splay(root, 3); 
  28.     splaytree_print(root); 
  29.     return 0; 

這里我沒有把查詢伸展樹的過程寫下來,只是強(qiáng)調(diào)一下,在查詢的過程中,只要調(diào)用這個(gè)核心方法,那么自然熱數(shù)據(jù)就跑到頂端了。

看一下過程

 

 

原文鏈接:http://www.cnblogs.com/baochuan/archive/2012/10/16/2716641.html 

【編輯推薦】

  1. 大型網(wǎng)站后臺(tái)構(gòu)建實(shí)踐
  2. 圖片存儲(chǔ)架構(gòu)學(xué)習(xí):緩存,架構(gòu)師的美麗小三
  3. 淺談大型網(wǎng)站的算法和架構(gòu)(二)
  4. 淺談大型網(wǎng)站的算法和架構(gòu)
  5. 企業(yè)應(yīng)用架構(gòu)模式之工作單元模式
責(zé)任編輯:張偉 來源: 川山甲的博客
相關(guān)推薦

2022-10-30 10:03:20

B+數(shù)據(jù)庫數(shù)據(jù)

2024-02-27 07:35:55

B-TreeB+TreeMySQL

2019-11-26 15:12:08

數(shù)據(jù)存儲(chǔ)B+樹

2022-06-01 12:04:02

項(xiàng)目Webpack

2017-07-18 16:25:31

機(jī)器學(xué)習(xí)算法決策樹

2022-09-26 07:56:53

AVL算法二叉樹

2009-09-09 17:08:27

LINQ Expres

2011-08-16 09:13:45

tree中文man

2023-10-10 11:02:00

LSM Tree數(shù)據(jù)庫

2009-09-09 17:02:05

LINQ Expres

2023-01-04 08:33:31

Linuxtree命令

2022-10-29 08:44:39

分布式數(shù)據(jù)庫存儲(chǔ)

2010-10-12 16:50:14

MySQL Hash索

2011-11-24 21:12:35

ibmdw

2020-02-13 17:27:31

CAPPaxos 共識(shí)算法

2021-06-28 07:01:50

Webpack 前端Tree shakin

2017-07-20 15:59:45

LinuxDevice Tree

2022-02-10 14:23:16

WebpackJavaScript

2023-01-26 00:59:39

B-Treegolang度量衡

2020-06-28 09:03:26

Linuxtree命令目錄
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)