思维导图链接

例题总结链接

排序算法思想和动图
排序算法代码

DS重点

  • 1.⭐⭐必背概念定义:
  • 2.⭐⭐必考解答题:
    • 2.1 绪论:
    • 2.2 线性表:
    • 2.3 栈
    • 2.4 队列
    • 2.5 树和二叉树(必考一个代码) ♥♥♥
      • 树、二叉树、森林的互相转化
      • 树和森林的遍历
      • 二叉排序树BST
      • 平衡二叉树AVL
      • 哈夫曼树和哈夫曼编码
      • 线索二叉树(待整理)
      • 2.5.2 ♥二叉树相关代码
    • 2.6 图(可能考一个代码,战略放弃)♥
      • 图的基本概念
      • 图的存储(邻接矩阵、邻接表)
      • 图的遍历(深度优先DFS、广度优先BFS)
      • (最小)生成树:Prim、Kruskal
      • 最短路径:Dijkstra、Floyd
      • 拓扑排序:AOV网
      • 关键路径:AOE网
      • 总结助记
    • 2.7 查找
    • 2.8 排序

1.⭐⭐必背概念定义:

满二叉树:高度为k的二叉树共有2的k次方-1个节点,2的(k-1)次方个叶子节点。

完全二叉树:除最后一层外为满二叉树,且最后一层节点从左到右分布,树中所有节点与满二叉树一一对应。

注:满二叉树和完全二叉树都适合顺序存储

线索二叉树(物理结构):一棵采用二叉链表存储的二叉树,每个节点设指向左右孩子的2个指针域,设其采用一种遍历方式,若节点左子树为空则指向其前驱节点,右子树为空指向后继节点,这种在二叉树中加上线索的二叉树称为线索二叉树。

哈夫曼树(最优二叉树):在含有n个带权叶节点的二叉树中,带权路径长度WPL最小的二叉树称为哈夫曼树。

二叉(排序/搜索/查找)树 BST(逻辑结构):它或者是1棵空树或者是满足如下条件的二叉树:
1 左子树非空,左子树节点的值<根节点
2 右子树非空,右子树>根节点
3 左右子树又分别是一棵BST二叉排序树
4 中序遍历为一个递增的有序序列

平衡二叉树 AVL树(逻辑结构):它或者是1棵空树或者是满足如下条件的二叉树:
左右子树的高度差的绝对值不超过1,且左右子树又分别是一棵平衡二叉树。

避免二叉排序树的高度增长过快而降低其性能,规定在插入和删除二叉树节点时,满足任意节点的左右子树高度差(平衡因子)的绝对值不超过1的二叉树
注意:调整平衡的时候,哪个节点左(右)旋就要牺牲它的左(右)孩子放到对应位置。

图的生成树:(对应深度优先+广度优先生成树)
生成树是连通图的包含图中的所有n个顶点n-1条边的极小连通子图。
图的生成树不惟一,不存在回路。从不同的顶点出发进行遍历,可以得到不同的生成树。

图的生成森林:
非连通图的连通分量的生成树构成了生成森林。

图的最小生成树MST:(无向图对应Prim和Kruskal算法)
连通的无向带权图中边权值之和最小的生成树。
最小生成树性质:
1最小生成树不唯一,树形不唯一,若图中各条边的权值不同则MST唯一。
2最小生成树的权重之和唯一
3具有n个顶点n-1条边,不产生回路
只有无向图才有最小生成树,有向图不研究

B树
(又称多路平衡查找树),B树中所有节点的孩子个数最大值m称为B树的阶。它或者是空树,或者是满足下列性质的m树:
1、树中每个节点最多m棵子树
2、根节点非终端则最少2棵子树
3、除根结点以外的所有结点(不包括叶子结点)最少┌m/2┐棵子树
4、非叶节点关键字递增有序且满足:左子树<节点<右子树,关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;
5、所有的叶子结点都位于同一层。
注意:B树的插入分裂都是往上和父节点挤在一起,而且如果平衡因子不为0需要再次 调整

B树创建、插入删除练习:

2008 给了一棵3阶B树,画图描述连续删除两个数,再在原图上连续插入两个数过程。
(说白了,往年很多这种题)

B+树: 仅了解 概念即可

2.⭐⭐必考解答题:

2.1 绪论:

有空研究下时间复杂度的判断

1.什么是数据结构?

数据结构是指相互之间存在一种或多种特定关系的 数据元素 的集合。包括:逻辑结构,存储结构和数据的运算。

