zoukankan      html  css  js  c++  java
  • SplayTree伸展树的非递归实现(自底向上)

    Splay Tree 是二叉查找树的一种,它与平衡二叉树、红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋转到树根的位置,这样就使得Splay Tree天生有着一种类似缓存的能力,因为每次被查找到的节点都会被搬到树根的位置,所以当80%的情况下我们需要查找的元素都是某个固定的节点,或者是一部分特定的节点时,那么在很多时候,查找的效率会是O(1)的效率!当然如果查找的节点是很均匀地分布在不同的地方时,Splay Tree的性能就会变得很差了,但Splay Tree的期望的时间复杂度还是O(nlogn)的。

    下图是对伸展树查询节点1和删除节点6的结果,利用我的伸展树来实现

      1 头文件————————————————————————————
      2 #ifndef _SPLAY_TREE_H_
      3 #define _SPLAY_TREE_H_
      4 
      5 #include <iostream>
      6 #include <iomanip>
      7 #include <cassert>
      8 #include <stack>
      9 
     10 typedef struct splay_tree_node_t
     11 {
     12      int data;
     13      struct splay_tree_node_t *left;
     14      struct splay_tree_node_t *right;
     15 } splay_tree_node, *position, *splay_tree;
     16 
     17 void print_splay_tree(splay_tree st, int depth, int ctrl);//ctrl:0=root 1=left 2=right
     18 position find_max(splay_tree st);
     19 void insert_splay_tree(splay_tree *pst, int x);
     20 void delete_splay_tree(splay_tree *pst, int x);
     21 int find_splay_tree(splay_tree *pst, int x);
     22 
     23 splay_tree rotate3(position child, position parent, position grand_parent, int *type);
     24 splay_tree rotate2(position child, position parent);
     25 
     26 inline void fcn(int type, position cur, position parent, position grand_parent);
     27 #endif
     28 
     29 源文件——————————————————————————————
     30 #include "./SplayTree.h"
     31 
     32 splay_tree rotate3(position child, position parent, position grand_parent, int *type)
     33 {
     34      assert(child != NULL && parent != NULL && grand_parent != NULL);
     35 
     36      if(parent->left == child && grand_parent->left == parent)//child, parent, grand_parent一字形东北方向 0
     37      {
     38           *type = 0;
     39           grand_parent->left = parent->right;
     40           parent->right = grand_parent;
     41 
     42           parent->left = child->right;
     43           child->right = parent;
     44      }
     45      else if(parent->right == child && grand_parent->right == parent)//child, parent, grand_parent一字形西北方向 1
     46      {
     47           *type = 1;
     48           grand_parent->right = parent->left;
     49           parent->left = grand_parent;
     50 
     51           parent->right = child->left;
     52           child->left = parent;
     53      }
     54      else if(parent->right == child && grand_parent->left == parent)//child, parent, grand_parent之字形<
     55      {
     56           *type = 2;
     57           grand_parent->left = child->right;
     58           parent->right = child->left;
     59           child->left = parent;
     60           child->right = grand_parent;
     61      }
     62      else if(parent->left == child && grand_parent->right == parent)//child, parent, grand_parent之字形>
     63      {
     64           *type = 3;
     65           grand_parent->right = child->left;
     66           parent->left = child->right;
     67           child->right = parent;
     68           child->left - grand_parent;
     69      }
     70 
     71      return child;
     72 }
     73 splay_tree rotate2(position child, position parent)
     74 {
     75      assert(child != NULL && parent != NULL);
     76      if(parent->left == child)
     77      {
     78           parent->left = child->right;
     79           child->right = parent;
     80      }
     81      else//parent->right == child
     82      {
     83           parent->right = child->left;
     84           child->left = parent;
     85      }
     86      return child;
     87 }
     88 
     89 position find_max(splay_tree st)
     90 {
     91      while(NULL != st && NULL != st->right)
     92           st = st->right;
     93      return st;
     94 }
     95 
     96 void print_splay_tree(splay_tree st, int depth, int ctrl)
     97 {
     98      if(NULL != st)
     99      {
    100           std::cout<<std::setw(depth);
    101           if(0 == ctrl)
    102                std::cout<<"root:";
    103           else if(1 == ctrl)
    104                std::cout<<"left";
    105           else if(2 == ctrl)
    106                std::cout<<"right";
    107           std::cout<<st->data<<std::endl;
    108           print_splay_tree(st->left, depth+6, 1);
    109           print_splay_tree(st->right, depth+6, 2);
    110      }
    111 }
    112 void insert_splay_tree(splay_tree *pst, int x)
    113 {
    114      if(NULL == *pst)
    115      {
    116           position tmp = new splay_tree_node;
    117           if(NULL == tmp)
    118                return ;
    119           tmp->data = x;
    120           tmp->left = tmp->right = NULL;
    121           *pst = tmp;
    122      }
    123      else if(x < (*pst)->data)
    124           insert_splay_tree(&((*pst)->left), x);
    125      else if(x > (*pst)->data)
    126           insert_splay_tree(&((*pst)->right), x);
    127      else
    128           return ;
    129 }
    130 void delete_splay_tree(splay_tree *pst, int x)
    131 {
    132      assert(NULL != pst);
    133      int res = find_splay_tree(pst, x);
    134      if(res == 0)//not found
    135           return ;
    136      //此时root指向的就是要删除的节点,因为find_splay_tree操作将节点推至向根
    137      position root = *pst;
    138      splay_tree splay_left = root->left;
    139      splay_tree splay_right = root->right;
    140      position tmp = find_max(splay_left);
    141      if(NULL == tmp)//无左子树
    142           *pst = splay_right;//将右子树为新树
    143      else
    144      {
    145           find_splay_tree(&splay_left, tmp->data);
    146           splay_left->right = splay_right;//将右子树为左子树的新右子树
    147           *pst = splay_left;//将左子树为新树
    148      }
    149 }
    150 int find_splay_tree(splay_tree *pst, int x)
    151 {
    152      assert(NULL != pst);
    153      position cur = *pst;
    154      std::stack<position> s;
    155 
    156      while(cur != NULL && cur->data != x)//沿着查找路径将树节点以此压入栈中
    157      {
    158           if(x < cur->data)
    159           {
    160                s.push(cur);
    161                cur = cur->left;
    162           }
    163           else
    164           {
    165                s.push(cur);
    166                cur = cur->right;
    167           }
    168      }
    169 
    170      if(NULL == cur)//not found
    171           return false;
    172 
    173      position parent, grand_parent;
    174      int type = -1;//0一字形东北方向; 1一字形西北方向; 2之字形<; 3之字形<
    175      //每次取父节点和祖父节点和当前节点进行伸展调节
    176      while(s.size() >= 2)
    177      {
    178           parent = s.top();
    179           s.pop();
    180           //fcn判断伸展的类型以便重新调整原来的树指针,调整好了才可以再次伸展
    181           fcn(type, cur, parent, grand_parent);
    182           grand_parent = s.top();
    183           s.pop();
    184           cur = rotate3(cur, parent, grand_parent, &type);//after rotate, cur is the new "root"
    185      }
    186      if(s.empty())
    187           *pst = cur;
    188      else //rotate cur and the old root
    189      {
    190           parent = s.top();
    191           s.pop();
    192           fcn(type, cur, parent, grand_parent);
    193           //此时只对cur和根节点进行伸展,完成后find_splay_tree函数结束
    194           *pst = rotate2(cur, parent);
    195      }
    196 
    197      return true;
    198 }
    199 
    200 //fcn判断伸展的类型以便重新调整原来的树指针,调整好了才可以再次伸展
    201 inline void fcn(int type, position cur, position parent, position grand_parent)
    202 {
    203      if(type == 0)
    204           {
    205                if(grand_parent == parent->left)
    206                     parent->left = cur;
    207                else if(grand_parent == parent->right)
    208                     parent->right = cur;
    209           }
    210           else if(type == 1)
    211           {
    212                if(grand_parent == parent->left)
    213                     parent->left = cur;
    214                else if(grand_parent == parent->right)
    215                     parent->right = cur;
    216           }
    217           else if(type == 2)
    218           {
    219                if(grand_parent == parent->left)
    220                     parent->left = cur;
    221                else if(grand_parent == parent->right)
    222                     parent->right = cur;
    223           }
    224           else if(type == 3)
    225           {
    226                if(grand_parent == parent->left)
    227                     parent->left = cur;
    228                else if(grand_parent == parent->right)
    229                     parent->right = cur;
    230           }
    231 }
  • 相关阅读:
    AWVS 安全渗透扫描
    Nmon 监控结果分析
    Jmeter 插件图表分析
    Nmon 安装
    子母钟系统(卫星时钟系统)在医院网络中的架设与设计
    从NTP网络授时到社交GPS千奇百怪的应用方式
    NTP网络时钟系统技术参数与详细介绍
    GPS北斗子母钟系统在某机场系统中的应用
    GPS北斗时间频率信号源的定义及简介
    ntp对时服务器同步网络中计算机详细配置
  • 原文地址:https://www.cnblogs.com/zxh1210603696/p/3252758.html
Copyright © 2011-2022 走看看