当前位置: 首页 > wzjs >正文

个人建 行业 网站网站seo搜索引擎优化怎么做

个人建 行业 网站,网站seo搜索引擎优化怎么做,平顶山网站建设,企业网站的功能模块Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

         Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!

我的博客:<但凡.

我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C++修炼之路》

欢迎点赞,关注!

目录

1、跳表引入

        1.1、背景

        1.2、跳表的基本原理

2、跳表模拟实现

        2.1、跳表节点

        2.2、跳表框架

        2.3、 查询

        2.4、 查找前置节点

        2.5、添加节点

        2.6、删除节点

3、跳表的性能分析


1、跳表引入

        1.1、背景

        跳表(Skip List)由美国计算机科学家威廉·普(William Pugh)于1989年提出,目的是解决有序链表查询效率低的问题。传统链表查询时间复杂度为O(n),而跳表通过引入多层索引结构,将查询、插入和删除操作的时间复杂度优化至O(log n),同时保持了较高的空间效率。普的论文《Skip Lists: A Probabilistic Alternative to Balanced Trees》奠定了跳表在数据结构领域的地位,成为平衡树轻量级替代方案


        1.2、跳表的基本原理

        跳表的核心思想是通过概率性构建多层索引加速查找。每一层都是有序链表,底层包含所有元素,上层逐步稀疏。稀疏与稠密是通过设置概率不同有所差别。每一个跳表的分布都是随机生成的。查找时从最高层开始,若当前节点的下一个节点值小于目标值,则向右移动;否则向下移动到下一层继续搜索。插入和删除操作通过调整相邻节点的指针实现,并动态维护索引层数。


2、跳表模拟实现

        2.1、跳表节点

        _val存储每个节点存储的值,_nextV指向下一个节点。

struct SkiplistNode
{int _val;vector<SkiplistNode*> _nextV;SkiplistNode(int val, int level):_val(val), _nextV(level, nullptr){}
};

        2.2、跳表框架

        对于跳表类的私有成员变量,有三个,_head是跳表的头,这个节点不存储值。_maxlevel存储最高层高,_p是晋升概率,也就是层高加一的概率。后面会详细说。

class Skiplist
{typedef SkiplistNode Node;
public:Skiplist(){srand(time(0));_head = new Node(-1, 1);}private:Node* _head;size_t _maxLevel = 32;double _p = 0.5;
};

        2.3、 查询

        我们先来说查找,一会在介绍怎么添加节点、

        对于查找的过程来说,我们从头结点开始查找,如果下一个节点的值小于我们想要查找的target,我们就直接跳到下一个节点那。如果下一个节点的值大于我们想要查找的taget,我们就得下降层数。如果层数下降到-1(0层是最低层)也没有找到target值,就跳出循环返回false。

        我们拿一个跳表模拟一下查找的过程:

bool search(int target)
{Node* cur = _head;int level = _head->_nextV.size() - 1;while (level >= 0){if (cur->_nextV[level] && cur->_nextV[level]->_val < target){cur = cur->_nextV[level];}//        走到最后一个节点else if (cur->_nextV[level] == nullptr || cur->_nextV[level]->_val > target){--level;}else{return true;}}return false;
}

        2.4、 查找前置节点

        首先我们先新建一个前置节点,然后把他初始化为level层,其实就是让他的层数和跳表中最高节点的层数相等。我们把这个前置节点的存储的值都初始化为_head。因为如果我们要查找的某个值都比跳表中的所有值都小,那么他的前置节点就是head。

        在循环的过程中,每次调整level我们就记录一下前置节点:

        后序删除和添加节点的时候我们都得先找到前置节点。

vector<Node*> FindPrevNode(int num)
{Node* cur = _head;int level = _head->_nextV.size() - 1;vector<Node*> prevV(level + 1, _head);while (level >= 0){if (cur->_nextV[level] && cur->_nextV[level]->_val < num){cur = cur->_nextV[level];}else if (cur->_nextV[level] == nullptr || cur->_nextV[level]->_val >= num){prevV[level] = cur;--level;}}return prevV;
}

        2.5、添加节点

         再添加节点的操作中,因为我们要控制每个跳表节点的高度都是随机的,所以说我们得先说一下生成随机层高的函数:

        随机数生成部分:

  generator是静态的默认随机数引擎

       用当前系统时间作为种子(time_since_epoch().count()),确保每次程序运行时种子不同static关键字保证在整个程序运行期间只初始化一次

   distribution:静态的均匀实数分布,范围[0.0, 1.0)用于生成0到1之间的随机浮点数。

        p是晋升概率,也就是我们层数++的概率。

        节点层数至少为1。而大于1的节点层数,满足一个概率分布。

        节点层数恰好等于1的概率为1-p。

        节点层数大于等于2的概率为p,而节点层数恰好等于2的概率为p(1-p)。

        节点层数大于等于3的概率为p^2,而节点层数恰好等于3的概率为p^2*(1-p)。

        节点层数大于等于4的概率为p^3,而节点层数恰好等于4的概率为p^3*(1-p)。

int RandomLevel()
{static std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());static std::uniform_real_distribution<double> distribution(0.0, 1.0);size_t level = 1;while (distribution(generator) <= _p && level < _maxLevel){++level;}return level;
}

        接下来我们看添加节点操作。首先我们找到应该插入位置的前置节点,然后依次设置每一层的节点链接。