2.逻辑结构与物理(存储)结构的联系和区别?

联系:1两者密不可分,算法的设计取决于逻辑结构,算法的实现取决于存储结构。
区别:
2逻辑结构 指数据之间的逻辑关系,分为线性结构和非线性结构,与数据如何存储无关,独立于计算机。
一个逻辑结构可以有多种存储结构。
3存储结构 指数据结构在计算机中的表示(映像),包括数据元素的表示和数据元素之间关系的表示。
主要有顺序、链式、索引、散列存储结构,依赖于计算机。

3.什么是算法?如何理解程序=数据结构+算法?

算法是指对特定问题求解步骤的一种描述,是指令的有限序列。
1.数据结构是底层,算法是高层;数据结构为算法提供服务;
数据结构是算法实现的基础,算法依赖数据结构操作;
2.数据是程序的中心,数据结构是数据间的有机关系,算法是对数据的操作步骤,
高效的程序需要在数据结构的基础上设计和选择算法.
3.数据结构和算法两者相互依存不可分割,否则程序根本无法设计。

4.算法的基本特性有哪些?简述其含义。

1.有穷性:一个算法必须在执行 有穷步 之后结束,每一步都在 有穷时间内 完成。
2.确定性:算法的每条指令必须有 确切 的含义,相同输入得到相同输出。
3.可行性:算法中描述的操作可以通过已经实现的基本运算 执行有限次 来实现。
4.输入性:算法有0个或多个输入,这些输入取自于某个特定 对象 的 集合  。
5.输出性:算法有1个或多个输出,这些输出是与输入有着某种特定 关系 的 量 。

5.好的算法应该具有哪些特性?简述之。

1.正确性:一个算法必须 正确解决 问题。
2.可读性:算法具有良好的 可读性 ,便于 理解 。
3.健壮性:输入 非法数据 时 ,算法能适当做出反应或处理,不会产生莫名其妙的输出结果。
4.效率与低存储量需求:效率指算法执行时间,存储量需求指算法执行所需的最大存储空间,2者都与问题规模n有关 。

6.如何衡量算法效率?

1.时间复杂度:衡量算法随着问题规模n的增大,算法 执行时间 增长的快慢 T(n)=O(f(n))
通常用算法中基本的运算频度f(n)来分析算法时间复杂度,
算法时间复杂度不仅与 问题规模n 还与 输入数据k的性质 有关
频度:语句在算法中被重复执行的次数
T(n):算法中所有语句频度之和
2.空间复杂度:衡量算法随着问题规模n的增大,算法 所需空间 增长的快慢 S(n)=O(g(n))
算法原地工作:算法所需辅助空间为常量O(1)。

2.2 线性表:

顺序或链式存储
单、循环、双向 链表插入、删除代码

1.分析线性表顺序存储和链式存储的优缺点?

1.顺序存储:
优点:随机访问(存取),按序号查找元素方便快速,存储密度高
缺点:需要事先划分整块内存空间,可能造成空间浪费,逻辑相邻元素物理也相邻,插入删除元素不方便
2.链式存储:
优点:插入删除节点方便,只需修改指针不需移动大量元素,内存分配灵活,       不要使用地址连续的存储单元
缺点:每个节点既有数据域还有指针域(占用额外空间),无法随机存取,只能顺序存取,查找不方便,需要从头遍历

2.头指针和头节点的区别?

1.头指针:
头指针始终指向链表的第一个结点,它是一个链表存在的标志,必须存在。
2.头节点:
头节点是第一个节点之前的节点,数据域通常不存储信息,方便在第一个节点之前进行插入删除操作,不是必须的。

3.带头和不带头节点单链表的区别?

1结构上:
带头节点,无论表是否为空,至少存在一个头节点,
不带头,则直接为空,不含头节点
2操作上:
带头节点,初始化时需要申请一个头节点,元素插入删除操作位置是否在第一个节点 无关
不带头,初始化不要申请头节点,若插入删除位置在第一个节点,则需要另外考虑

4.单链表插入、删除节点操作?(插删操作时间复杂度都是O(1)但是查找On)

单链表结构体定义
typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;带头结点(head)的头插法建表:
LNode<T> * s=new LNode<T> ();//T是模板型定义 template<typename T>s->data=x;s->next=head->next;head->next=s;
带尾指针(rail)的尾插法建表:
LNode * s=new LNode ();//新建节点s->data=x;r->next=s;r=s;r=>next=null;
单链表删除节点:p=GetElem(head,i-1);//p为删除节点的前驱节点q=p->next;//q指向待删节点p->next=q->next;delete q;

