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

眉山营销型网站建设seo关键词排名在线查询

眉山营销型网站建设,seo关键词排名在线查询,wordpress文章不显示作者,wordpress集成后台无法登录一、线段树 线段树又称"区间树”,在每个节点上保存一个区间,当然区间的划分采用折半的思想,叶子节点只保存一个值,也叫单元节点,所以最终的构造就是一个平衡的二叉树,拥有 CURD 的 O(lgN)的时间。 从…

一、线段树

线段树又称"区间树”,在每个节点上保存一个区间,当然区间的划分采用折半的思想,叶子节点只保存一个值,也叫单元节点,所以最终的构造就是一个平衡的二叉树,拥有 CURD 的 O(lgN)的时间。
image.png
从图中我们可以清楚的看到[0-10]被划分成线段的在树中的分布情况,针对区间[0-N],最多有 2N 个节点,由于是平衡二叉树的形式也可以像堆那样用数组来玩,不过更加耗费空间,为最多 4N 个节点,在针对 RMQ 的问题上,我们常常在每个节点上增加一些 sum,max,min 等变量来记录求得的累加值,当然你可以理解成动态规划的思想,由于拥有 logN 的时间,所以在 RMQ 问题上比数组更加优美。

二、代码

1、在节点中定义一些附加值,方便我们处理 RMQ 问题。

 #region 线段树的节点/// <summary>/// 线段树的节点/// </summary>public class Node{/// <summary>/// 区间左端点/// </summary>public int left;/// <summary>/// 区间右端点/// </summary>public int right;/// <summary>/// 左孩子/// </summary>public Node leftchild;/// <summary>/// 右孩子/// </summary>public Node rightchild;/// <summary>/// 节点的sum值/// </summary>public int Sum;/// <summary>/// 节点的Min值/// </summary>public int Min;/// <summary>/// 节点的Max值/// </summary>public int Max;}#endregion

2、构建(Build)
前面我也说了,构建有两种方法,数组的形式或者链的形式,各有特点,我就采用后者,时间为 O(N)。

  #region 根据数组构建“线段树"/// <summary>/// 根据数组构建“线段树"/// </summary>/// <param name="length"></param>public Node Build(int[] nums){this.nums = nums;return Build(nodeTree, 0, nums.Length - 1);}#endregion#region 根据数组构建“线段树"/// <summary>/// 根据数组构建“线段树"/// </summary>/// <param name="left"></param>/// <param name="right"></param>public Node Build(Node node, int left, int right){//说明已经到根了,当前当前节点的max,sum,min值(回溯时统计上一层节点区间的值)if (left == right){return new Node{left = left,right = right,Max = nums[left],Min = nums[left],Sum = nums[left]};}if (node == null)node = new Node();node.left = left;node.right = right;node.leftchild = Build(node.leftchild, left, (left + right) / 2);node.rightchild = Build(node.rightchild, (left + right) / 2 + 1, right);//统计左右子树的值(min,max,sum)node.Min = Math.Min(node.leftchild.Min, node.rightchild.Min);node.Max = Math.Max(node.leftchild.Max, node.rightchild.Max);node.Sum = node.leftchild.Sum + node.rightchild.Sum;return node;}#endregion

3、区间查询
在线段树中,区间查询还是有点小麻烦的,存在三种情况。
① 完全包含:也就是节点的线段范围完全在查询区间的范围内,这说明我们要么到了“单元节点",要么到了一个子区间,这种情况就是我找到了查询区间的某一个子区间,直接累积该区间值就可以了。
② 左交集: 这种情况我们需要到左子树去遍历。
③ 右交集: 这种情况我们需要到右子树去遍历。
比如说:我要查询 Sum[4-8]的值,最终会成为:Sum 总=Sum[4-4]+Sum[5-5]+Sum[6-8],时间为 log(N)。

 #region 区间查询/// <summary>/// 区间查询(分解)/// </summary>/// <returns></returns>public int Query(int left, int right){int sum = 0;Query(nodeTree, left, right, ref sum);return sum;}/// <summary>/// 区间查询/// </summary>/// <param name="left">查询左边界</param>/// <param name="right">查询右边界</param>/// <param name="node">查询的节点</param>/// <returns></returns>public void Query(Node node, int left, int right, ref int sum){//说明当前节点完全包含在查询范围内,两点:要么是单元节点,要么是子区间if (left <= node.left && right >= node.right){//获取当前节点的sum值sum += node.Sum;return;}else{//如果当前的left和right 和node的left和right无交集,此时可返回if (node.left > right || node.right < left)return;//找到中间线var middle = (node.left + node.right) / 2;//左孩子有交集if (left <= middle){Query(node.leftchild, left, right, ref sum);}//右孩子有交集if (right >= middle){Query(node.rightchild, left, right, ref sum);}}}#endregion

