开发成长之路(15)-- 数据结构:编程基石

Posted 看,未来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开发成长之路(15)-- 数据结构:编程基石相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

前言

在写STL的时候,我就意识到了缺少了一篇数据结构。
提到数据结构,很多学生可能会想到学校里上的数据结构的课,教的那些数组、链表、栈、队列、树、图等

但是真实的数据结构显然不止这么点,开发中也一般用不到这些数据结构。
所以数据结构我将分两部分来写,一部分写学校中教的数据结构,一部分写学校中不教的数据结构。


系列教程一览

开发成长之路(1)-- C语言从入门到开发(入门篇一)
开发成长之路(2)-- C语言从入门到开发(函数与定制输入输出控制函数)
开发成长之路(3)-- C语言从入门到开发(讲明白指针和引用,链表很难吗?)
开发成长之路(4)-- C语言从入门到开发(距离开发,还差这一篇)
开发成长之路(5)-- C语言从入门到开发(仿ATM机项目,我写的第一个项目)
开发成长之路(6)-- C++从入门到开发(C++入门不难)
开发成长之路(6)-- C++从入门到开发(C++知名库:STL入门·容器(一))
开发成长之路(7)-- C++从入门到开发(C++知名库:STL入门·容器(二))
开发成长之路(8)-- C++从入门到开发(C++知名库:STL入门·容器(三))
开发成长之路(9)-- C++从入门到开发(C++知名库:STL入门·空间配置器)
开发成长之路(10)-- C++从入门到开发(C++知名库:STL入门·算法)
开发成长之路(11)-- STL常用函数大集合
开发成长之路(12)-- Linux网络服务端编程(通识篇之熟悉操作环境)
开发成长之路(13)-- Linux网络服务端编程(通识篇)
开发成长之路(14)-- 小项目:视频点播器服务端(放码过来)
开发成长之路(14)-- 设计模式:写代码的艺术


“看,未来”的个人简介

朋友们大家好,我是“看,未来”,最近跟CSDN头部大佬们学了这一招,听说挺受用的,我也来试试。

本系列主要面向想要走开发路线,又不知从何学起的大学生。
我本人也是在大一的时候就去参加了培训,后来又自学了一段时间,在这期间,我觉得更重要的是跟行业内的前辈们请教,这比培训来的实在多了。

如果对学习有困惑的小伙伴可以私信我,知无不言,言无不尽,欢迎来聊。


指针&引用

指针和引用在数据结构中占的位置还是很高的。
所以对指针和引用不了解的小伙伴,我发现这个系列已经讲过了指针和引用,在第三篇,所以就不再多言。


数组

所谓数组,就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。数组是在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来的一种形式。这些按序排列的同类数据元素的集合称为数组。

在这里插入图片描述

关于数组的详尽解释可以移步:为实习准备的数据结构(1)-- 详尽数组篇


链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

链表有很多种不同的类型:单向链表,双向链表以及循环链表。

关于链表的实现代码可以移步:为实习准备的数据结构(2)-- 详尽链表篇


栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

在这里插入图片描述

关于栈的众多应用场景,例如:单调栈、汉诺塔、波兰式等应用场景,可以移步:
为实习准备的数据结构(3)-- 详解 栈


二叉树

树是我们计算机中非常重要的一种数据结构,同时使用树这种数据结构,可以描述现实生活中的很多事物,例如家
谱、单位的组织架构、等等。
树是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就
是说它是根朝上,而叶朝下的。

喏,看:
在这里插入图片描述

 1.每个结点有零个或多个子结点;
 2.没有父结点的结点为根结点;
 3.每一个非根结点只有一个父结点;
 4.每个结点及其后代结点整体上可以看做是一棵树,称为当前结点的父结点的一个子树;

二叉树是树里面比较基础的一环,入门树的话从二叉树开始即可。

详情请移步:为实习准备的数据结构(4)-- 二叉树


平衡二叉树

二叉搜索树一定程度上可以提高搜索效率,但是当原序列有序,例如序列A = {1,2,3,4,5,6},构造二叉搜索树如图。依据此序列构造的二叉搜索树为右斜树,同时二叉树退化成单链表,搜索效率降低为O(n)。

