6.3数据结构
- 进程,和程序的区别
- 什么是栈和队列?区别和联系?
- 递归和非递归的优缺点
- 用自己的话描述图的深度广度搜索
- 什么是二叉树、满二叉树和完全二叉树
- 快排的主要步骤
- 栈和队列有哪些具体?循环队列有什么好处?
- 二叉树的几种遍历算法及其思想?怎样用遍历算法确定唯一的二叉树
- 哪些方法可生成最小生成树?
- 排序算法的种类
- 二叉树的遍历算法
第一章 绪论
-
谈一下学习数据结构的意义
研究非数值计算领域的程序设计问题
问题的操作对象
操作对象之间的关系
在操作对象上面施加的操作
用程序代码把现实世界的问题信息化
用计算机高效地处理这些信息而创造价值
算法+数据结构=程序
-
数据、数据元素、数据项
要根据实际业务需求确定
-
数据:对客观事物的符号描述 图像声音等
-
数据元素:数据的基本单位
( 学生的记录信息)
-
数据项:构成数据元素的不可分割的最小单位,一个数据元素可由若干个数据项组成 (学号、姓名、性别等)
-
数据对象:具有相同性质的数据元素的集合 (没强调关系)
-
数据结构:强调各个元素之间的关系
数据结构:某个特定门店的排队顾客信息和它们之间的关系
数据对象:全国所有门店的排队顾客信息
-
-
谈一下数据的逻辑结构和存储结构,数据结构的形式定义
逻辑结构:数据元素之间的相互逻辑关系
四种基本逻辑结构:
集合、线性结构、树形结构、图状结构 或网状结构
数据存储结构:
数据结构是一个二元组Data_Structures=(D,S)
eg:
GROUP=(P,R)
P={M,D1,D2,E11,E12,E13,E21,E23,E23}
R={<M,D1>,<M,D2>,<D1,E11>,<D1,E12>…<D2,E23>} -
谈一下算法的定义,以及它的5个特性
对特定问题求解步骤的一种描述,是指令的有限序列
输入:有0个或多个输入
输出:有一个或多个输出(处理结果)
确定性:每步定义都是确切、无歧义的
有穷性:算法应在执行有穷步后结束
有效性(可行性):每一步骤都能有效执行,并得到确定结果 -
谈一下算法描述方法+算法设计原则
自然语言、程序设计语言、类程序设计语言、流程图
正确性、可读性、健壮性、高效率与低存储量需求
第二章 线性表
-
谈一下线性表的特点
有且只有一个第一元素,有且只有一个“最后元素”,除了第一元素外,其他元素都有唯一的直接前驱,除最后一个元素外,其他元素都有唯一的直接后继
顺序存储的线性表,称为顺序表
特点:
逻辑上相邻的数据元素,其物理位置也相邻
利用物理位置上的关系反映元素的逻辑关系
-
顺序表的类型定义
#define MAXSIZE maxlen typedef int elemtype; typedef struct { elemtype v[Maxsize]; int len; }
-
谈一下什么是顺序存储,以及顺序存储的优缺点
顺序存储:在内存中开辟一段连续的存储空间,用一组连续的存储单元依次存放数据。特点是逻辑关系上相邻的两个元素在物理位置上也
优点:(1)随机存取元素容易实现,根据定位公式容易确定表中每个元素的存储位置,所以指定第i个结点很方便。(2)简单直观
缺点:(1)插入删除结点很困难(2)扩展不灵活,估计不到表的最大长度,就很难确定分配的空间 (3)分配空间过大时,容易造成浪费
-
顺序表上的基本运算
//1.求线性表的长度 void main() { sqlist *L; int lenth(sql *L); L = (sqlist *)malloc(sizeof(sqlist)); L->len = 0; printf("顺序表的长度为:%d\n",lenth(L)); } int lenth(sqlist *L) { int lenth; lenth=L->len; return(lenth) } //2.插入算法 /* 判断线性表的存储空间是否已满,若已满进行溢出处理 检查i是否超出所允许的范围(i<=i<=n+1),若超出,则进行"超出"处理 将线性表的第i个元素和它后面的元素均往后移动一个位置 将新的数据元素写入到下标为i-1的位置上 线性表的长度增加1 */ //3.删除算法 /* 判断i值是否超出所允许的范围(1<=i<=n),若是则进行“超出范围"处理 把第i个元素赋予给y 把第i个元素后的所有元素依次向前移动一个位置 线性表的长度减1 */ //4.查找算法 int search(sqlist *L,int x) { int i; for(i=0;i<L-len;i++) if(x==L->v[i]) break; if(i<L->len) return(i+1); else return(0) }
-
顺序表和线性链表的区别是什么?
顺序表中,所有数据元素是依次存放在一组连续的存储单元中,数据元素在线性表中的顺序可以确定它在存储单元中的位置,逻辑上相邻的两个数据元素其物理位置也相邻。
而线性表中,结点在存储器中的位置是任意的,结点之间的逻辑关系由结点中的指针来指示。
-
单链表类型定义
typedef struct node {elemtype data; struct node *next; }Lnode, *linklist;
-
谈一下循环链表、双向链表、双向循环链表的特点
循环链表是一种首位相接的链表,最后一个结点的指针域的值指向头结点
从表中任意结点出发均可以找到表中其他的结点。
双向链表中,每一个结点中有两个指针域,一个指向直接后继,另一个指向直接前驱,这种链表称为双向链表。
双向循环链表就是
第三章 栈和队列
-
谈一下栈的概念
栈只能在表的一端进行插入和删除操作的线性表,类似于死胡同,栈的特点实施后进先出,它的典型应用是十进制转化为二进制时,先出现的余数排在后面,后出现的余数排在前面,可以用一个栈来保存所有的余数。
允许插入删除操作的一端叫栈顶,不允许的一端叫栈底,通常设置top指针指示栈顶元素的当前位置(top是整型变量)
#define maxsize typedef struct { elemtype elem[maxsize]; int top; }sqstacktp;
-
谈一下栈的顺序存储结构和链式存储结构
顺序存储
栈的顺序存储结构叫做顺序栈,通常用一组地址连续的存储单元依次存放从栈底到栈顶的元素,同时设置指针top(整型变量)指示栈顶元素在数组中的位置
s.top=0表示空栈,s.top=maxsize表示栈满
顺序栈上的操作有:1.初始化(栈置空)操作 2.判断栈空3.进栈4.出栈5.求栈深操作6.读取栈顶元素
特点:结构简单但是必须预先为它分配空间,而且为了避免栈溢出,通常必须分配较大的空间
链式存储
链表尾部结点是栈底,头部结点是栈顶,由于只在链表的头部进行操作,所有没必要设置头结点;不会发生栈满,空间动态分配
应用:表达式求值
-
谈一下队列的基本概念及应用
队列是只允许在表的一端进行插入,在表的另一端进行删除的线性表(队尾进,队头出),特点是先进先出
顺序存储
队列的顺序存储结构(顺序队列)由一个存放数组的元素和指示队头和队尾的元素组成,入队-队尾指针+1,出队-队头指针+1,当两指针相等表示队空,但是会发生假溢出的现象,于是有了循环队列,约定队头指针指示的元素不用来存放元素
(sq.rear+1)%maxsize=sq.front
链式存储
链队列-实际是同时带有头指针和尾指针的单链表,虽然用头指针就可以唯一确定这个单链表,但是插入操作总是在队尾进行,如果没有尾指针,时间复杂度将从O(1)升到O(n)
应用
伴舞问题:男女排成一队,各出一个人配成舞伴
第五章 树
-
说一下树的概念
树是由n个结点组成的有限集合,当n=0时称为空树,否则在任一非空树中:必有一个特定的称为根的结点,剩下的结点又分成互不相交的集合,这些集合组成的每一个又都是树
-
树的基本术语
度(degree):终点拥有的子树的个数(与这个结点下方相连有几根线)
叶子(终端结点):度=0,就是没有孩子了
兄弟:同一个双亲的孩子(它们的父亲一样)
深度,高度:就是树的最大层次
森林:m颗互不相交的树的集合
-
树的基本操作有哪些?
初始化
求根函数
求双亲
求孩子结点
求右兄弟
创建树
插入子树
删除子树
遍历操作
-
谈一下二叉树的概率及特点
二叉树是结点的有限集合,要么这个集合是空的(空二叉树),要么只有根节点,要么由互不相交的左子树和右子树组成
特点:树中每个结点最多只能有两棵子树,二叉树的子树有左右结点之分,即使在只有一棵子树的情况下,也应该分清是左子树还是右子树
-
说一下满二叉树和完全二叉树的区别
一棵二叉树它的深度为k,当它的结点数刚好等于2k-1时,它就是满二叉树,如果它的结点数n<2k-1时,并且1-n对应的结点和满二叉树中对应的结点一样。
-
二叉树的存储
顺序存储
结点在向量中的相对位置表示结点之间的关系,这种存储只使用于完全二叉树,对于一般的二叉树,这样存储就很浪费空间
链式存储
二叉链表(左右指针域和数据域)和三叉链表(+指向双亲结点的指针域)
-
二叉树的遍历算法,一般树的表示方法有哪几种
先序、中序、后序
双亲表示法(data+parent)
这种存储结构利用每个结点除了根结点都有唯一的一个双亲,反复进行求双亲的操作,直到遇到无双亲的结点时就遇到了根。但是这样表示求结点的孩子时就要遍历整个向量。
孩子表示法
孩子链表:就是把每个结点的孩子排成一个单链表,有n个结点就有n个孩子链表(叶子的孩子链表为空表)。
带双亲的孩子链表:就是把双亲表示法和孩子链表结合起来。
孩子兄弟表示法
以二叉链表作为树的存储结构,data+fch+nsib;一个指向结点的第一个孩子结点,一个指向结点的下一个兄弟结点。
-
说一下如何将树转换成二叉树
1.加线:在兄弟之间加一连线
2.抹线:对每个结点,除了它的第一孩子,去除其与其他孩子的连线
3.旋转:顺时针旋转45°
-
说一下如何将二叉树转换成树
1.加线:如果p结点是双亲结点的左孩子,那将p的右孩子,右孩子的右孩子,一直找下去,都和双亲结点连接起来
2.抹线:抹掉原二叉树中双亲与右孩子之间的连线
3.调整:将结点按照层次排列,形成树结构
-
森林转化为二叉树
1.将每棵树分别转化成二叉树
2.将每棵树的根节点连起来
3.用第一棵树的根节点为二叉树的根,再以根节点为轴心,顺时针旋转
-
请简单谈一下哈夫曼树
**定义:**假设有n个权值w1到wn,试构成一棵有n个叶子结点的树,每个叶子结点带权值wi,则其中带权路径长度WPL最小的树就叫做哈夫曼树。
构造:(1)从二叉树的集合F中任选两棵根结点最小的树构建一棵二叉树并且置新的二叉树的权值为左右子树权值之和。
(2)删除这两棵树,同时将新的到的树加入到F中。
重复上述步骤
第六章 图
-
简要说一下图的概念
图分为有向图和无向图,数据元素之间的关系是任意的,每个数据元素都可以和任何其他元素相关
<x,y>表示从x到y的一条弧线
(x,y)表示x和y之间相连
-
图的基本术语
**度:**顶点v的度是与v相关联的边的数目
子图:v包含v1,那么v1是v2的子图
路径和回路:路径就是一个顶点到另一个顶点(有向)回路就是绕了一圈,第一个顶点和最后一个顶点相同。 简单路径/简单回路:就是除了头尾顶点外,不重复出现其余顶点
连通图、连通分量:
无向图中:
两个顶点间有路径就是连通的,如果图中任意两个顶点之间都有路径就叫做连通图,无向图中的最大连通子图就叫连通分量
如果是有向图,那就对应强连通图和强连通分量
生成树:不含回路的连通图叫树
权:图的每条边上的数字
网:带权的图
-
简单谈一下图的两种存储结构
邻接矩阵
一个二维数组来存储,无向图的邻接矩阵是对称的,当图的邻接矩阵是稀疏矩阵时,为确定边的条数,有大量的零元素要检查,所有很浪费时间
邻接表
对图中每个顶点建立一个单链表,每个结点由3个域组成:邻接点域指示与顶点邻接的点在图中的编号,链域指示下一条边或弧的结点,数据域存储边或弧相关的信息
-
用自己的话描述一下图的深度优先搜索和广度优先搜索
深度优先搜索
假设初始状态是图中,所有顶点都没被访问过,下面从任一顶点v0出发,访问与v0相邻但未被访问过的顶点v1,再访问和v1相邻但未被访问的顶点V2,重复上述过程,如果遇到所有的邻接点都被访问过的顶点时,就依次回退,直到所有顶点都被访问。
广度优先搜索
假设初始状态是图中所有顶点都没被访问过,从v0出发,访问v0的全部邻接点w1到wn,再依次访问W1到Wn的全部邻接点(已经访问过后的除外),依次类推,直到所有的顶点都被访问。
-
谈一下图的生成树概念
在图论中将无回路的连通图定义为树,任意两个顶点间存在一条不重复的路径,且是唯一的路径;
在连通图中:连通图的极小连通子图称为图的生成树
生成树包含图中所有的顶点,且没有回路,由DFS得到的是深度优先生成树,由BFS得到的是广度优先生成树。生成树不唯一
**非连通图的生成树:**每个连通分量中的顶点集合遍历时走过的边一起构成若干棵生成树,这些连通分量的生成树组成非连通图的生成森林
-
简单说一下最小生成树
最小生成树就是权重最小的生成树,它的提出最先是在n个城市建立网络通信,求最短路径,使得花费最小。还有就是旅行推销员问题。
最小生成树(Prim)算法:适用于局部最优解决全局最优问题
初始情况这棵树只有一个顶点,从一个顶点出发,找到和这个顶点相邻接的边中最小权值边(代价最小),继续寻找下一个顶点中与之相邻的最小权值边,以此类推,直到连上所有的顶点
最小生成树-克鲁斯卡尔(Kruskal)算法:
最小生成树的初始状态是n个顶点而没有边的非连通图T,从中选择权值最小的边,如果这条边依附的顶点在T中不同的连通分量上,则将此边加入T,否则舍去。选择下一条代价最小的边,以此类推,直到T中所有的点都在同一连通分量内为止。
-
简述拓扑排序的方法
在有向图中任选一个入度为0的顶点,并输出
从图中删除该顶点和以它为尾的弧,重复上述两步,直到全部顶点均已输出,或者当图中不存在度为0的顶点为止
第七章 查找
-
简单谈一下查找的分类
查找分为静态查找表和动态查找表和哈希表查找
静态查找表结构:顺序查找、有序表的折半查找、分块查找等
**动态查找表结构:**二叉排序树、平衡二叉树、B+树等
哈希查找:哈希查找和前两者的巨大区别是,前两种都是直接通过比较缩小反而,而哈希是直接通过关键字得到其对应元素的位置。
-
常用的哈希函数和处理冲突的方法
直接定址法
除留余数法
平方取中法
处理方法:
1.开发定址法(分为线性探测和二次探测,哈希函数探测)
2.拉链法(每个哈希地址作为一个指针m个,建立m个空链表,所得哈希地址一样就接在链表后面)
3.建立一个公共溢出区
-
哈希表的查找分析(效率)
查找过程中关键字比较的次数取决于产生冲突的多少。冲突少效率就高
产生冲突有以下3个因素:
(1)哈希函数是否均匀
(2)处理冲突的方法
(3)哈希表的装填因子(填入表中的元素个数除以哈希表的长度)
第八章排序
-
简单说一下排序的种类
排序分为插入排序(直接插入排序、希尔排序)
基本思想:每步将一个待排序的记录,按其关键字值的大小,插入到已经排好序的数据集合中适当的位置上,直到全部插入完为止
交换排序(冒泡排序和快速排序)
基本思想:交换排序是通过两两比较待排序记录的关键值,交换不满足顺序的那些偶对,直到全部满足为止
选择排序(简单选择排序、堆排序)
基本思想:选择排序是指每次从待排序的记录中选出关键字值最小(或最大)的记录,顺序放在已排序的有序序列中,直到全部排完
归并排序
合并是归并排序的核心
将两个有序子表合并成一个有序子表
在合并的基础上进行一趟排序
在一趟排序的基础上完成多趟排序。