5.双链表插入、删除节点操作?

双链表结构体定义(方便找前驱)
typedef struct DNode{int data;struct DNode *prior,*next;}DNode,*DLinkList;双链表在p指向节点之后插入s:
DNode * s=new DNode ();//新建节点
p->nex->prior=s;
s->next=p->next;
p->next=s;
s-prior=p;双链表删除p指向节点的后继节点q:
q->nex->prior=p;
p->next=q->next;
delete q;

6.循环单链表和循环双链表

循环单链表尾指针不指向NULL, 判空条件head->next==head;
仅设尾指针rail的循环单链表 效率最高O(1),因为rail->next==head,找头方便
如果只有头指针要从头遍历找rail  O(n)循环双链表  判空条件head->next==head&&head->prior==head;
head->prior==rail
rail->next==head
此外首节点也前驱也指向头节点

2.3 栈

仅允许栈顶TOP一端进行插入删除,先进后出
n个元素入栈,出栈序列公式:(同时也是具有n个节点不同二叉树的个数)

1.栈空栈满的条件?

栈空:s.top==-1
栈满:s.top==Maxsize-1

2.顺序栈与链式栈入栈出栈操作?

顺序栈
入栈:if(s.top!=Maxsize-1) s.data[++s.top]=x;
出栈:if(s.top!=-1) x=s.data[s.top--];链式栈(所有操作在表头进行,头插,头删,不会出现栈上满溢)
入栈:p->next=top; top=p;
出栈:x=top->data; top=top=>next;

3.利用栈进行中缀转后缀表达式?

若为操作数ABCD直接进入后缀表达式
若为"("则直接入栈
若为“)”则把栈中“(...)”之间的元素从 上到下 所有运算符+-*/全部捞出来 从左到右 放入后缀
若为"+-*/"低优先级的<op> 例如+或者-可以把同级的 +- 或者高级的 */ 捞出来,按顺序放入后缀注意运算符<op>捞的途中遇到栈中的"("会被隔断
最后栈中剩余运算符按顺序全部出栈进入后缀

4.利用栈进行后缀表达式求值


5.栈应用在括号匹配中的思想?

2.4 队列

栈和队列的比较,队满或空条件,入队出队,层次遍历+B D P

1.比较栈和队列的异同?

相同:
逻辑结构都属于线性结构
都可顺序和链式结构存储
都是操作受限的线性表,插入都在表尾进行不同:
操作不同:
栈仅仅允许在栈顶(表尾)进行插入和删除,满足先进后出
队列允许在队尾插入,队头删除,满足先进先出
应用不同:
栈应用包括:函数调用及递归实现,括号匹配,表达式转换和求值,深度优先搜索遍历,迷宫求解
队列应用:消息缓冲区,计算机资源管理,层次遍历,广度优先搜索遍历
栈有共享栈,队列没有

2.顺序队列和单循环链式队列 队空队满条件?

顺序队空:Q.front==Q.rear==0
顺序队满:(Q.rear+1)%Maxsize==Q.front队中元素总数=(Q.rear-Q.front+Maxsize)%Maxsize
单循环链式队空:front==rear
单循环链式队满:rear->next==front注意 非循环 单链队列 队空条件front==rear==NULL,因为单链队入队无限制,所以不会队满!

3.入队出队操作?

