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

青白江区城乡和建设局网站wordpress 文章多图

青白江区城乡和建设局网站,wordpress 文章多图,零基础网站建设教学培训班,wordpress 首页大图简介 数据结构的本质,只有两种结构,数组与链表。其它的都是它的衍生与组合算法的本质就是穷举。 数组 数组可以分为两大类,静态数组与动态数组。静态数组的本质是一段连续的内存,因为是连续的,所以我们可以采用偏移量的…

简介

数据结构的本质,只有两种结构,数组与链表。其它的都是它的衍生与组合算法的本质就是穷举

数组

数组可以分为两大类,静态数组动态数组。静态数组的本质是一段连续的内存,因为是连续的,所以我们可以采用偏移量的方式来对元素实现快速访问。而动态数组则是对静态数组的封装,使得更加方便操作元素。有了动态数组,后续的栈,哈希,队列都能更加优雅的实现。

静态数组

  1. 数组的超能力随机访问。只要任意一个索引,都能推测出元素的内存地址,而计算机的内存寻址能力为Log(1),所以数组的随机访问时间复杂度也同样为Log(1)

  2. 数组的局限性由于数组的大小是固定的,所以当数组满了,或者需要在中间插入/删除时。都需要移动元素,这时候时间复杂度就上升为Log(N)

动态数组

动态数组无法解决静态数组Log(N)的问题,它只是帮你隐藏了动态扩容与元素搬移的过程,以及更加易用的API。

数组随机访问的超能力源于数组连续的内存空间,而连续的内存空间就不可避免地面对元素搬移和扩缩容的问题

一个简单的动态数组

public class MyList<T>(){//真正存储数据的底层private T[] arr = new T[5];//记录元素的数量public int Count { get; private set; }/// <summary>/// 增/// </summary>/// <param name="item"></param>public void Add(T item){if (Count == arr.Length){//扩容Resize(Count * 2);}arr[Count] = item;Count++;}/// <summary>/// 删/// </summary>/// <param name="idx"></param>public void RemoveAt(int idx){if (Count == arr.Length / 4){//缩容Resize(arr.Length / 2);}Count--;for (int i = idx; i < Count; i++){arr[i] = arr[i + 1];}arr[Count] = default(T);}public void Remove(T item){var idx = FindIndex(item);RemoveAt(idx);}/// <summary>/// 改/// </summary>/// <param name="idx"></param>/// <param name="newItem"></param>public void Put(int idx,T newItem){arr[idx] = newItem;}/// <summary>/// 查/// </summary>/// <param name="item"></param>/// <returns></returns>public int FindIndex(T item){for(int i = 0; i < arr.Length; i++){if (item.Equals(arr[i]))return i;}return -1;}/// <summary>/// 扩容/缩容操作/// </summary>/// <param name="initCapacity"></param>private void Resize(int initCapacity){var newArray=new T[initCapacity];for(var i = 0; i < Count; i++){newArray[i] = arr[i];}arr = newArray;}}

数组的变种:环形数组

有人可能会问了?数组不是一段连续的内存吗?怎么可能是环形的?从物理角度出发,这确实不可能。但从逻辑角度出发,这是有可能的。其核心内容就是利用求模运算

