数据结构小点

顺序表的动态实现:
typedef struct
{
ElemType data;//存储顺序表中元素的首地址
unsigned int maxsize;//顺序表最大长度
unsigned int length;//顺序表元素个数
}SeqList,
PSeqList;

归并算法:有两个顺序表AB,两个顺序表首元素比较,符合条件的(假如是A表的首元素)那个放到新建表里,然后B表的首元素继续和A表的第二个比,直到一个表全部比完,剩下的归并到新表

单链表:
typedef struct LNode
{
ElemType data;//存放节点数据元素
struct LNode* next;//指向下一个节点的指针
}LNode,*Linklist;
Linklist LL;//强调声明一个链表

递归实现:递归是层的概念,自己调用自己,递去归来,如果符合return的条件,就退出当前的层,回到上一层执行完剩下的内容

顺序栈:
typedef struct
{
int data[max];//用数组存放元素
int top;//"栈顶指针"
}SeqStack,*PSeqStack;

链栈:
1.初试化:分配头结点
2.入栈:每次在头结点后插入
3.出栈:在头节点后删除

循环队列:移动头指针和尾指针,因为数组大小是固定的,队底进满了就在头进,然后尾指针移到上面
队尾位置:if(rear>maxsize)rear = rear - maxsize;/rear = rear%(maxsize)+1
队长length = (rear - front + 1 +maxsize)%maxsize
链式队列:尾部入队,头部出队(比单链表多一个尾指针)
1.初始化:生成一个头节点,然后让front指针和rear指针都指向头结点
2.入队:直接在尾指针后加
3.出队:直接让头指针的next指向取出元素的next,如果是出队的是最后一个节点的话,将头指针赋给尾指针

串:
typedef struct
{
char* data;//存放首元素地址
unsigned int maxsize;//字符串最大长度
unsigned int length;//实际长度
}string;

字符串匹配算法
BF算法:目标串A和模式串B,都有一个指针,逐个对比,不符合就将B串的指针下移一位,将A串的指针重新回溯到第一位
KMP算法:如果一次比较没符合,目标串指针每次移到到下一位,模式串可以不回溯到第一位,回溯的位置由比较失败后前面字符串的前缀和后缀决定
目标串ababddgghr
模式串ababc
比较到ababc最后一个c时,目标串是d,不符合,然后看目标串的abab,前缀有a、ab、aba,后缀有b、ab、bab,相同的最大长度的是ab,则回溯到(最大长度+1)2+1=3的位置,即回到第二个a的位置继续比
根据模式串算nextval数组:例如模式串ababc:
含失败的对比串 除去失败 回溯的位置
a 空 0(固定)
ab a 1(固定)
aba ab(a b) 0+1=1
abab aba(a、ab和a、ba) 1+1=2
ababc abab(a、ab、aba和b、ab、bab) 2+1=3
对应的next数组(减1):-1 0 0 1 2
KMP算法优化(优化next数组)
如 a a a a a a
-1 0 1 2 3 4
-1 -1 -1 -1 -1 -1(第一位固定一样,第二个a回到的位置是第一个,然后对比两个字符,一样就用相同的nextval值)
又如b a a b a a
-1 0 0 0 1 2

  • -1 0 0 -1 0 0

顶点的度:与顶点相关联的边的条数
入度:以该定点为终点的边的条数(出度是起点)
路径(顶点序列)、回路(第一个顶点和最后一个顶点相同的路径)、连通(无向图)、强连通(有向图)
连通图(任意两个顶点都是连通的,顶点为n最后n-1条边)
强连通图(顶点为n---n条边)

图的数组表示法(邻接矩阵)
typedef struct{
char vexs[maxsize];//顶点的最大数值
int edges[maxsize][maxsize];//二维数组表示边表(邻接矩阵)
int vexnum,arcnum;//图的顶点数[V]和边数[E]
}MGraph;
在无向图的邻接矩阵,顶点的度为该点所在的行或列中非0个数
在有向图的邻接矩阵,顶点的出度为所在行的非0个数,入度为所在列的非0个数
带权的直接将权值写入邻接矩阵就好
空间复杂度是O(|V|^2),求度的时间复杂度O(|V|)【遍历某行/列】

图的邻接表(有数据冗余):
typedef struct VNode{
VertType data;//顶点的信息
ArcNode first;//顶点的第一条边
}VNode;//顶点的结构体
typedef struct ArcNode{
int adjvex;//边指向的顶点的数组下标(伪指针)
InfoType info;//边的相关信息(权值)
struct ArcNode
next;//指向下一条边的指针
}ArcNode;//边链表的结构体
typedef struct{
VNode vexs[maxsize];//顶点的数组
int vexnum,arcnum;//图的顶点数和边数
}ALGraph;//图的结构体
无向图中,边链表的节点数是2|E|,空间复杂度是O(|V|+2|E|),求顶点度的时间复杂度是O(1)【遍历待求顶点的链表就行】

有向图中,边链表的节点数是|E|,空间复杂度是O(|V|+|E|),求顶点的出度的时间复杂度是O(1),入度是O(|E|)

图的十字链表[适用有向图](就是原有的连接表再加上一个入度的链接表):
边链表的节点总数是|E|,空间复杂度是O(|V|+|E|),顶点的入度和出度的时间复杂度O(1)~O(|E|)

图的邻接多重表[适用无向图]:
边链表的节点总个数是|E|,空间复杂度是O(|V|+|E|),删除边和顶点的操作很方便

图的基本操作--->
1.判断图中是否存在顶点a到b的边:无向图的邻接表直接找a顶点的边链表,邻接矩阵直接数组下标,邻接矩阵最好的时间复杂度是O(1),邻接表的最好O(1)【没有边】最坏复杂度是O(|V|)(连接了其他所有节点,遍历整条边链表来找)
有向图的差不多
2.列出顶点a和b邻接的边:无向图的邻接矩阵直接找a行/b行,邻接矩阵直接找,邻接矩阵最好的时间复杂度是O(|V|)(扫描一整行/列),邻接表最好是O(1)最坏O(|V|)
有向图的邻接矩阵时间复杂度是O(|V|)+O(|V|),邻接表的出度最好O(1),最坏O(|V|),入边O(|E|)
3.插入顶点:都是O(1)
4.删除顶点:
5.插入一条边:O(1)

图的遍历:
广度:利用辅助数组和队列,先入队一个元素,然后出队,再将与其相关联的元素入队(入队就是标记为已访问元素,将辅助数组对应的位置置为true)
深度:利用辅助数组、栈和邻接表(进栈的顺序按照边链表的来)先进栈一个元素A,然后找与A相关联的元素入栈(一直有没访问过的相关联就一直进栈),直到某个元素B和它相关联的元素全部访问过,元素B出栈,然后继续查找上一个元素没访问的元素

最小生成树:
普里姆算法:从任意顶点开始生成树,依次将代价最小的其他顶点纳入生成树(O(n^2))
克鲁什卡尔算法:纵观全图,每次选择权值最小的边,让这条边的两个顶点连通,如果两个顶点已有另外的路径实现了连通,则不选O(|E|log|E|)

posted @ 2022-04-29 10:59  随笔小点  阅读(39)  评论(0)    收藏  举报