4、更新操作
这个操作跟树状数组中的更新操作一样,当递归的找到待修改的节点后,改完其值然后在当前节点一路回溯,并且在回溯的过程中一路修改父节点的附加值直到根节点,至此我们的操作就完成了,复杂度同样为 logN。

 #region 更新操作/// <summary>/// 更新操作/// </summary>/// <param name="index"></param>/// <param name="key"></param>public void Update(int index, int key){Update(nodeTree, index, key);}/// <summary>/// 更新操作/// </summary>/// <param name="index"></param>/// <param name="key"></param>public void Update(Node node, int index, int key){if (node == null)return;//取中间值var middle = (node.left + node.right) / 2;//遍历左子树if (index >= node.left && index <= middle)Update(node.leftchild, index, key);//遍历右子树if (index <= node.right && index >= middle + 1)Update(node.rightchild, index, key);//在回溯的路上一路更改,复杂度为lgNif (index >= node.left && index <= node.right){//说明找到了节点if (node.left == node.right){nums[index] = key;node.Sum = node.Max = node.Min = key;}else{//回溯时统计左右子树的值(min,max,sum)node.Min = Math.Min(node.leftchild.Min, node.rightchild.Min);node.Max = Math.Max(node.leftchild.Max, node.rightchild.Max);node.Sum = node.leftchild.Sum + node.rightchild.Sum;}}}#endregion