        public static void Run(){var arr = new int[] { 1, 2, 3, 4, 5, 6 };var i = 0;while (arr.Length > 0){Console.WriteLine(arr[i]);//关键代码在此,当i遍历到末尾时,i+1与arr.Length去余数变成0//从逻辑上完成了闭环i = (i + 1) % arr.Length;if ((i % arr.Length) == 0){Console.WriteLine("完成了一次循环,i归零");Thread.Sleep(1000);}}}

环形数组的关键在于,它维护了两个指针 start 和 end,start 指向第一个有效元素的索引,end 指向最后一个有效元素的下一个位置索引环形数组解决了什么问题?数组在头部增删从O(N),优化为O(1)

链表

链表分为单链表双链表,单链表只有一个指针,指向next元素。双链表有两个指针,分别指向previous与next。除此之外并无其它区别。主要功能区别在于能否向前遍历。

为什么需要链表

前面说到,数组的本质是一段连续的内存,当元素移动/扩容时,需要one by one 移动,花销很大。那有没有一种能突破内存限制的数据结构呢?链表就应运而生。链表不需要连续内存,它们可以分配在天南海北,它们之间的联系靠next/prev链接,将零散的元素串成一个链式结构。

这么做有两个好处

  1. 提高内存利用率,分配在哪都可以。所以可以降低内存碎片

  2. 方便扩容与移动,只需要重新指向next/previous 即可实现增,删,改等操作,无需移动元素与扩容。

但万物皆有代价,因为链表的不连续性,所以无法利用快速随机访问来定位元素,只能一个一个的遍历来确定元素。因此链表的查询复杂度为Log(N)

一个简单的链表

public class MyLinkedList<T>
{public static void Run(){var linked = new MyLinkedList<string>();linked.AddLast("a");linked.AddLast("b");linked.AddLast("c");linked.AddLast("d");linked.Add(1, "bc");linked.Put(1, "aaaa");Console.WriteLine(linked.ToString()) ;}/// <summary>/// 虚拟头尾节点,有两个好处/// 1.无论链表是否为空, 两个虚拟节点都存在,避免很多边界值处理的情况。/// 2.如果要在尾部插入数据,如果不知道尾节点,那么需要复杂度退化成O(N),因为要从头开始遍历到尾部。/// </summary>private Node _head, _tail; public int Count { get; private set; }public MyLinkedList(){_tail = new Node();_head = new Node();_head.Next = _tail;_tail.Prev = _head;}public void AddLast(T item){var prev = _tail.Prev;var next = _tail;var node = new Node(item);node.Next = next;node.Prev = prev;prev.Next = node;next.Prev = node;Count++;}public void AddFirst(T item){var prev = _head;var next = _head.Next;var node=new Node(item);node.Prev= prev;node.Next= next;prev.Next= node;next.Prev = node;Count++;}public void Add(int idx,T item){var t = Get(idx);var next = t.Next;var prev = t;var node = new Node(item);node.Next = next;node.Prev = prev;prev.Next = node;next.Prev = node;}public void Remove(int idx){var t = Get(idx);var prev = t.Prev;var next = t.Next;prev.Next = next;next.Prev = next;t = null;Count--;}public void Put(int idx,T item){var t = Get(idx);t.Value= item;}private Node? Get(int idx){var node = _head.Next;//这里有个优化空间,可以通过idx在Count的哪个区间。从而决定从head还是从tail开始遍历for (int i = 0; i < idx; i++){node = node.Next;}return node;}public override string ToString(){var sb = new StringBuilder();var node = _head.Next;while (node != null && node.Value != null){sb.Append($"{node.Value}<->");node = node.Next;}sb.Append("null");return sb.ToString();}private class Node{public T? Value { get; set; }public Node Next { get; set; }public Node Prev { get; set; }public Node(){Value=default(T);}public Node(T value){Value = value;}}
}

链表的变种:跳表

在上面简单的例子中,查询的复杂度为O(N),插入的复杂度为O(1).主要消耗在查询操作,只能从头结点开始,逐个遍历到目标节点。所以我们优化的重点就在于优化查询。

上面的例子中,我们使用了虚拟头尾节点来空间换时间,提高插入效率。同样的,我们也可以采用这个思路来提高查询效率

跳表核心原理

index  0  1  2  3  4  5  6  7  8  9
node   a->b->c->d->e->f->g->h->i->j

此时此刻,你想拿到h的节点,你需要从0开始遍历直到7。这时候你就想,如果我能提前知道6的位置就好了,这样我就只需要Next就能快速得到h

调表就是如此

indexLevel   0-----------------------8-----10
indexLevel   0-----------4-----------8-----10
indexLevel   0-----2-----4-----6-----8-----10
indexLevel   0--1--2--3--4--5--6--7--8--9--10
nodeLevel    a->b->c->d->e->f->g->h->i->j->k

调表在原链表的基础上,增加了多层索引,每向上一层,索引减少一半,所以索引的高度是O(log N)

  1. 首先从最高层索引开始往下搜,索引7在[0,8]区间

  2. 从节点0开始,发现7在【4,8】,拿到节点4的地址

  3. 从节点4开始,发现7在【6,8】,拿到节点6的地址

  4. 从节点6开始,发现7在【6,7】,最终找到节点7

在搜索的过程中,会经过O(log N)层索引,所以时间复杂度为O(log N)

调表实现比较复杂,当新增与删除时,还需考虑索引的动态调整,需要保证尽可能的二分,否则时间复杂度又会退化为O(N)有点类似自平衡的二叉搜索数,不过相对来说比较简单。

文章转载自:叫我安不理

原文链接:重生之数据结构与算法----数组&链表 - 叫我安不理 - 博客园

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构


文章转载自:

http://34kCVP8B.zfcfk.cn
http://Tq8Cipfd.zfcfk.cn
http://vCS2Y7FZ.zfcfk.cn
http://Tc3nndUN.zfcfk.cn
http://2ZRcENzV.zfcfk.cn
http://MeeprLKR.zfcfk.cn
http://XY4NqK1G.zfcfk.cn
http://PnTUqOXq.zfcfk.cn
http://7N4wxoCB.zfcfk.cn
http://DzD8PQnI.zfcfk.cn
http://y9GsHO1l.zfcfk.cn
http://pE53dvwq.zfcfk.cn
http://A5VK8miy.zfcfk.cn
http://ryBW7emD.zfcfk.cn
http://gHRpEo4U.zfcfk.cn
http://uOfRgbJK.zfcfk.cn
http://YgGUFX22.zfcfk.cn
http://xWdZYGqW.zfcfk.cn
http://cc2hXEVe.zfcfk.cn
http://yyi0Ubix.zfcfk.cn
http://eWwZCGJ7.zfcfk.cn
http://fmKJLD5b.zfcfk.cn
http://D7Spn686.zfcfk.cn
http://ko9tvVLP.zfcfk.cn
http://RQx37NqP.zfcfk.cn
http://ulgGGQyJ.zfcfk.cn
http://kW6ynt6n.zfcfk.cn
http://BbUlxDLi.zfcfk.cn
http://wlfUDG7X.zfcfk.cn
http://nbV7ItnH.zfcfk.cn
http://www.dtcms.com/wzjs/744330.html

相关文章:

  • android 网站模板海尔网站建设推广
  • 网站组成元素十大接单推广平台
  • 网站运营和seo的区别为什么做可信网站
  • 中学生做的安全作业网站字节跳动公司简介
  • 自己做的网站给人攻击了怎么办通化县住房和城乡建设局网站
  • 网站建设到备案wordpress显示评论数
  • 个人兼职网站建设如何自学做网站
  • 成都网站制作机构美容北京公司网站建设
  • 广州做网站哪家强网站开发工资多少钱
  • 做网站的收益长清治做网站
  • 学做网站应该看那些书小程序定制开发深圳公司
  • 宜宾网站建设哪家好昆明网站建设博滇
  • 优化网站价格网站建设的岗位职责
  • 合肥电信网站备案城市文明建设网站
  • 花店网站建设构思黄江二手车东莞网站建设
  • 新泰建设局网站交互设计软件有哪些
  • 网站开发需要用到哪些资料当地的建设工程信息网
  • 学校网站管理系统 php58同城网络营销
  • 广州市手机网站建设品牌网站建设与实践
  • 淮北网站网站建设网站策划的基本过程
  • 永久网站建设免费微网站系统
  • 网站系统说明上海徽与章网站建设宗旨
  • 宁夏银川做网站的公司建立网站需要多少钱怎么样
  • 杭州网站设计公司有哪些明年做哪些网站能致富
  • 设计个网站需要怎么做win7怎么做网站域名绑定
  • 网站标题可以修改吗做网站需要会什么编程
  • 网站建设都有那些费用广告推广系统
  • 大气家具行业商城类公司网站织梦模板做网站公司哪家
  • 2003配置网站与2008的区别网站排名怎样做有效
  • 精美公司网站源码网站建设翻译插件