Advertisement
pavelperc

TestSkipList

Nov 1st, 2018
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.54 KB | None | 0 0
  1.  
  2. #include <vector>
  3.  
  4. using namespace std;
  5.  
  6. const int MAX_LEVELS = 10;
  7.  
  8. /** \brief СкипЛист на стероидах.
  9.  * Умеет печатать себя с помощью PRINT_REFS, PRINT_VALUES, PRINT_KEYS.
  10.  * Ещё умеет запрашивать нужную ноду через operator[], вычислять длину себя, и среднюю длину уровней.
  11.  * Может создаваться по заданным значениям ключей и их уровней.
  12.  */
  13. class TestSkipList
  14.         : public SkipList<std::string, int, MAX_LEVELS>
  15. {
  16. public:
  17.     explicit TestSkipList(double prob = 0.5) : SkipList(prob)
  18.     {}
  19.  
  20.     /// Constr with initial values and levels. Levels must be in [0..MAX_LEVELS]
  21.     TestSkipList(const vector<int>& keys,
  22.                  const vector<int>& levels,
  23.                  const vector<string>& values = vector<string>()
  24.     ) : SkipList()
  25.     {
  26.         if (keys.size() != levels.size())
  27.             throw invalid_argument("keys.size != levels.size");
  28.        
  29.         if (!values.empty() && !levels.empty() && values.size() != levels.size())
  30.             throw invalid_argument("values.size != levels.size");
  31.        
  32.         Node* last = _preHead;
  33.         for (int i = 0; i < keys.size(); ++i)
  34.         {
  35.             string value = values.empty() ? "val" + to_string(i) : values[i];
  36.             Node* newNode = new Node(keys[i], value);
  37.             newNode->levelHighest = levels[i] - 1;
  38.             if (levels[i] > MAX_LEVELS || levels[i] < 0)
  39.                 throw invalid_argument("some level is not in [0..MAX_LEVELS]");
  40.  
  41.             last->next = newNode;
  42.             newNode->next = _preHead;
  43.  
  44.             last = newNode;
  45.         }
  46.  
  47.         for (int i = 0; i < MAX_LEVELS; ++i)
  48.         {
  49.             Node* prev = _preHead;
  50.  
  51.             Node* curr = _preHead;
  52.             while (curr->next != _preHead)
  53.             {
  54.                 curr = curr->next;
  55.  
  56.                 if (curr->levelHighest >= i)
  57.                 {
  58.                     prev->nextJump[i] = curr;
  59.                     prev = curr;
  60.                 }
  61.             }
  62.             prev->nextJump[i] = _preHead;
  63.         }
  64.     }
  65.  
  66.     double getProbability()
  67.     {
  68.         return _probability;
  69.     }
  70.  
  71.     /// -1 returns _preHead.
  72.     Node* operator[](int pos)
  73.     {
  74.         if (pos < -1)
  75.             throw invalid_argument("pos < -1");
  76.         Node* curr = _preHead;
  77.         while (pos-- != -1)
  78.             curr = curr->next;
  79.         return curr;
  80.     }
  81.  
  82.     int size()
  83.     {
  84.         int ans = 0;
  85.         Node* curr = _preHead;
  86.         while (curr->next != _preHead)
  87.         {
  88.             ans++;
  89.             curr = curr->next;
  90.         }
  91.         return ans;
  92.     }
  93.  
  94.     double meanHeight()
  95.     {
  96.         long hSum = 0;
  97.         int size = 0;
  98.         Node* curr = _preHead;
  99.         while (curr->next != _preHead)
  100.         {
  101.             curr = curr->next;
  102.             hSum += curr->levelHighest + 1;
  103.             size++;
  104.         }
  105.         return (double) hSum / size;
  106.     }
  107.  
  108.     /// Displays only heights of all nodes. If you need to validate references, use PRINT_REF.
  109.     void PRINT_KEYS()
  110.     {
  111.         printf("\nPRINT_KEYS\n");
  112.         for (int i = MAX_LEVELS - 1; i >= -1; --i)
  113.         {
  114.             printf("%2d pr ", i);
  115.             Node* curr = _preHead;
  116.             while (curr->next != _preHead)
  117.             {
  118.                 curr = curr->next;
  119.                 if (curr->levelHighest < i)
  120.                     printf("--- ");
  121.                 else
  122.                     printf("%3d ", curr->key);
  123.             }
  124.             printf("pr\n");
  125.         }
  126.         cout << endl;
  127.     }
  128.  
  129.     /// Works like PRINT_KEYS, but prints values instead of keys.
  130.     /// size - max size of string value
  131.     void PRINT_VALUES(unsigned int size = 5)
  132.     {
  133.         string pattern_val = "%" + to_string(size) + "s ";
  134.         string pattern_sparse = string(size, '-') + " ";
  135.        
  136.         printf("\nPRINT_VALUES\n");
  137.         for (int i = MAX_LEVELS - 1; i >= -1; --i)
  138.         {
  139.             printf("%2d pr ", i);
  140.             Node* curr = _preHead;
  141.             while (curr->next != _preHead)
  142.             {
  143.                 curr = curr->next;
  144.                 if (curr->levelHighest < i)
  145.                     printf(pattern_sparse.c_str());
  146.                 else
  147.                     printf(pattern_val.c_str(), curr->value.c_str());
  148.             }
  149.             printf("pr\n");
  150.         }
  151.         cout << endl;
  152.     }
  153.  
  154.     /// It is like PRINT_KEYS, but it iterates over references in sparse levels.
  155.     void PRINT_REFS()
  156.     {
  157.         printf("\nPRINT_REFS\n");
  158.         for (int i = MAX_LEVELS - 1; i >= 0; --i)
  159.         {
  160.             printf("%2d pr ", i);
  161.             Node* sparse = _preHead;
  162.             Node* full = _preHead->next;
  163.             while (full != _preHead)
  164.             {
  165.                 if (sparse->nextJump[i] == full->next)
  166.                 {
  167.                     printf("--> ");
  168.                 } else if (sparse->nextJump[i] == full)
  169.                 {
  170.                     printf("%3d ", full->key);
  171.                     sparse = sparse->nextJump[i];
  172.                 } else
  173.                 {
  174.                     printf("--- ");
  175.                 }
  176.                 full = full->next;
  177.             }
  178.             printf("pr\n");
  179.         }
  180.         printf("-1 pr ");
  181.         Node* curr = _preHead->next;
  182.         while (curr != _preHead)
  183.         {
  184.             printf("%3d ", curr->key);
  185.             curr = curr->next;
  186.         }
  187.         printf("pr\n");
  188.         cout << endl;
  189.     }
  190.  
  191.  
  192.     string joinKeysToString()
  193.     {
  194.         stringstream ss;
  195.         Node* curr = _preHead;
  196.         while (curr->next != _preHead)
  197.         {
  198.             curr = curr->next;
  199.             ss << curr->key << " ";
  200.         }
  201.         return ss.str().substr(0, ss.str().size() - 1);
  202.     }
  203.  
  204.     string joinValuesToString()
  205.     {
  206.         stringstream ss;
  207.         Node* curr = _preHead;
  208.         while (curr->next != _preHead)
  209.         {
  210.             curr = curr->next;
  211.             ss << curr->value << " ";
  212.         }
  213.         return ss.str().substr(0, ss.str().size() - 1);
  214.     }
  215. };
  216.  
  217.  
  218. TEST(SkipList, simple)
  219. {
  220.     TestSkipList list();
  221.  
  222. //    TestSkipList list1(0.3);
  223. //    TestSkipList list2(0.6);
  224. //    for (int i = 0; i < 20; ++i)
  225. //    {
  226. //        list1.insert("val", i);
  227. //        list2.insert("val", i);
  228. //    }
  229. //    cout << "list1" << endl;
  230. //    list1.PRINT_REFS();
  231. //    cout << "list2" << endl;
  232. //    list2.PRINT_REFS();
  233. //    list2.PRINT_VALUES();
  234. //    list2.PRINT_KEYS();
  235.  
  236. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement