栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

跳表C++实现(skip

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

跳表C++实现(skip

skip_list.h

#pragma once
#include 
#include 
#include 
namespace util {
#ifdef DEBUG
template  void print(T arg) { std::cout << arg << " "; }
template  void debug_print(Args... args) {
  int arr[] = {(print(args), 0)...};
}

#define DEBUG_PRINT(...)                                                       
  debug_print(__FUNCTION__, ":", __LINE__, ##__VA_ARGS__);
#else
#define DEBUG_PRINT(...)
#endif

#define SKIPLIST_MAXLEVEL 4
template  class skip_list {
  using value_type = T;
  using pointer = value_type *;
  using const_pointer = const value_type *;
  using reference = value_type &;
  using const_reference = const value_type &;
  using size_t = unsigned long long;
  class skiplist_node {
    class skip_node_level {
    public:
      skip_node_level() : next_(nullptr), span_(0) {}
      ~skip_node_level() { next_ = nullptr; }
      skiplist_node *next_; 
      size_t span_;         
    };

  public:
    skiplist_node(int level, pointer data)
        : data_(data), prev_(nullptr), level_(new skip_node_level[level]) {}
    ~skiplist_node() {
      delete[] level_;
      level_ = nullptr;
      prev_ = nullptr;
    }
    pointer data_;           
    skiplist_node *prev_;    
    skip_node_level *level_; 
  };

  class sl_iterator {
  public:
    explicit sl_iterator(skiplist_node *node) : pointer_(node) {}

    sl_iterator(sl_iterator &&sli);

    inline friend bool operator==(const sl_iterator &lhs,
                                  const sl_iterator &rhs) {
      return lhs.pointer_ == rhs.pointer_;
    }
    inline friend bool operator!=(const sl_iterator &lhs,
                                  const sl_iterator &rhs) {
      return lhs.pointer_ != rhs.pointer_;
    }
    sl_iterator &operator=(sl_iterator &&sli) {
      if (this != &sli) {
        pointer_ = sli.pointer_;
        sli.pointer_ = nullptr;
      }
      return *this;
    }
    sl_iterator(const sl_iterator &&sli);
    sl_iterator &operator=(sl_iterator &sli) {
      if (this != &sli) {
        pointer_ = sli.pointer_;
      }
      return *this;
    }
    sl_iterator(const sl_iterator &sli);
    sl_iterator &operator=(const sl_iterator &&sli) {
      if (this != &sli) {
        pointer_ = sli.pointer_;
      }
      return *this;
    }
    inline sl_iterator &operator++() {
      pointer_ = pointer_->level_[0].next_;
      return *this;
    }
    inline sl_iterator operator++(int) {
      skiplist_node *tmp = pointer_;
      pointer_ = pointer_->level_[0].next_;
      return std::move(sl_iterator(tmp));
    } 
    inline sl_iterator &operator--() {
      pointer_ = pointer_->prev_;
      return *this;
    }
    inline sl_iterator operator--(int) {
      skiplist_node *tmp = pointer_;
      pointer_ = pointer_->prev_;
      return std::move(sl_iterator(tmp));
    } 
    inline reference operator()() { return *pointer_->data_; }
    inline const_reference operator()() const { return *pointer_->data_; }
    inline reference operator*() { return *pointer_->data_; }
    inline const_reference operator*() const { return *pointer_->data_; }

  private:
    skiplist_node *pointer_;
  };

  using iterator = sl_iterator;

public:
  skip_list();
  ~skip_list();
  void insert(reference data);

  void remove(const_reference data);
  template 
  friend std::ostream &operator<<(std::ostream &out, const skip_list &slst);
  iterator begin() { return std::move(iterator(header_->level_[0].next_)); }
  iterator back() { return std::move(iterator(tailer_)); }
  iterator end() { return std::move(iterator(nullptr)); }
  inline int level(bool do_latch = false) const { return level_; }
  inline size_t length(bool do_latch = false) const { return length_; }
  iterator find(const_reference data);

private:
  void remove_helper(skiplist_node *x, skiplist_node **update);
  static inline int random_level() { return random() % SKIPLIST_MAXLEVEL + 1; }
  inline void set_level(int level, bool do_latch = false) { level_ = level; }
  inline void level_deacur(bool do_latch = false) { --level_; }
  inline void set_length(size_t length, bool do_latch = false) {
    length_ = length;
  }
  inline void length_incr(bool do_latch = false) { ++length_; }
  inline void length_deacur(bool do_latch = false) { --length_; }
  inline skiplist_node *header(bool do_latch = false) const { return header_; }
  inline void set_header(skiplist_node *header, bool do_latch = false) const {
    return header_;
  }
  inline skiplist_node *tail(bool do_latch = false) const { return tailer_; }
  inline void set_tail(skiplist_node *tail, bool do_latch = false) {
    tailer_ = tail;
  }

private:
  skiplist_node *header_, *tailer_;
  size_t length_;
  int level_;
};
} // namespace util
#include "skip_list.inc"

skip_list.inc

namespace util {
template  skip_list::skip_list() {
  int j;
  level_ = 1;
  length_ = 0;
  header_ = new skiplist_node(SKIPLIST_MAXLEVEL, nullptr);
  tailer_ = nullptr;
  for (j = 0; j < SKIPLIST_MAXLEVEL; j++) {
    header_->level_[j].next_ = tailer_;
    header_->level_[j].span_ = 0;
  }
  header_->prev_ = nullptr;
}
template  skip_list::~skip_list() {
  skiplist_node *x = header();
  if (x != nullptr) {
    while (x != nullptr) {
      skiplist_node *next = x->level_[0].next_;
      delete x;
      x = next;
    }
  }
}

template  void skip_list::insert(reference data) {
  DEBUG_PRINT("nn");
  skiplist_node *update[SKIPLIST_MAXLEVEL], *x;
  unsigned int rank[SKIPLIST_MAXLEVEL];
  int i, nlevel;
  x = header();
  for (i = level() - 1; i >= 0; --i) {
    rank[i] = ((i == level() - 1) ? 0 : rank[i + 1]);
    DEBUG_PRINT(i, rank[i], "n");
    DEBUG_PRINT(x, "n")
    while (x->level_[i].next_ != nullptr &&
           *x->level_[i].next_->data_ <= data) {
      rank[i] += x->level_[i].span_;
      DEBUG_PRINT(x, "n")
      x = x->level_[i].next_;
    }
    update[i] = x;
    DEBUG_PRINT(
        "tt", i, "prev",
        (x != nullptr ? (x->data_ != nullptr ? *x->data_ : -1) : -3), "next",
        (x->level_[i].next_ != nullptr ? (x->level_[i].next_->data_ != nullptr
                                              ? *x->level_[i].next_->data_
                                              : -1)
                                       : -3),
        data, "n");
  }
  nlevel = random_level();
  DEBUG_PRINT("ttt", "nlevel", nlevel, "n");
  if (nlevel > level()) {
    for (i = level(); i < nlevel; i++) {
      rank[i] = 0;
      update[i] = header();
      update[i]->level_[i].span_ = length();
    }
    set_level(nlevel);
  }
  x = new skiplist_node(nlevel, &data);
  DEBUG_PRINT("data", x, *x->data_, "n")
  DEBUG_PRINT(
      "data",
      x->prev_ != nullptr && x->prev_->data_ != nullptr ? *x->data_ : -3, "n")

  for (i = 0; i < nlevel; ++i) {
    x->level_[i].next_ = update[i]->level_[i].next_;
    update[i]->level_[i].next_ = x;
    DEBUG_PRINT(
        "tttt", update[i],
        update[i]->data_ != nullptr ? *update[i]->data_ : -3, *x->data_,
        (x->level_[i].next_ != nullptr && x->level_[i].next_->data_ != nullptr
             ? *x->level_[i].next_->data_
             : -3),
        "n");

    x->level_[i].span_ = update[i]->level_[i].span_ - (rank[0] - rank[i]);
    update[i]->level_[i].span_ = (rank[0] - rank[i]) + 1;
  }
  for (i = nlevel; i < level(); ++i) {
    update[i]->level_[i].span_++;
  }
  x->prev_ = (update[0] == header()) ? nullptr : update[0];
  if (x->level_[0].next_ != nullptr) {
    x->level_[0].next_->prev_ = x;
  } else {
    set_tail(x);
  }
  length_incr();
}
template  void skip_list::remove(const_reference data) {
  skiplist_node *update[SKIPLIST_MAXLEVEL];
  skiplist_node *x = header();
  for (int i = level() - 1; i >= 0; --i) {
    DEBUG_PRINT(x, "n")
    while (x->level_[i].next_ != nullptr &&
           *x->level_[i].next_->data_ < data) {
      DEBUG_PRINT(x, "n")
      x = x->level_[i].next_;
    }
    update[i] = x;
    if (i == 0 && (x->level_[i].next_ == nullptr ||
                   x->level_[i].next_->data_ == nullptr ||
                   *x->level_[i].next_->data_ != data)) {
      return;
    } else if (i == 0) {
      x = x->level_[0].next_;
      break;
    }
    DEBUG_PRINT("tt", i, "prev",
                (update[i] != nullptr
                     ? (update[i]->data_ != nullptr ? *update[i]->data_ : -1)
                     : -3),
                "target",
                (x != nullptr ? (x->data_ != nullptr ? *x->data_ : -1) : -3),
                data, "n");
  }
  remove_helper(x, update);
}
template 
void skip_list::remove_helper(skiplist_node *x, skiplist_node **update) {
  int i;
  for (i = 0; i < level(); i++) {
    if (update[i]->level_[i].next_ == x) {
      update[i]->level_[i].span_ += x->level_[i].span_ - 1;
      update[i]->level_[i].next_ = x->level_[i].next_;
    } else {
      update[i]->level_[i].span_ -= 1;
    }
  }
  if (x->level_[0].next_) {
    x->level_[0].next_->prev_ = x->prev_;
  } else {
    set_tail(x->prev_);
  }
  while (level() > 1 && header()->level_[level() - 1].next_ == nullptr) {
    length_deacur();
    level_deacur();
  }
}
template 
std::ostream &operator<<(std::ostream &out, const skip_list &slst) {
  if (slst.header() != nullptr) {
    const typename skip_list::skiplist_node *x = slst.header();
    for (int i = slst.level() - 1; i >= 0; i--) {
      const auto *node = x->level_ + i;
      const typename skip_list::skiplist_node *iter = node->next_;
      while (iter != nullptr) {
        T *data = iter->data_;
        if (data != nullptr) {
          out << "[" << *data << "," << iter->level_[i].span_ << "]"
              << "->";
        } else {
          out << "nullptr->";
        }
        iter = iter->level_[i].next_;
      }
      out << "nullptr" << std::endl;
    }
  }
}
template  skip_list::sl_iterator::sl_iterator(sl_iterator &&sli) {
  if (this != &sli) {
    pointer_ = sli.pointer_;
    sli.pointer_ = nullptr;
  }
}

template 
skip_list::sl_iterator::sl_iterator(const sl_iterator &&sli) {
  if (this != &sli) {
    pointer_ = sli.pointer_;
  }
}

template 
skip_list::sl_iterator::sl_iterator(const sl_iterator &sli) {
  if (this != &sli) {
    pointer_ = sli.pointer_;
  }
}
template 
typename skip_list::iterator skip_list::find(const_reference data) {
  skiplist_node *x = header();
  for (int i = level() - 1; i >= 0; --i) {
    DEBUG_PRINT(x, "n")
    while (x->level_[i].next_ != nullptr && *x->level_[i].next_->data_ < data) {
      DEBUG_PRINT(x, "n")
      x = x->level_[i].next_;
    }
    if (x->level_[i].next_ != nullptr && *x->level_[i].next_->data_ == data) {
      return std::move(iterator(x->level_[i].next_));
    }
  }
  return end();
}
} // namespace util

TEST

#include "operation/stats.h"
#include "skip_list.h"
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
void TEST_SKIPLIST() {
  util::skip_list slst;
  vector vec;
  vec.reserve(20);
  for (int i = 0; i < 20; i++) {
    vec.push_back((int)(random() % 1001));
  }
  for(int i = 0;i < 20;i++){
    slst.insert(vec[i]);
  }
  std::cout << slst << std::endl;
  slst.remove(5);
  std::cout << slst << std::endl;
  slst.remove(10);
  std::cout << slst << std::endl;
  slst.remove(0);
  std::cout << slst << std::endl;
}
void TEST_SKIPLIST_OOM(char *argv[]) {
  if (argv[1] == nullptr) {
    printf("input the correct process namen");
    exit(-1);
  }
  pid_t pid = get_pid(argv[1]);
  if (pid <= 0) {
    printf("input the correct process namen");
    exit(-1);
  }
  unsigned int mem_use = 0, pre_mem_use = 0;
  int loops = 100;
  for (int i = 0; i < loops; i++) {
    if (i == 0) {
      pre_mem_use = get_proc_mem(pid);
      mem_use = max(pre_mem_use, mem_use);
    }
    mem_use = max(get_proc_mem(pid), mem_use);
    util::skip_list slst;
    vector vec;
    vec.reserve(10000);
    for (int i = 0; i < 10000; i++) {
      vec.push_back(i);
      slst.insert(vec[i]);
    }
    slst.remove(5);
    slst.remove(10);
    slst.remove(0);
  }
  assert(mem_use < pre_mem_use * 4);
  printf("OOM test passn");
}
void TEST_SKIPLIST_ITERATOR() {
  util::skip_list slst;
  vector vec;
  vec.reserve(10);
  for (int i = 0; i < 10; i++) {
    vec.push_back(i);
    slst.insert(vec[i]);
  }
  bool debug_flag1 = slst.begin() == slst.end();
  int i = 0;
  int pre_value = *slst.begin();
  for (auto iter = slst.begin(); iter != slst.end() && i < vec.size();
       iter++, i++) {
    assert(*iter == vec[i] && pre_value <= *iter);
    pre_value = *iter;
  }
  i = vec.size() - 1;
  for (auto iter = slst.back(); iter != slst.end() && i >= 0; iter--, i--) {
    assert(*iter == vec[i]);
  }
  printf("iterator test passn");
}

void TEST_SKIPLIST_FIND() {
  util::skip_list slst;
  vector vec;
  vec.reserve(10);
  for (int i = 0; i < 10; i++) {
    vec.push_back(i);
    slst.insert(vec[i]);
  }
  assert(slst.find(5) != slst.end() && *slst.find(5) == 5);
  assert(slst.find(11) == slst.end());
  assert(slst.find(-4) == slst.end());
  printf("find test passn");
}

int main(int argc, char *argv[]) {
  TEST_SKIPLIST(); 
  TEST_SKIPLIST_FIND();
  TEST_SKIPLIST_ITERATOR();
  TEST_SKIPLIST_OOM(argv);
  return 0;
}

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/311824.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号