入队:if((Q.rear+1)%Maxsize!=Q.front) Q.data[Q.rear]=x;Q.rear=(Q.rear+1)%Maxsize;出队:if((Q.front!=Q.rear) x=Q.data[Q.front];Q.front=(Q.front+1)%Maxsize;

3.最适合作链队的链表?

带队首和队尾指针的非循环单链表
(循环单链表需要更新首尾,较为麻烦,适合出队不释放空间循环利用的队列。)

4.队列应用在二叉树层次遍历的思想?

1.根入队
2.队列中第一个节点出队,访问之首先若有左孩子,左孩子入队其次若有右孩子,右孩子入队
3.重复执行2直到队空,结束遍历。

2.5 树和二叉树(必考一个代码) ♥♥♥

♥树和二叉树的 基本概念 见前面必背概念题部分

1.度为2的树和二叉树的区别?

1、树的度不同
二叉树对于度的要求为不超过2,节点最多只能够有两个叉,同时也可以是0或者1。最少0个节点
度为2的树要求任意节点最多只能够有两棵子树,而且最少存在一个节点有两棵子树。最少3个节点
2、次序不同
一棵度为2的树和二叉树在形式上非常的相似,但度为2的数的子树是无序的,但是二叉树的子树是有顺序的。
3、分支不同
一棵度为2的树可能有两个子树,但度为2的数的子树没有左右之分。
同样的二叉树也具有两个子树,但是两个子树左右之分,子树的次序不能任意的颠倒。

2.一般树的存储结构有哪些?

1、双亲表示法
采用一组连续的空间存储每个节点,同时在每个节点后面增设一个伪指针指向双亲
2、孩子表示法
将每个节点的孩子用单链表链接起来形成一个线性结构
3、孩子兄弟表示法
二叉链表作为树的存储结构,左指针指向第一个孩子节点,右指针指向相邻的兄弟节点,(左孩子右兄弟)
typedef struct TNode{int data;TNode * Lchild; //指向第一个孩子TNode * Ribiling;//指向第一个兄弟
}TNode, *Tree;

二叉树链式存储如下:

typedef struct BiTNode{int data;struct BiTNode *Lchild,*Rchild;//左右孩子指针
}BiTNode, *BiTree;

树、二叉树、森林的互相转化




树和森林的遍历







二叉排序树BST

静态有序查找表选:顺序表+二分查找
动态有序查找表选:二叉排序树(逻辑结构)
BST查找效率:进化为AVL时 平均ASL:为O(log②n),单支树O(n)

左<根<右
中序遍历为递增的有序序列
构造、插入、查找 直接从上到下依次按大小即可

BST删除节点Z操作:
1删除叶子直接删,不影响
2Z有一个孩子(左或右),直接继承Z的位置
3Z有2个孩子,则从左子树或者右子树 找中序遍历 大小最接近Z 的节点代替Z,优先选保持树 平衡 的节点。



平衡二叉树AVL

平均查找长度ASL为O(log②n)
n个节点的平衡二叉树的最大(理想)高度:log②n取下整后+1 (有时不适用,最好按下面公式慢慢数)
高度为h的平衡二叉树的最少节点:N0=0,N1=1,N2=2,N(h)=N(h-1)+N(h-2)+1(别忘记+1!)
N3=4,N4=7,N5=12,N6=20…

n个节点二叉树查找某个关键字最多比较次数
BST:n次
AVL:log②n取下整后+1次

调整平衡的注意点:

1新建一个二叉平衡树在插入部分节点 过程中 一影响平衡就调整,而不是等到所有节点插入完成才调整
2每次调整 最小 不平衡子树,如果导致A和A的子树B都失衡,先调整子树B。
3每次导致以A为根的树失衡,都是对其失衡的左L(右R)子树儿子或者孙子进行上旋转,而不是A
4每次左(右)上旋,都要将其左(右)子树节点(如果有)贡献出去。
5倒过来旋: LL右旋,RR左旋,儿子旋一次
LR左+右旋,RL右+左旋 孙子先旋一次,儿子再旋一次
6在A儿子B的子树C上插入的 不管是C的左还是右子树 导致不平衡,不影响旋转。
A父亲,B儿子,C孙子




哈夫曼树和哈夫曼编码

原节点(叶子节点)为⬜,新建节点(根节点)为⚪,
叶子节点n个,新建的根节点n-1个,哈夫曼树一共2*n-1个节点
WPL只计算叶子节点,新建的根节点没有权值,且结果没有分母,有分母的是ASL。.
且WPL是路径x节点的权值,ASL直接路径×1(节点权值全为1)/节点数


构造哈夫曼求WPL例题






线索二叉树(待整理)

王道P142

2.5.2 ♥二叉树相关代码



1.二叉树 前中后 序遍历算法如下:

先序递归算法:
void PreOrder(BiTree T)
{if(T!=NULL){visit(T);//根PreOrder(T->lchild);//左PreOrder(T->rchild);//右}
}
中序,后序改变3条语句位置即可。先序非递归算法(借助栈):
void PreOrderStack(BiTree T)
{InitStack(S);//初始化栈BiTree p=T;//指针p用于遍历while(p || !Isempty(S))//p不空或者栈不空循环{if(p)//一路向左{Push(S,p);//当前节点入栈p=p->lchild;//一直往左访问左孩子}else//出栈,转向出栈节点右子树{Pop(S,p);visit(p);//栈顶出栈,访问出栈节点p=p->rchild;//往右子树走,p指向右子树}}
}

2.二叉树 层次 遍历算法如下(借助队列):

 void LevelOrder(BiTree T){InitQueue(Q);//初始化队列EnQueue(Q,T);//根入队BiTree p;while(!IsEmpty(Q))//队不空则循环{DeQueue(Q,p);//队头出队visit(p);//访问队头if(p->lchild !=null)Enqueue(Q,p->lchild);//左子树不空,左子树根入队if(p->rchild !=null)Enqueue(Q,p->rchild);//右不空,右根入队}}

用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。

[题目分析]
若某个结点左子树空右子树非空或者右子树空左子树非空,则该结点为度为1的结点
[算法描述]
int Level(BiTree bt) //层次遍历二叉树,并统计度为1的结点的个数
{int num=0; //num统计度为1的结点的个数if(bt){QueueInit(Q); QueueIn(Q,bt);//Q是以二叉树结点指针为元素的队列
while(!QueueEmpty(Q))
{p=QueueOut(Q); cout<<p->data;     //出队,访问结点
if(p->lchild && !p->rchild ||!p->lchild && p->rchild)num++;
//度为1的结点
if(p->lchild) QueueIn(Q,p->lchild); //非空左子女入队
if(p->rchild) QueueIn(Q,p->rchild); //非空右子女入队
} // while(!QueueEmpty(Q))
}//if(bt)
return(num);
}//返回度为1的结点的个数 

判断是否为完全二叉树

int IsFull_BiTree(BiTree T)//判断是否为完全二叉树
{LinkQueue Q;InitQueue(&Q);int flag=0;EnQueue(&Q,T);Q_ElemType p;while(!QueueEmpty(Q)){DeQueue(&Q,&p);if(!p){flag=1;}else if(flag){return 0;}else{EnQueue(&Q,p->Lchild);EnQueue(&Q,p->Rchild);}}return 1;
}

4.统计二叉树度为2的节点数目代码。2018

4.统计二叉树度为0的节点(叶子节点)数目代码。2016,2019

统计二叉树度为0,1, 2节点数

3.以二叉链表为存储结构,写出求二叉树深度depth的代码。

int Max (int a,int b)
{if(a>b)return a;return b;
}
int GetBinaryTreeDepth(BL_BTree BT_root)
{if(BT_root==NULL)return 0;elsereturn Max( GetBinaryTreeDepth(BT_root->lchild),GetBinaryTreeDepth(BT_root->rchild) )+1;
}//法二
int TreeDeep(BiTree T)//求树的深度
{int n=0;if(T){int L=TreeDeep(T->Lchild);int R=TreeDeep(T->Rchild);n=L+1>R+1?L+1:R+1;}return n;}

4.求二叉树的宽度width代码。

在这里插入代码片

bool _CheckCompleteTree(Node *root){queue<Node*> q;if (root == NULL)      //空树是完全二叉树return true;q.push(root);bool flag = false;while (!q.empty()){Node* front = q.front();if (front != NULL){if (flag)return false;q.push(front->_left);q.push(front->_right);}elseflag = true;q.pop();}return true;}

4.判断给定二叉树是否为二叉排序树BST的代码。王道

在这里插入代码片

5.判断给定二叉树是否为二叉平衡树AVL的代码。王道

在这里插入代码片


struct Element{int key;};
struct TreeNode
{TreeNode *LeftChild,*RightChild;Element data;
}
利用上面两个结构给出判断一棵根为t的二叉树是否为AVL树的递归算法。(此题我用了2分钟)
bool Tree::IsAVL()
{return  IsAVL(t);
}bool Tree::IsAVL(TreeNode * cur)
{if(!cur) return true;//...下面自己写哈
}int Tree::Height(TreeNode * cur)
{

6.求给定二叉排序树最小和最大关键字k的代码。王道

在这里插入代码片


2013年935

(8分)二叉树T采用二叉链表存储,T中结点结构为(Lchild,data,Rchild),其中Lchild和Rchild分别是指向左右孩子的指针,data为正整数,编写算法,按后序遍历次序输出T中每个结点data值及所处层次(假定根节点在第一层)

24(12分)设S是n个互不相同的整数组成的序列,试编写一个尽可能高效的算法,判定S是否可能在某棵二叉搜索树查找过程中产生的关键字比较序列,若S可能是,则算法输出为1,否则为0。请说明算法的设计思想,并给出时间复杂度和空间复杂度。

2017 935


2.6 图(可能考一个代码,战略放弃)♥

图的基本概念

连通:2个顶点有路径
连通图:图中任意2个顶点都连通
极大连通子图(连通分量):该连通图要包含所有的边,如果整个图不连通,可能有多个连通分量
极小连通子图:保持图连通且边最少的子图,其中最小生成树对应n个顶点n-1条边的极小连通子图

图的存储(邻接矩阵、邻接表)


存储的空间复杂度:
邻接表O(n+e)
邻接矩阵O(n²)


图的遍历(深度优先DFS、广度优先BFS)

采用不同存储方式 图遍历的时间复杂度:
邻接表O(n+e)
邻接矩阵O(n²)

避免重复访问采用visited[]数组给访问过的节点加标记=1
DFS采用栈进行回退,BFS利用队列的思想




(最小)生成树:Prim、Kruskal

区分:
生成树:不带权值 , 不唯一
最小生成树:带权值的生成树,可能唯一,最小权值可能重复边

因为 无向图 的生成树不唯一,每条路径加上权值w就可以得到最小生成树MST,包含n个顶点,n-1条边,权值最小,无回路 。(有向图叫最小树形图不作研究)
最小生成树MST唯一的一个充分条件是:在带权连通图的任意一个当中所包含的权值均不相同时。

Prim算法:点点相连,V0出发 每次找相邻顶点的最小权值边相连,直到所有顶点都访问
记顶点数v,边数e 时间复杂度 :邻接矩阵:O(v²) 邻接表:O(elog₂v)
算法改进的思路:1减少候选边的数量,2提高候选边的选择效率


重点:选择最短边时不要有回路,否则舍弃选次短

最短路径:Dijkstra、Floyd

求v0到其它各点的最短路径:
结果:(V0,V2,V4,V3,V5)。



Floyd算法 O(n³)

void Floyd(int n,int Gtaph[maxisize][maxisize],int path[maxisize][maxisize])
{int i,j,k;int A[maxisize][maxisize];for(int i=0;i<n;i++)//初始化最短路径邻接矩阵A和路径path数组{for(j=0;j<n;j++){A[i][j]=Graph[i][j];path[i][j]=-1;}}for(k=0;k<n;k++)//Vk作为中转节点{for(int i=0;i<n;i++){for(j=0;j<n;j++){if(A[i][k]+A[k][j]<A[i][j])//如果Vi经过Vk中转到达Vj路径更短{A[i][j]=A[i][k]+A[k][j];//更新Vi->Vj的最短路径path[i][j]=k;//同时更新中转矩阵}}}}
}


拓扑排序:AOV网

拓扑序列(不唯一):
C1–C2–C3–C4–C5–C7–C9–C10–C11–C6–C12–C8
C9–C10–C11–C6–C1–C12–C4–C2–C3–C5–C7–C8

拓扑排序算法实现:
1 DFS+栈的实现思路:时间复杂度O(n+e)
找到顶点,递归遍历到最后的结点,通过回溯将遍历到的点入栈,
那么先进栈的必定是出度为0的结点,入度为0的结点必定在最后进栈,最后通过出栈可以得到排序后的顺序。
注意:
在DFS中,依次打印所遍历到的顶点;而在拓扑排序时,顶点必须比其邻接点先出现。
在DFS实现拓扑排序时,用栈来保存拓扑排序的顶点序列;并且保证在某顶点入栈前,其所有邻接点已入栈。
2 队列的思路:
通过遍历,将所有入度为0的进入队列。并将与之相连的结点的入度-1。
然后一个一个的出队列,出队列的同时判断与出队列结点相连的结点是否入度为0,为0则进队。
循环第一二步,直到所有节点被选择或者栈空。(其实队空的时候,所有节点就是被选择了)

关键路径:AOE网



事件最早=活动最早=源点到事件顶点V的路径权值和的最大值(从前往后和最大)
事件最迟=汇点到事件V各条路径的距离最小值(从后往前差最小)
活动最迟=事件最迟-活动的权值
关键活动:活动最迟-活动最早=0

注:从源点到汇点时,选择较大的权值。从汇点到源点时,选择较小的权值。来回均相同的路径就是关键路径。
上图顶点 左|右 活动时间差额为0的顶点就是关键活动,从前往后所有的活动次序就算关键路径。

总结助记

BDP、DFK、拓扑排序、关键路径

栈: 递归,先序遍历, DFS深度优先遍历

队列: 层次遍历,BFS广度优先遍历(无权图单源最短路径)

DP 顶点出发

=DJ迪杰斯特拉 正权图 单源 最短路径,解答过程是每次选出一个顶点的表格
=Prim最小生成树:从某点V1出发,每次再找点与其他点相连的最短边,点点相连

FK 短边优先

Floyd 正+负 权图 各顶点 最短路径,
解答过程是每次更新一个顶点矩阵A(i) (i=-1,0,1,2...n)aij 为各个顶点的距离
和Path矩阵path(i)  (i=-1,0,1,2...n)pathij 为需要更新的中转节点,初始默认全为-1
=K克鲁斯卡尔最小生成树:首先列出所有顶点(不带边),每次优先选择一条最短边(且不产生回路),短边集合

连通无向图G=(V,E)采用邻接表存储,其中|V|=n,|E|=e。现需要在G中找到这样一个顶点V,删除V及相关联的边对剩下的图的连通性无影响。试说明解决上述问题的算法思路(不需要写出具体程序),并估计时间复杂度

2.7 查找

二分查找,哈希表构造,散列函数,处理冲突,拉链法/线性探测法,ASL成功/失败

二分查找:O(log2n)
仅适用于顺序存储结构且效率较高的非线性查找

1.散列(哈希)表 查找O(1):建立了关键字和存储地址之间一种直接映射关系的数据结构。
散列函数:一个把查找表中关键字映射为该关键字对应地址的函数。
冲突:散列函数把多个不同关键字映射为同一地址的情况。
同义词:发生碰撞的不同关键字

常用散列函数
1直接定址法:H(key)=a*key+b 不产生冲突,适合关键字基本连续,否则可能会造成空间浪费
2除留余数法:H(key)=key mod q
3数字分析
4平方取中

处理冲突方法:1开放定址法、2链地址(拉链法)、3再哈希法(同时构造多个哈希函数直到解决冲突)

开放定址法:Hi=(H(key)+di)%m
开放定址法的增量序列di取法 :
1线性探测法di=0,1,2,3,m-1
2平方探测法di=0,1²,-1²,2²,-2²
3双(再)散列法(构造2个哈希函数)
4伪随机序列法

查找成功平均长度ASL成功=总查找成功次数 / 关键字个数n
查找失败平均长度ASL失败=每个下标到最近的空位置(一直往寻找)的长度和 / MOD的值q(分母不是表长m)。

2.拉链法:

ASL成功:节点个数*拉链表位置之和/关键字个数n
ASL失败:节点个数n/表长m=装填因子a

装填因子a=表中元素个数n/散列表长度m
如果已知a 例如=0.75和表元素个数n 例如11,可以求得表长m=44/3≈ 14(取上整),从而得q=13

ASL 成功= (1×3 + 2 + 3)/5 = 1.6
ASL 失败= (5 + 4 + 3 + 2 + 1 + 2 + 1) / 7≈ 2.57(如果空位置不算作一次那结果应该相差1)



注意:开放定址法Hi=(H(key)+di)%m=(key%q +di)%m 其中q是最接近表长m(不是元素个数n)的素数
H0=H(key)不冲突的情况,此时用不到表长,只用对q取余
H1=(key%q +d1)%m 冲突一次,此处是取余表长m不是q!

对于查找失败的情况只需要关注q个元素的失败情况,因为对q取余最多是0-q-1也就是q个数,表中多出q的元素(q~m-1)在查找失败时候可以忽略不记,如下题

H0(20)=20%7= 6 冲突!-> H1(20)=(6+1)%11=7


2.8 排序

内部排序各种算法的稳定性,时间复杂度,比较,概念

什么是排序算法的稳定性?(稳定性并不体现算法优劣,时间/空间复杂度来体现)

经过排序后,关键字相同的元素保持原顺序的相对位置不变,则称该排序算法稳定。

不稳定的排序算法:希堆快选
1次排序能确定1个元素最终位置的排序:冒堆快选
排序趟数与原始有关的:冒堆快

基于比较排序 关键字最少比较次数:log₂(n!)取上整
不基于比较的内部排序算法:基数排序
既适用顺序存储又适用链式存储的排序:直接插入,快排、基、归并排序
仅适用顺序表:折半,希尔排序,堆排序也不能用链表 因为调整堆时没法随机访问底层孩子节点
平均性能最好的内部排序:快速排序

算法复杂度与序列初始状态无关的:


内部和外部排序算法的区别:

内部排序:排序期间元素都存储在内存中
外部排序:排序期间元素内外存不断移动

堆排序:待整理

例题1



【数据结构】思维导图补充知识相关推荐

  1. 个人知识体系思维导图_“知识体系”打得好,学霸孩子跑不了,巧用“思维导图”来帮忙...

    文章纯属原创,版权归本作者所有,欢迎个人转发分享. 相信很多妈妈都会看见孩子学习学不进去的苦恼,孩子看着很用功,每天按时完成作业.做练习题,但是成绩就是一直上不去,还会出现成绩不升反降的情况.这成了许 ...

  2. 数据结构思维导图——Java版

    数据结构思维导图--Java版

  3. 数据结构思维导图,超全!超详细!

    文章目录 数据结构思维导图 一.数据结构基本概念 二.线性表 三.栈和队列 四.树 五.图 六.查找 七.排序 八.二叉树与树与森林 数据结构思维导图 我在一个平台(忘记了)上发现了一个博主制作的数据 ...

  4. 通过思维导图学习知识的两种模板鉴赏

    在学习中,我们可以制作思维导图来帮助记忆.理解.正所谓千言万语不如图,一张简单的思维导图就能涵盖整篇文章的中心思想.分析出事物之间的关系.而在制作思维导图的时候,人脑也跟着进行分析,这才是思维导图最大 ...

  5. 《数据结构 思维导图》

    下面和大家分享一下数据结构的思维导图. 总的思维导图: 第一章:数据结构 第二章:线性表 第三章:栈.队列和数组 第四章:树和二叉树 第五章:图 第六章:查找 第七章:排序

  6. 【转】ADO.Net之SqlConnection、 Sqlcommand的应用学习心得(思维导图,知识解析,案例分析)

    ADO.Net之SqlConnection. Sqlcommand的应用 一.思维导图: ADO.NET与SQL连接: 二.知识点介绍: SqlConnection和Sqlcommand都是组成数据提 ...

  7. 数据结构 思维导图【绪论、线性表、栈、队列和数组、树与二叉树、图、查找、排序】

    目录 01.绪论 02.线性表 03.栈.队列和数组 04.树与二叉树 05.图 06.查找 07.排序 算法 数据结构 排序算法 01.绪论 02.线性表 03.栈.队列和数组 04.树与二叉树 0 ...

  8. 数据结构思维导图汇总

    数据结构框架: 注:以下转载自董的博客 1.常见数据结构 线性:数组,链表,队列,堆栈,块状数组(数组+链表),hash表,双端队列,位图(bitmap) 树:堆(大顶堆.小顶堆),trie树(字母树 ...

  9. 数据结构思维导图总表

    数据结构总表:单说数据的结构,其实就分为逻辑结构和物理结构. 逻辑结构包括:线性结构.非线性结构.抽象数据类型. 物理结构包括:顺序存储.链式存储.索引存储.哈希存储. 其他的后续再补充. 百度定义: ...

最新文章

  1. fedora上ARM-LINUX-GCC 编译器安装
  2. 应用宝上架审核要求_【建议收藏】安卓应用商店上架经验,含流程,方法
  3. Emotion英语学习
  4. 写给java初学者,从零开始学习java开发的完整学习路线
  5. 保存光谱曲线出现问题_直读光谱仪计量周期-这家好【博越仪器】
  6. 《Cocos2d-x3.x游戏开发之旅》学习
  7. Orleans 知多少 | Orleans 中文文档上线
  8. 月薪30K大佬源码阅读的经验总结,干货不容错过
  9. 云承软件和云溪哪个好_多工序开料机的软件对接及注意事项
  10. 【UML】部署图和构件图
  11. VB6_小林的气象类模块
  12. PS制作透明图片png格式
  13. 怎样看股市K线图指标之市场盈亏指标CYS
  14. win10用账户登录计算机,Win10支持两种账户登录,一种是本地账户,另一种是Microsoft账户...
  15. android多任务列表高斯模糊
  16. Spark 和hadoop的一些面试题(准备)
  17. [solved] hp victus ubuntu 20.04 wifi
  18. 3D Human Pose Estimation with Spatial and Temporal Transformers论文笔记
  19. 时间序列分析 | Python实现时间序列统计分析与建模
  20. 桌面应用程序和网站引入Mapl中的数学引擎

热门文章

  1. if(-1)为真还是假_女人是“真拒绝”还是“假矜持”,其实一眼就能看出来
  2. oracle 闪回技术
  3. Python 和curl 调用sendcloud发送邮件
  4. 仿真文件的写法(以四位全加器为例)
  5. php接收vb post数据,VB Post方式提取网页数据
  6. SQL NOTE-VARIABLE
  7. springboot如何使用多线程,线程池管理
  8. Android系统使用感受——记录我的三星GT-S5830
  9. 怎样让git不用每次输入密码_不用输入WIFI密码 “一碰连”就能上网
  10. telnet收发邮件