最后我们做个例子,在 2000000 的数组空间中,寻找 200-3000 区间段的 sum 值,看看他的表现如何。

 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.Threading;using System.IO;namespace ConsoleApplication2{public class Program{public static void Main(){int[] nums = new int[200 * 10000];for (int i = 0; i < 10000 * 200; i++){nums[i] = i;}Tree tree = new Tree();//将当前数组构建成 “线段树”tree.Build(nums);var watch = Stopwatch.StartNew();var sum = tree.Query(200, 3000);watch.Stop();Console.WriteLine("耗费时间:{0}ms,  当前数组有:{1}个数字, 求出Sum=:{2}", watch.ElapsedMilliseconds, nums.Length, sum);Console.Read();}}public class Tree{#region 线段树的节点/// <summary>/// 线段树的节点/// </summary>public class Node{/// <summary>/// 区间左端点/// </summary>public int left;/// <summary>/// 区间右端点/// </summary>public int right;/// <summary>/// 左孩子/// </summary>public Node leftchild;/// <summary>/// 右孩子/// </summary>public Node rightchild;/// <summary>/// 节点的sum值/// </summary>public int Sum;/// <summary>/// 节点的Min值/// </summary>public int Min;/// <summary>/// 节点的Max值/// </summary>public int Max;}#endregionNode nodeTree = new Node();int[] nums;#region 根据数组构建“线段树"/// <summary>/// 根据数组构建“线段树"/// </summary>/// <param name="length"></param>public Node Build(int[] nums){this.nums = nums;return Build(nodeTree, 0, nums.Length - 1);}#endregion#region 根据数组构建“线段树"/// <summary>/// 根据数组构建“线段树"/// </summary>/// <param name="left"></param>/// <param name="right"></param>public Node Build(Node node, int left, int right){//说明已经到根了,当前当前节点的max,sum,min值(回溯时统计上一层节点区间的值)if (left == right){return new Node{left = left,right = right,Max = nums[left],Min = nums[left],Sum = nums[left]};}if (node == null)node = new Node();node.left = left;node.right = right;node.leftchild = Build(node.leftchild, left, (left + right) / 2);node.rightchild = Build(node.rightchild, (left + right) / 2 + 1, right);//统计左右子树的值(min,max,sum)node.Min = Math.Min(node.leftchild.Min, node.rightchild.Min);node.Max = Math.Max(node.leftchild.Max, node.rightchild.Max);node.Sum = node.leftchild.Sum + node.rightchild.Sum;return node;}#endregion#region 区间查询/// <summary>/// 区间查询(分解)/// </summary>/// <returns></returns>public int Query(int left, int right){int sum = 0;Query(nodeTree, left, right, ref sum);return sum;}/// <summary>/// 区间查询/// </summary>/// <param name="left">查询左边界</param>/// <param name="right">查询右边界</param>/// <param name="node">查询的节点</param>/// <returns></returns>public void Query(Node node, int left, int right, ref int sum){//说明当前节点完全包含在查询范围内,两点:要么是单元节点,要么是子区间if (left <= node.left && right >= node.right){//获取当前节点的sum值sum += node.Sum;return;}else{//如果当前的left和right 和node的left和right无交集,此时可返回if (node.left > right || node.right < left)return;//找到中间线var middle = (node.left + node.right) / 2;//左孩子有交集if (left <= middle){Query(node.leftchild, left, right, ref sum);}//右孩子有交集if (right >= middle){Query(node.rightchild, left, right, ref sum);}}}#endregion#region 更新操作/// <summary>/// 更新操作/// </summary>/// <param name="index"></param>/// <param name="key"></param>public void Update(int index, int key){Update(nodeTree, index, key);}/// <summary>/// 更新操作/// </summary>/// <param name="index"></param>/// <param name="key"></param>public void Update(Node node, int index, int key){if (node == null)return;//取中间值var middle = (node.left + node.right) / 2;//遍历左子树if (index >= node.left && index <= middle)Update(node.leftchild, index, key);//遍历右子树if (index <= node.right && index >= middle + 1)Update(node.rightchild, index, key);//在回溯的路上一路更改,复杂度为lgNif (index >= node.left && index <= node.right){//说明找到了节点if (node.left == node.right){nums[index] = key;node.Sum = node.Max = node.Min = key;}else{//回溯时统计左右子树的值(min,max,sum)node.Min = Math.Min(node.leftchild.Min, node.rightchild.Min);node.Max = Math.Max(node.leftchild.Max, node.rightchild.Max);node.Sum = node.leftchild.Sum + node.rightchild.Sum;}}}#endregion}}

image.png

http://www.dt0577.cn/news/48089.html

相关文章:

  • 哪个网站推荐做挖机事的广东宣布即时优化调整
  • 网站的 营销渠道的建设品牌策划方案ppt
  • 我们一起做网站如何免费找精准客户
  • 为什么要做网站优化合肥疫情最新消息
  • 上海网站营销怎么样东莞seo整站优化火速
  • 河南专业做网站保定seo网络推广
  • 长沙新媒体公司排名win7系统优化软件
  • 产品网站设计理念网站流量排行
  • wordpress 天津机房保定seo排名外包
  • 网站建设湖南南昌网站seo外包服务
  • 做网站图片要求天津优化网络公司的建议
  • 做外贸翻译用那个网站营销策略分析包括哪些内容
  • 做虚拟币网站需要什么手续怎么开网店新手入门
  • 动态网站建设 作业如何搭建一个网站平台
  • 网页设计简单教程茶叶seo网站推广与优化方案
  • 网站后台做的超链接打不开网络推广公司排名
  • 能自己做网站接业务吗爱站网站
  • 八年级学生做的简易网站网站联盟推广
  • 做网站买什么服务器 便宜口碑营销成功案例简短
  • 网站恢复爱站官网
  • 网站开发交流平台推荐就业的培训机构
  • 公司网站如何做的美丽学大教育培训机构怎么样
  • wordpress公众号上海seo怎么优化
  • 上海建筑电工证查询网站优化营商环境条例心得体会
  • 公司网站代码关键词搜索量查询
  • 光谷网站建设百度排行榜前十名
  • 建网站公建网站公司湖南靠谱seo优化公司
  • 怎么看网站是不是php语言做的seo营销服务
  • 收到短信说备案被退回但工信部网站上正常啊重庆seo优化推广
  • 各省网站备案条件百度问答库