void add(int num)
{vector<Node*> prevV = FindPrevNode(num);int n = RandomLevel();Node* newnode = new Node(num, n);if (n > _head->_nextV.size()){_head->_nextV.resize(n, nullptr);prevV.resize(n, _head);}for (size_t i = 0;i < n;i++){newnode->_nextV[i] = prevV[i]->_nextV[i];prevV[i]->_nextV[i] = newnode;}
}

        2.6、删除节点

        最后需要注意我们得调整一下头结点的层数。

bool erase(int num)
{vector<Node*> prevV = FindPrevNode(num);if (prevV[0]->_nextV[0] == nullptr || prevV[0]->_nextV[0]->_val != num){//该节点不存在return false;}else{Node* del = prevV[0]->_nextV[0];for (size_t i = 0;i < del->_nextV.size();i++){prevV[i]->_nextV[i] = del->_nextV[i];}delete del;//如果删除了最高层节点,就把头结点层数降一下int i = _head->_nextV.size() - 1;while (i >= 0){if (_head->_nextV[i] == nullptr)--i;elsebreak;}_head->_nextV.resize(i+1);return true;}
}

 

3、跳表的性能分析

        时间复杂度查询、插入、删除均为O(log n),依赖随机层数分布。

        空间复杂度平均O(n),索引节点数量约为n/2 + n/4 +... ≈ n。

        时间复杂度都是由查询操作卡着,而查询操作其实是从上到下遍历一遍。跳表的高度通常为O(log n),其中n是节点数量。

        优势实现简单,无需复杂平衡操作;适合高并发场景(如Redis的有序集合)。

        跳表作为一种高效动态数据结构,兼具实用性与灵活性,是算法设计中的经典案例。

        好了,今天的内容就分享到这,我们下期再见! 

 

http://www.dtcms.com/wzjs/241007.html

相关文章:

  • 十堰h5响应式网站百度推广多少钱
  • 功能网站建设宁波网站建设
  • 广州网页设计公司排名一键优化免费下载
  • 专业做外贸的网站萧山seo
  • 找人做网站需要注意什么什么是网络整合营销
  • 做展板好的网站企业网站推广公司
  • wordpress百度地图沈阳seo顾问
  • 长沙网站开发的网站厦门关键词优化企业
  • 男人和女人做污的视频网站深圳网络营销推广招聘网
  • 帮客户做传销网站360网站推广费用
  • 给银行做网站aso优化是什么
  • 织梦做的网站首页打不开seo内部优化方式包括
  • 网站页面做互联网推广软件
  • 财务管理做的好的门户网站搜狐新闻手机网
  • 校园类网站模板网页设计制作
  • 市场营销策划案重庆优化seo
  • 中英文网站怎么做的厦门人才网招聘
  • 天河区住房和建设水务局官方网站软文之家
  • 学校 网站建设工作小组哈尔滨网络seo公司
  • 特色网站建设免费优化
  • 做最好的导航网站十大管理培训课程
  • 网站搭建合同房地产销售怎么找客户
  • 网站建设要程序员吗大数据培训
  • 威海做企业网站的公司企业网站管理系统
  • aspcms手机网站源码百度商家怎么入驻
  • 南京建设网站哪家好优化营商环境应当坚持什么原则
  • html5网站源码phpseo托管服务
  • 网站建设项目职责新闻式软文经典案例
  • php学完可以做网站互联网项目
  • 线上推广是做什么的淘宝seo搜索排名优化