数据结构与算法设计知识点精心整理Word文档格式.docx
- 文档编号:17840957
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:30
- 大小:946.09KB
数据结构与算法设计知识点精心整理Word文档格式.docx
《数据结构与算法设计知识点精心整理Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构与算法设计知识点精心整理Word文档格式.docx(30页珍藏版)》请在冰豆网上搜索。
设计算法时,通常还应考虑满足以下目标:
1.正确性,2.可读性,3.健壮性
4.高效率与低存储量需求
如何估算算法的时间复杂度?
算法=控制结构+原操作
(固有数据类型的操作)
算法的执行时间=原操作(i)的执行次数×
原操作(i)的执行时间
算法的执行时间与原操作执行次数之和成正比
算法的空间复杂度定义为:
S(n)=O(g(n))
表示随着问题规模n的增大,算法运行所需存储量的增长率与g(n)的增长率相同。
算法的存储量包括:
1.输入数据所占空间
2.程序本身所占空间
3.辅助变量所占空间
第二章线性表
1、掌握线性表的顺序存储结构,了解顺序表的存储特点(数据元素在内存中依次顺序存储),优点:
可随机存取访问;
缺点:
结点的插入/删除操作不方便。
线性表:
是一种最简单的数据结构,也是构造其它各类复杂数据结构的基础。
一个数据元素的有序(次序)集。
它有顺序和链式两种存储表示方法。
线性表必有:
1.集合中必存在唯一的一个“第一元素”
2.集合中必存在唯一的一个“最后元素”
3.除最后元素在外,均有唯一的后继;
4.除第一元素之外,均有唯一的前驱
定义如下:
typedefintElemType;
typedefstruct{
ElemType*elem;
//存储数据元素的一维数组;
intlength;
//线性表当前长度;
intlistsize;
//当前分配数组容量;
}SqList;
VoidInitSqList(SqListA,intmaxsize)//初始化线性表
{
A.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!
A.elem)
{
exit(0);
}
A.length=0;
A.listsize=LIST_INIT_SIZE;
return;
}
2、了解线性表的链式存储结构,重点掌握带头结点的单链表的基本操作(结点的插入与删除运算),了解单向循环链表和双向链表存储表示方法。
单链表:
用一组地址任意的存储单元存放线性表中的数据元素。
以元素(数据元素的映象)+指针(指示后继元素存储位置)=结点
(表示数据元素或数据元素的映象)
单链表是一种顺序存取的结构,求以此为存储表示的线性表长度,可设置一个计数器
3、了解有序线性表的特点(顺序有序表、有序链表)。
有序线性表:
线性表中的数据元素相互之间可以比较,并且数据元素在线性表中依值非递减或非递增有序排列,即ai≥ai-1或ai≤ai-1(i=2,3,…,n),则称该线性表为有序表(OrderedList)
4、学会对线性表设计相关的算法进行相应的处理。
第三章排序
1、掌握对顺序表数据记录进行排序的基本思路和常规操作(比较、移动),了解排序算法的稳定性问题。
2、掌握简单选择排序、直接插入排序、冒泡排序算法,了解各种排序算法的特点及时间复杂度。
排序:
将一组“无序”的记录序列按某一关键字调整为“有序”的记录序列。
若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序;
反之则为外部排序。
选择排序:
从记录的无序子序列中“选择”关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度
基本代码如下
for(i=0;
i<
n-1;
i++)/*外循环控制趟数,n个数选n-1趟*/
k=i;
/*假设当前趟的第一个数为最值,记在k中*/
for(j=i+1;
j<
n;
j++)/*从下一个数到最后一个数之间找最值*/
if(a[k]<
a[j])/*若其后有比最值更大的*/
k=j;
/*则将其下标记在k中*/
if(k!
=i)/*若k不为最初的i值,说明在其后找到比其更大的数*/
t=a[k];
a[k]=a[i];
a[i]=t;
}/*则交换最值和当前序列的第一个数*/
插入排序:
插入排序是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。
代码如下:
voidInsertSort(SqList&
L)//对顺序表L作插入排序
for(i=2;
i<
=L.length;
++i)
if(L.r[i].key<
L.r[i-1].key)
{
L.r[0]=L.r[i];
//复制为哨兵
for(j=i-1;
L.r[0].key<
L.r[j].key;
--j)
L.r[j+1]=L.r[j];
//记录后移
L.r[j+1]=L.r[0];
//插入到正确位置
冒泡排序:
泡排序是一种最直观的排序方法,在排序过程中,将相邻的记录的关键字进行比较,若前面记录的关键字大于后面记录的关键字,则将它们交换,否则不交换。
或者反过来,使较大关键字的记录后移,像水中的气泡一样,较小的记录向前冒出,较大的记录
像石头沉入后部。
故称此方法为冒泡排序法
voidBubbleSort(SqList&
L)
{RcdTypeW;
i=L.length;
while(i>
1){//i>
1表明上一趟曾进行过记录的交换
lastExchangeIndex=1;
for(j=1;
j<
i;
j++){
if(L.r[j+1].key<
L.r[j].key){
W=L.r[j];
L.r[j]=L.r[j+1];
L.r[j+1]=W;
//互换记录
lastExchangeIndex=j;
}
i=lastExchangeIndex;
//一趟排序中无序序列中最后一个记录的位置
3、了解什么是堆?
堆是满足下列性质的数列{r1,r2,…,rn}:
(小顶堆)(大顶堆)
第四章栈和队列
1、掌握栈和队列的结构特点及基本操作(入栈、出栈/入队、出队)。
栈(后进先出),队列(先进先出)
构造空栈:
voidInitStack_Sq(SqStack&
S)
{//构造一个空栈S
S.elem=newSElemType[maxsize];
S.top=-1;
S.stacksize=maxsize;
S.incrementsize=incresize;
栈:
(入栈)
voidPush_Sq(SqStack&
S,SElemTypee){
if(S.top==S.stacksize-1)
incrementStacksize(S);
//如果顺序栈的空间已满,应为栈扩容
S.elem[++S.top]=e;
//在栈顶插入数据元素
boolPop_Sq(SqStack&
S,SElemType&
e){
//若栈不空,则删除S的栈顶元素,
//用e返回其值,并返回TRUE;
//否则返回FALSE。
if(S.top==-1)returnFALSE;
e=S.elem[S.top--];
returnTRUE;
2、对于顺序栈,熟悉栈空和栈满的条件;
对于链栈,掌握其栈空的条件。
#include<
iostream>
usingnamespacestd;
#defineINITSIZE100
#defineRESIZE20
typedefstruct{
int*base;
int*top;
intstacksize;
}Sqstack;
intInitstack(SqstackS){
S.base=(int*)malloc(INITSIZE*sizeof(int));
S.base)returnfalse;
S.top=S.base;
S.stacksize=INITSIZE;
returntrue;
intClearstack(Sqstack&
S){
free(S.base);
intStackempty(SqstackS){
if(S.base==S.top)returntrue;
elsereturnfalse;
intPush(Sqstack&
S,inte){
if(S.top-S.base>
=S.stacksize){
S.base=(int*)realloc(S.base,(RESIZE+INITSIZE)*sizeof(int));
S.top=S.base+S.stacksize;
S.stacksize+=RESIZE;
*S.top++=e;
intPop(Sqstack&
S,int&
e){
if(S.base==S.top)returnfalse;
e=*--S.top;
intmain()
SqstackS;
intt,e;
Initstack(S);
cin>
>
t;
//需要输入元素的个数
while(t--)
{
e;
Push(S,e);
}//进栈
while(S.top!
=S.base)
Pop(S,e);
cout<
<
e<
"
"
;
}//出栈
链栈栈空的判断判断链栈是否为空很简单,还记得结构体定义时的那个count吗?
如果那个count为0,就说明链栈为空。
StatusClearStack(LinkStack*S)
LinkStackPtrp,q;
p=S->
top;
while(p)
{q=p;
p=p->
next;
free(q);
}
S->
count=0;
returnOK;
3、掌握栈的典型应用——背包问题求解的基本方法。
背包问题
假设有n件体积分别为w1,w2,…wn的物品和一个能装载体积为T的背包.能否从n件物品中选择若干件恰好装满背包,
即wi1+wi2+…+wik=T,则背包问题有解;
否则无解.
以W(1,8,4,3,5,2),T=10为例
(1,4,3,2),(1,4,5),(8,2)和(3,5,2)是其解。
算法如下
voidknapsack(intw[],intT,intn){
//T在算法中是剩余的容积,初值为背包的体积
InitStack(S);
k=0;
do{while(T>
0&
&
k<
n){
if(T-w[k]>
=0){//第k件物品可以进栈
Push(S,k);
T─=w[k];
k++;
if(T==0)StackTraverse(S);
//输出一个解
Pop(S,k);
T+=w[k];
//退出栈顶物品
}while(!
StackEmpty(S)||k<
n);
4、对于带头结点的链队列,掌握队列为空的条件,熟悉入队、出队的基本操作方法。
voidInitQueue(LiQueue*&
q)
{q=(LiQueue*)malloc(sizeof(LiQueue));
q->
front=q->
rear-NULL;
}//初始化
intQueueEmpty(LiQueue*q)
{if(q->
rear==NULL)return1;
elsereturn0;
}//判空
voidenQueue(LiQueue*&
q,ElemTypee)
{QNode*s;
s=(QNode*)malloc(sizeof(QNode));
s->
data=e;
next=NULL;
if(q->
rear==NULL)
rear=s;
else
{q->
rear->
next=s;
//入队
intdeQueue(LiQueue*&
q,ElemType&
e)
{QNode*t;
return0;
t=q->
front;
front==q->
rear)
rear=NULL;
front->
e=t->
data;
free(t);
return1;
}
//出队
break;
//取队头
5、对于采用顺序存储结构的循环队列,掌握队列为空、队列满的条件,及队列的基本操作。
循环队列判断空满有两种方法:
1.另设一个标志位以区分队列空满;
2.少用一个元素空间,当队头指针在队尾指针下一位时,队列为满,当队头指针与队尾指针相同是队列为空。
在循环队列下,仍定义front=rear时为队空,而判断队满则用两种办法,一是用“牺牲一个单元”,即rear+1=front(准确记是(rear+1)%m=front,m是队列容量)时为队满。
另一种解法是“设标记”方法,如设标记tag,tag等于0情况下,若删除时导致front=rear为队空;
tag=1情况下,若因插入导致front=rear则为队满。
第五章串和数组
1、掌握字符串类型的定义及存储表示方法。
一般情况之下用char定义,
串(String),或称字符串是由零个或多个字符组成的有限序列。
记作:
S=a0a1…ai…an-1(n≥0)
其中,ai属于字符集,n为串的长度,当n=0时串为空串
存储特点
串的实际长度可在这个予定义长度的范围内随意设定,超过予定义长度的串值则被舍去,称之为“截断”
按这种串的表示方法实现的串的运算时,其基本操作为“字符序列的复制”
2、掌握数组的定义和存储结构,熟悉二维数组中数据元素按行存储的基本方法,会计算元素的存储地址。
数组的定义和存储结构
数组是线性表的一种扩充,一维数组即为线性表,二维数组定义为“其数组元素为一维数组”的线性表
3、了解矩阵压缩存储的目的、原理及基本思路和方法。
矩阵压缩存储的目的
1)零值元素占了很大空间;
2)计算中进行了很多和零值的运算,
遇除法,还需判别除数是否为零。
原理及基本思路和方法
1)尽可能少存或不存零值元素;
2)尽可能减少没有实际意义的运算;
3)操作方便。
即:
能尽可能快地找到与下标值(i,j)对应的元素,能尽可能快地找到同一行或同一列的非零值元。
4、了解随机稀疏矩阵的压缩存储方法(三元组顺序表、十字链表)。
三元组顺序表
十字链表
第六章二叉树
1、掌握二叉树的定义、特点及相关概念。
结点的层次:
假设根结点的层次为1,第l层的结点的子树根结点的层次为l+1
树的深度:
树中叶子结点所在的最大层次
二叉树的定义
二叉树是n(n≥0)个元素的有限集,它或为空树,或是由一个根结点加上两棵分别称为左子树和右子树的、互不交的二叉树组成。
2、了解二叉树的性质和存储结构特点,掌握二叉树的顺序存储结构主要用于完全二叉树。
二叉树的性质:
1.在二叉树的第i层上至多有2i-1个结点(i≥1)。
2.深度为k的二叉树上至多含2k-1个结点(k≥1)。
3.对任何一棵二叉树,若它含有n0个叶子结点、n2个度为2的结点,则必存在关系式:
n0=n2+1。
4.具有n个结点的完全二叉树的深度为log2n+1。
若对含n个结点的完全二叉树从上到下且从左至右进行1至n的编号,则对完全二叉树中任意一个编号为i的结点:
(1)若i=1,则该结点是二叉树的根,无双亲,
否则,编号为i/2的结点为其双亲结点;
(2)若2i>
n,则该结点无左孩子,
否则,编号为2i的结点为其左孩子结点;
(3)若2i+1>
n,则该结点无右孩子结点,
否则,编号为2i+1的结点为其右孩子结点。
3、掌握二叉树的二叉链表存储结构。
4、了解二叉树遍历的基本方法(先根次序、中根次序及后根次序遍历二叉树)。
5、了解堆排序的基本方法、了解二叉排序树的基本特点以及如何构造一棵哈夫曼树。
树和森林
树和森林的存储结构
第七章图
1、了解图的基本概念和相关术语。
图是较树结构更复杂的非线性结构
图Graph是由一个顶点集V和一个弧集E构成的数据结构,记作Graph=(V,E)。
其中,图的顶点为数据结构中的数据元素,弧的集合E是定义在顶点集合V上的一个关系。
有序对<
v,w>
表示从v到w的一条弧,并称v为弧头,w为弧尾。
谓词P(v,w)定义了弧<
的意义或信息
由于“弧”是有方向的,因此称由顶点集和弧集构成的图为有向图
2、了解图的存储结构特点(邻接矩阵、邻接表存储结构)。
邻接矩阵:
邻接表存储
3、了解图的遍历方法(深度优先搜索DFS和广度优先搜索BFS)。
深度优先搜索DFS
连通图的深度优先搜索遍历
从图中某个顶点V0出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到。
voidDFS(GraphG,intv){
//从顶点v出发,深度优先搜索遍历连通图G
visited[v]=TRUE;
VisitFunc(v);
for(w=FirstAdjVex(G,v);
w!
=0;
w=NextAdjVex(G,v,w))
if(!
visited[w])DFS(G,w);
//对v的尚未访问的邻接顶点w
//递归调用DFS
}//DFS
非连通图的深度优先搜索遍历
首先将图中每个顶点的访问标志设为FALSE,之后搜索图中每个顶点,如果未被访问,则以该顶点为起始点,进行深度优先搜索遍历,否则继续检查下一顶点。
voidDFSTraverse(GraphG){
//对图G作深度优先遍历
for(v=0;
v<
G.vexnum;
++v)
visited[v]=FALSE;
//访问标志数组初始化
visited[v])DFS(G,v);
//对尚未访问的顶点调用DFS
广度优先搜索BFS
从图中的某个顶点V0出发,并在访问此顶点之后依次访问V0的所有未被访问过的邻接点,之后按这些顶点被访问的先后次序依次访问它们的邻接点,直至图中所有和V0有路径相通的顶点都被访问到。
voidBFSTraverse(GraphG,intv){
++v)
//初始化访问标志
InitQueue(Q);
//置空的辅助队列Q
for(v=0;
++v)
if(!
visited[v]){//v尚未访问
}//BFSTraverse
以深度优先搜索DFS和广度优先搜索BFS的算法为框架,可以派生出很多有实用价值的应用。
1.求一条从顶点i到顶点s的简单路径;
2.求两个顶点之间的一条路径长度最短的路径;
3.求迷宫的最短路径。
4、了解连通网的最小生成树和单源最短路径算法。
连通网的最小生成树
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 算法 设计 知识点 精心 整理
![提示](https://static.bdocx.com/images/bang_tan.gif)