如下图:
在这里插入图片描述

在此二叉搜索树中查找元素6需要查找6次。二叉搜索树的查找效率取决于树的高度,因此保持树的高度最小,即可保证树的查找效率。同样的序列A,改为下图方式存储,查找元素6时只需比较3次,查找效率提升一倍。

在这里插入图片描述

可以看出当节点数目一定,保持树的左右两端保持平衡,树的查找效率最高。这种左右子树的高度相差不超过1的树为平衡二叉树。

平衡二叉树是入门高级树的跳板,转此:为实习准备的数据结构(5)-- 图解AVL树(平衡二叉搜索树)


红黑树

红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构。
红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但 对之进行平衡的代价较低, 其平均统计性能要强于 AVL 。
由于每一棵红黑树都是一颗二叉排序树,因此,在对红黑树进行查找时,可以采用运用于普通二叉排序树上的查找算法,在查找过程中不需要颜色信息。

红黑树是每个结点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 结点是红色或黑色。
性质2. 根结点是黑色。
性质3. 所有叶子都是黑色。(叶子是NULL结点)(这个性质我也不知道有什么用,最好配上上面的图看,不然会晕)
性质4. 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
性质5. 从任一节结点到每个叶子的所有路径都包含相同数目的黑色结点

这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。这个在高度上的理论上限允许红黑树在最坏情况下都是高效的。
是性质4导致路径上不能有两个连续的红色结点确保了这个结果。最短的可能路径都是黑色结点,最长的可能路径有交替的红色和黑色结点。因为根据性质5所有最长的路径都有相同数目的黑色结点,这就表明了没有路径能多于任何其他路径的两倍长。

关于红黑树的详解:为实习准备的数据结构(8)-- 倾心图解红黑树


跳表

能放在这一篇里面的数据结构都不简单。
跳表为什么重要,听都没听过啊?!!知道redis吗?

跳表(skip list) 对应的是平衡树(AVL Tree),是一种 插入/删除/搜索 都是 O(log n) 的数据结构。它最大的优势是原理简单、容易实现、方便扩展、效率更高。因此在一些热门的项目里用来替代平衡树,如 redis, leveldb 等。

跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。

链表会写不?

在这里插入图片描述

上面这张图看着有感觉吗?我第一眼看到那个图,大概就明白了,同时觉得,秀啊!!!
还能这么玩。

一个节点要不要被索引,建几层的索引,都在节点插入时由抛硬币决定。当然,虽然索引的节点、索引的层数是随机的,为了保证搜索的效率,要大致保证每层的节点数目与上节的结构相当(差不多对半开)。

了解更多跳表的信息:为实习准备的数据结构(9)-- 跳表


哈希散列表

久等了吧,哈希表的大名应该没有多少人不知道吧?!!!

哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

哈希表hashtable(key,value)
就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射,
pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。)
而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。

小故事看懂哈希表:为实习准备的数据结构(10)-- 哈希散列表


图论算法

在这里插入图片描述

是吧,看脑子好不好使,就给他看图论算法。

不多说啊,直接上干货:为实习准备的数据结构(11)-- 图论算法 集锦


前缀树

这个可能就更陌生了吧,我本来也挺陌生的,但是了解之后发现应用场景还不少。

直接说可能不太理解,我直接来张图:
在这里插入图片描述

晓得了吧,一种特殊的N叉树。用于检索字符串数据集中的键。

了解更多关于前缀树的知识:为实习准备的数据结构(13)-- 前缀树(字典树、Trie)


就先盘点到这儿啦,回头这些数据结构还要再手写一遍才好。

以上是关于开发成长之路(15)-- 数据结构:编程基石的主要内容,如果未能解决你的问题,请参考以下文章

从0到1Flink的成长之路(十七)-高级特性(Flink四大基石)

移动开发者的成长之路?

开发成长之路(13)-- Linux网络服务端编程(通识篇)

开发成长之路(13)-- Linux网络服务端编程(通识篇)

开发成长之路(11)-- STL常用函数大集合

开发成长之路(11)-- STL常用函数大集合