开篇-学习算法与数据结构有什用?
序言
学习数据结构的必要性
1.首先我们做一个简单的测试,创建一个十万次的for循环,循环过程中判断当前i值是否在list集合中,如果不在,就将其加入到集合中去。通过结果我们可以看到一个如此简单的逻辑耗时竟然高达95634毫秒,将近100秒的时间。
Stopwatch sw = new Stopwatch(); sw.Start(); List<string> list = new List<string>(); for (int i = 0; i < 100000; i++) { if (!list.Contains(i.ToString())) { list.Add(i.ToString()); } } Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadKey();
2.我们将List集合改为HashSet,将循环次数修改为循环一百万次,发现结果不过是1195毫秒,性能得到了显著地提升。
Stopwatch sw = new Stopwatch(); sw.Start(); HashSet<string> hashSet = new HashSet<string>(); for (int i = 0; i < 1000000; i++) { if (!hashSet.Contains(i.ToString()))//如果当前i值不在hashSet集合中 { hashSet.Add(i.ToString());//将当前i值添加到该集合中去 } } Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadKey();
3.我们将List集合改为Dictionary<string,string>,将循环次数修改为循环一百万次,发现结果不过是1753毫秒,性能同样得到了显著地提升。
Stopwatch sw = new Stopwatch(); sw.Start(); Dictionary<string,string> dic =new Dictionary<string, string>(); for (int i = 0; i < 1000000; i++) { if (!dic.ContainsKey(i.ToString()))//如果当前i值不在字典中 { dic.Add(i.ToString(),i.ToString());//将当前i值添加到该字典中去 } } Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadKey();
4.同样的逻辑采用不同的方法,性能差异为何如此之大,这就不得不从底层封装的数据结构说起了。
学习数据结构有什么用?
学了顺序表和链表,你就知道,在查询操作更多的程序中,你应该用顺序表;而修改操作更多的程序中,你要使用链表;
而单向链表不方便怎么办,每次都从头到尾好麻烦啊,怎么办?你这时就会想到双向链表or循环链表。
学了栈之后,你就知道,很多涉及后入先出的问题,例如函数递归就是个栈模型、Android的屏幕跳转就用到栈,很多类似的东西,你就会第一时间想到:我会用这东西来去写算法实现这个功能。
学了队列之后,你就知道,对于先入先出要排队的问题,你就要用到队列,例如多个网络下载任务,我该怎么去调度它们去获得网络资源呢?
再例如操作系统的进程(or线程)调度,我该怎么去分配资源(像CPU)给多个任务呢?肯定不能全部一起拥有的,资源只有一个,那就要排队!那么怎么排队呢?用普通的队列?但是对于那些优先级高的线程怎么办?
那也太共产主义了吧,这时,你就会想到了优先队列,优先队列怎么实现?
用堆,然后你就有疑问了,堆是啥玩意?自己查吧,敲累了。
总之好好学数据结构就对了。我觉得数据结构就相当于:我塞牙了,那么就要用到牙签这“数据结构”,当然你用指甲也行,只不过“性能”没那么好;我要拧螺母,肯定用扳手这个“数据结构”,当然你用钳子也行,只不过也没那么好用。
学习数据结构,就是为了了解以后在IT行业里搬砖需要用到什么工具,这些工具有什么利弊,应用于什么场景。
以后用的过程中,你会发现这些基础的“工具”也存在着一些缺陷,你不满足于此工具,此时,你就开始自己在这些数据结构的基础上加以改造,这就叫做自定义数据结构。
而且,你以后还会造出很多其他应用于实际场景的数据结构。。你用这些数据结构去造轮子,不知不觉,你成了又一个轮子哥。
hello-algo
逻辑结构可分为“线性”和“非线性”两大类。线性结构比较直观,指数据在逻辑关系上呈线性排列;非线性结构则相反,呈非线性排列。
- 线性数据结构:数组、链表、栈、队列、哈希表,元素之间是一对一的顺序关系。
- 非线性数据结构:树、堆、图、哈希表。
非线性数据结构可以进一步划分为树形结构和网状结构。
- 树形结构:树、堆、哈希表,元素之间是一对多的关系。
- 网状结构:图,元素之间是多对多的关系。
值得说明的是,所有数据结构都是基于数组、链表或二者的组合实现的。例如,栈和队列既可以使用数组实现,也可以使用链表实现;而哈希表的实现可能同时包含数组和链表。
- 基于数组可实现:栈、队列、哈希表、树、堆、图、矩阵、张量(维度 ≥3 的数组)等。
- 基于链表可实现:栈、队列、哈希表、树、堆、图等。
链表在初始化后,仍可以在程序运行过程中对其长度进行调整,因此也称“动态数据结构”。数组在初始化后长度不可变,因此也称“静态数据结构”。值得注意的是,数组可通过重新分配内存实现长度变化,从而具备一定的“动态性”。
总结
数据的逻辑结构一 般有 4 类:集合、线性结构、树形结构和图状结构。集合中的数据元素除了属于 “同一集合这一关系外”,没有其它任何的关系。
- 线性结构中的数据元素之间存 在一对一的关系;
- 树形结构中的数据元素之间存在一对多的关系;
- 图状结构的数 据元素之间存在多对多的关系。
- 数据的逻辑结构分为两种类型:线性结构和非线性结构。树形结构和图状结构属于非线性结构。
- 数据的物理结构又叫存储结构, 是数据元素在计算机中的存储方式。存储结构有两类,顺序存储结构和链式存储结构。
- 顺序存储结构是在计算机中把逻辑上相邻的数据元素存储在物理位置相邻的存储单元中。
- 链式存储结构是逻辑上相邻的数据元素不一定存储在物理位置相邻的存储单元中,数据元素之间的逻辑关系用引用表示。
算法是一种将有限计算资源发挥到极致的武器