图的存储和串的匹配
一、图的四种存储方式
//下面是图的存储
//(1)邻接矩阵法
#define MaxVertexNum 100
typedef char VertexType;
typedef int EdgeType;
typedef struct
{
VertexType Vex[MaxVertexNum];//顶点表
EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表
int vexnum, arcnum;//图的当前顶点数和弧数
}MGraph;
//(2)邻接表存储
typedef struct ArcNode//边表结点
{
int adjvex;//该弧所指向的顶点的位置
struct ArcNode* next;//指向下一条弧的指针
}ArcNode;
typedef struct VNode//顶点表节点
{
VertexType data;//顶点信息
ArcNode* first;//指向第一条依附该顶点的弧的指针
}VNode, AdjList[MaxVertexNum];
typedef struct
{
AdjList vertices;//邻接表
int vexnum, arcnum;//图的顶点数和弧数
}ALGraph;//以邻接表存储的图类型
//(3)十字链表
typedef struct ArcNode//边表结点
{
int tailvex, headvex;//该弧的头尾结点
struct ArcNode* hlink, * tlink;//分别指向弧头相同和弧尾相同的结点
}ArcNode;
typedef struct VNode//顶点表结点
{
VertexType data;//顶点信息
ArcNode* firstin, * firstout;//指向第一条入弧和出弧
}VNode;
typedef struct
{
VNode xlist[MaxVertexNum];//邻接表
int vexnum, arcnum;//图的顶点数和弧数
}GLGraph;
//(4)邻接多重表
typedef struct ArcNode
{
bool mark;//访问标记
int ivex, jvex;//分别指向该弧的两个结点
struct ArcNode* ilink, * jlink;//分别指向两个顶点的下一条边
}ArcNode;
typedef struct VNode//顶点表结点
{
VertexType data;//顶点信息
ArcNode* firstedge;//指向第一条依附该顶点的边
}VNode;
typedef struct
{
VNode adjmulist[MaxVertexNum];//邻接表
int vexnum, arcnum;//图的顶点数和弧数
}AMLGraph;
二、串的匹配方式
//子串的定位操作通常叫做串的模式匹配,它求的是子串(常称模式串)在主串中的位置
//(1)利用串的其他基本操作给出定位操作的一种算法
int Index(string S, string T, int pos)
{
if (pos > 0)
{
int n = strlen(S);
int m = strlen(T);
int i = pos;
while (i < n - m + 1)
{
substring(sub, S, i, m);
if (strcompare(sub, T) != 0)
++i;
else
return i;
}
return 0;
}
}
//不依赖于其他串操作的暴力算法
int Index(String S, String T, int pos)
{
int i = pos, j = 1;
while(i <= S.length && j <= T.length)
{
if (S.ch[i] == T.ch[j])
{
++i;
++j;//继续比较后继字符
}
else
{
i = i - j + 2;
j = 1;//指针后退重新开始匹配
}
}
if (j > T.length)
return i - T.length;
else
return 0;
}
//KMP算法重要的3个概念:前缀、后缀、部分匹配值(字符串的前缀和后缀的最长相等前后缀长度)
//现在变成子串向后移动,主串不移动
//移动尾数=已匹配的字符数-对应的部分匹配值
//Move = (j - 1) - next[j - 1];
void get_next(string T, int next[])
{
int i = 1, j = 0;
next[1] = 0;
while (i < T.length)
{
if (j == 0 || T.ch[i] == T.ch[j])
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j];
}
}
}
/*
和next数组的计算相比,KMP匹配算法相对要简单得多,它在形式上和简单的模式匹配算法很相似。
不同之处仅仅在于当匹配过程产生失配的时候,指针i不变,指针j退回到next[j]的位置并重新进行比较
并且当指针j为0时,指针i和j同时加1
若主串的第i个位置和模式串的第一个字符不等,则应从主串的第i+1个位置开始匹配
*/
int Index_KMP(string S, string T, int next[], int pos)
{
int i = pos, j = 1;
while (i <= S.length && j <= T.length)
{
if (j == 0 || S.ch[i] == T.ch[j])
{
++i;
++j;//继续比较后续字符
}
else
j = next[j];//模式串向后移动
}
if (j > T.length)
return i - T.length;//匹配成功
else return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下