文章目录
- 0 前言
- 1 基本概念
- 1.1 什么是数据结构?
- 1.2 逻辑结构与物理结构
- 2 基本数据结构介绍
- 2.1 数组
- 2.2 栈
- 2.3 队列
- 2.4 链表
- (1)单链表
- (2)双向链表
- 2.5 树
- (1)二叉树
0 前言
由于疫情的原因数据结构与算法这门很重要的课是以网上授课的形式进行教学的,自己没好好听。最近又想刷算法题,所以趁着寒假的时间从头再把数据结构与算法学一遍,并通过写博客的形式记录下学习笔记。这让我明白了出来混,迟早是要还的。
- 本系列文章是
先讲解完数据结构
后再讲解一些基本算法。 - 先讲解原理,然后再用代码实现出来(以Java语言为例)
- 本系列的一些基本概念有借鉴于《大话数据结构》、《漫画算法-小灰的算法之旅》
- 有错误、疑问或不懂的地方欢迎评论指出。
1 基本概念
1.1 什么是数据结构?
- 数据:我们电脑上存储的东西都是数据。图片是图像数据,歌曲是声音数据,而我这篇文章主要就是由文字数据构成。我们编程语言中用int、double、char定义的变量都是数据。
- 数据元素:是组成数据的、有一定意义的基本单位,在计算机中通常作为整体处理。比如在人类中,数据元素是指一个人 。
- 结构:简单的理解就是关系。比如分子结构,就是说组成分子的原子之间的排列方式。严格点说,结构是指各个组成部分间相互搭配和排列的方式 。
经过以上几个名词的解释,我们可以得出结论,数据结构是指相互之间存在着特定关系的的数据元素的集合。
1.2 逻辑结构与物理结构
类似于逻辑地址与物理地址。
(1)逻辑结构:是指数据元素之间的相互关系,与他们在计算机中存储的位置无关。
逻辑结构分为以下四种:
①集合结构,元素间无关系。类似于数学中集合的概念。
②线性结构,元素间一对一。
③树形结构,元素间一对多。
④图形结构,元素间多对多。
(2)物理结构:指数据元素在计算机磁盘中存储的方式。通常有顺序存储、链式存储、索引存储和哈希存储。
2 基本数据结构介绍
2.1 数组
数组(array),线性数据结构,在内存中顺序存储。 特点:高效的访问,低效的插入和删除。
1)插入操作
演示将绿色插在第二个位置
确保在定义数组时尾部留有额外的空间或将数组进行扩容操作。
为了将第二个位置腾出空间,所以第二个位置后面的元素都要向后移动一位。
将绿色元素添加到空白处
2)删除操作
其实跟插入操作是相反的过程。倒着看插入操作,先删除绿色元素,再将绿色元素后面的元素都向前移动一位。
3)读取操作
由于数组是顺序存储的,所以访问数组时直接通过下标访问即可。
2.2 栈
栈(stack),线性数据结构,元素只能先进后出(First In Last Out,简称FILO)。最早进入的元素存放的位置叫作栈底(bottom),最后进入的元素存放的位置叫作栈顶(top)。
关于栈的操作有入栈(push)、出栈(pop)和遍历栈。
2.3 队列
队列(queue),线性结构,可以理解成平常我们排队打饭,先来的人先打饭,后来的后打。队列的特性是:**先进先出,后进后出。**基本操作就是入队和出队。
**补充(循环队列):**由于队列既可以顺序存储又可以链式存储,当顺序存储时我们可以使用循环对列,来提高队列空间的使用效率。下面用动态图来演示下基本过程。
循环对列需要一个头指针front和一个尾指针tail来判断队列的状态。头指针始终指向队首元素,尾指针始终指向队尾元素的后一个位置, 并且尾指针指向的位置不存储元素,所以队列满时,其中的元素个数为capacity - 1。 当front == tail 时,说明队列为空;当front ==(tail + 1)% capacity时,队列满。(**注:**capacity指顺序存储时队列的总容量)
2.4 链表
链表在计算机中的存储方式为随机存储,不像数组是顺序存储。通过下面这张图可以认识下两种存储方式的不同。
链表也包括好几种,单链表、单向循环链表、双链表和双向循环链表。这里只介绍两种常用的链表。
(1)单链表
链表是由一个个结点所构成,先介绍单链表的一个结点。
单链表基本结构
基本操作有:插入操作、删除操作、更新操作和查找操作。
插入结点操作:
删除操作
(2)双向链表
双向链表的结点比单链表的结点多一个前驱指针,一个结点有两个指针域。
2.5 树
树和图都是非线性数据结构,是由n(n>=0)个节点构成的有限集。n=0时称为空树。n>0时,有限集的元素构成一个具有层次感的数据结构。
基本概念:
- 根节点:树的第一层的节点为根节点,根节点最多只有一个。
- 叶子结点:无子节点的节点。
- 父节点:有子节点的节点,如图中节点2为节点4和节点5的父节点。
- 子节点:图中节点7、8为节点4的子节点,4、5又为节点2的子节点。
- 树的高度(深度):从根开始定义起,根为第一层 , 根的孩子为第二层。根节点到离它最远的叶子节点为树的高度。图中为4
- 节点的度:一个节点拥有 的子节点的个数,如节点4的度为2
- 兄弟节点:如同一个父节点的节点彼此间为兄弟节点,如2与3、4与5、7与8
(1)二叉树
二叉树或者为空集,或者由一个根节点和两棵互不相交的、分别称为左子树和右子树的二叉树组成。从定义可以看出一棵二叉树:
- 二叉树是有序树,区分左子树与右子树,不可以随意交换子树位置。
- 一个节点的子树数量取值范围为0,1,2。0代表该节点是叶子节点,1代表该节点只有左子树或只有右子树,2代表该节点有左右子树。
根据定义,一棵二叉树有5中基本形态:
满二叉树: 满二叉树的两个条件: ①一个二叉树的所有非叶子节点都存在左右孩子 ②所有的叶子节点都在同一层。
简单点说,满二叉树的每一个分支都是满的。
**完全二叉树:**在一棵二叉树中,只有最下两层的度可以小于2,并且最下一层的叶子节点集中出现在靠左的若干位置上。
**二叉排序(查找)树:**它或者是一棵空树,或者是具有下列性质的二叉树 。
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结构的值
- 若它的右子树不空 ,则右子树上所有结点的值均大于宫的根结点的值
- 它的左、右子树也分别为二叉排序树。
下图就是一个二叉排序树
**二叉树的遍历:**二叉树的遍历分为前序遍历、中序遍历和后序遍历。
前序遍历,输出顺序:根节点、左子树、右子树
中序遍历,输出顺序:左子树、根节点、右子树
后序遍历,输出顺序:左子树、右子树、根节点
可以得知遍历顺序的不同主要是由于根节点遍历时的顺序的不同。
举例上图二叉树的三种遍历方式:前序遍历:1,2,4,5,3,6 中序遍历:4,2,5,1,3,6 后序遍历:4,5,2,6,3,1
二叉树的性质:
性质一:在二叉树的第i层上至多有2^(i-1)个节点(i>=1)
性质二:深度为k的二叉树至多有2^k-1个节点
性质三:对任何一棵二叉树T,如果终端节点数为n0,度为2的节点数为n2 ,那么 n0 = n2 +1
性质四: 具有n个节点的完全二叉树的高度为至少为log2(n+1)
性质五:如果对一棵有n个节点的完全二叉树的节点按层序编号(从第一层开始到最下一层,每一层从左到右编号),对任一节点i有: 1. 如果i=1 ,则节点为根节点,没有双亲。
2. 如果2 * i > n ,则节点i没有左孩子 ;否则其左孩子节点为2i . (n为节点总数)
3. 如果2 * i+1>n ,则节点i没有右孩子;否则其右孩子节点为21+1
: 具有n个节点的完全二叉树的高度为至少为log2(n+1)
性质五:如果对一棵有n个节点的完全二叉树的节点按层序编号(从第一层开始到最下一层,每一层从左到右编号),对任一节点i有: 1. 如果i=1 ,则节点为根节点,没有双亲。
2. 如果2 * i > n ,则节点i没有左孩子 ;否则其左孩子节点为2i . (n为节点总数)
3. 如果2 * i+1>n ,则节点i没有右孩子;否则其右孩子节点为21+1