2023/1/8总结

目录

一:kruskal算法(最小生成树)

二:prim算法

 三:KMP算法


一:kruskal算法(最小生成树)

1:理解

2023/1/8总结_第1张图片

 如图,要求找到一条最短的路径。我们先从最小的数1开始,1->2为1,1->3为2,4->6为3,6->5为4,2->3注意2和3这两个端点都被连接了,也就是说2->3可以通过2->1->3.同理4->5也不行,3->4为9可以,当数量达到总数-1时路便通了。

此时变成

2023/1/8总结_第2张图片

 步骤:1,先把长度从小到大排序。2,查找两个点是否都连接了,3,到n-1的时候输出。

注意:排序使用快排,查找使用查并集。

1,排序

void kp(int l,int r)//从大到小进行快排
{struct fun t;
    if(l>r)
    return;
    int i=l,j=r;
    while(i!=j)
        {
            while(kk[j].c>=kk[l].c&&i

 2,查找

void csh(int q)//初始化
{
    for(int i=1;i<=q;i++)
        x[i]=i;
}
int find(int i)//查找
{
    if(x[i]==i) return i;
    x[i]=find(x[i]);return x[i];
}
int hp(int i,int j)//合并并判断
{
    if(find(i)!=find(j))
        {x[j]=i;return 1;}
        return 0;
}

 3,kruskal核心算法

  for(int i=1;i<=m;i++)//核心算法
    {
        if(hp(kk[i].a,kk[i].b))
        {
            c++;sum+=kk[i].c;
        }
        if(c==n-1) break;
    }

完整代码:

#include
using namespace std;
#define N 100
int x[100];
struct fun
{
    int a,b,c;
}kk[N];
void kp(int l,int r)//从大到小进行快排
{struct fun t;
    if(l>r)
    return;
    int i=l,j=r;
    while(i!=j)
        {
            while(kk[j].c>=kk[l].c&&i>n>>m;
    csh(n);
    for(int i=1;i<=m;i++)
    {
        cin>>kk[i].a>>kk[i].b>>kk[i].c;
    }
    kp(1,m);
    for(int i=1;i<=m;i++)//核心算法
    {
        if(hp(kk[i].a,kk[i].b))
        {
            c++;sum+=kk[i].c;
        }
        if(c==n-1) break;
    }
    cout<

二:prim算法

1,理解:

2023/1/8总结_第3张图片

还是这张图,求最短路径。这里我们随便选一个点1,离他最近的点是2,那么1和2看成一个集合,离着个集合最近的点是3,123又成一个集合,同理找到4,6,5。sum=1+2+9+3+4=19.

注意:找点的时候要找孤立的点。 

这里把每两点距离进行初始化

 for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(i==j) e[i][j]=0;
            else e[i][j]=inf;

在存储的时候要反向再储存一遍

for(i=1;i<=m;i++)
    {
        cin>>t1>>t2>>t3;
        e[t1][t2]=t3;//无向图,需要反向再储存一遍
        e[t2][t1]=t3;
    }

初始化1号顶点到每个点的距离,就是我们说的集合处理找最短

for(i=1;i<=n;i++)//初始化,1号顶点到各个顶点的距离
        dis[i]=e[1][i];

核心

book[1]=1;//标记是否一个顶点已经加入树
    c++;
    while(ce[j][k])
                dis[k]=e[j][k];
        }
    }
    cout<

完整代码

#include
using namespace std;
int main()
{
    int n,m,i,j,k,min,t1,t2,t3;
    int e[7][7],dis[7],book[7]={0};
    int inf=99999999;//储存一个无穷值
    int c=0,sum=0;//c用来记录树中顶的个数,sum储存路径和
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(i==j) e[i][j]=0;
            else e[i][j]=inf;
    for(i=1;i<=m;i++)
    {
        cin>>t1>>t2>>t3;
        e[t1][t2]=t3;//无向图,需要反向再储存一遍
        e[t2][t1]=t3;
    }
    for(i=1;i<=n;i++)//初始化,1号顶点到各个顶点的距离
        dis[i]=e[1][i];
    book[1]=1;//标记是否一个顶点已经加入树
    c++;
    while(ce[j][k])
                dis[k]=e[j][k];
        }
    }
    cout<

 三:KMP算法

字符串查找问题。

首先,我们得知道部分匹配值(数组next)。部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。

以ABCDABD为例。

"A"的前缀和后缀都为空集,共有元素的长度为0;

"AB"的前缀为[A],后缀为[B],共有元素的长度为0;

"ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

"ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

"ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

"ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;

"ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

那么知道了部分匹配值,这有一个公式:移动位数 = 已匹配的字符数 - 对应的部分匹配值

以字符串:BBC ABCDAB ABCDABCDABDE为例 ,子链:ABCDABD

2023/1/8总结_第4张图片

 next(部分匹配值)

 for(int i=2;i<=len2;i++)//next数组处理
   {
    while(i1&&str2[i1+1]!=str2[i])//如果str2[i1+1]!=str2[i]那么这串连续的相等断了,所以无法继承之前的情况
    {
        i1=n[i1];//顺着next我们可以找到能够让我们继续匹配的值,但i1不能为0并且如果我们找到了str2[i1+1]==str2[i]的地方,那么就可以从这里开始继承
    }
    if(str2[i1+1]==str2[i])
    {
        i1++;//相等就比下一个,同时这也是计数+1
    }
    n[i]=i1;//把算出的值给next
   }

代码

#include
using namespace std;
char str1[1000005],str2[1000005];
int len1,len2,i1;
int n[1000005];
int main()
{
    scanf("%s %s",str1+1,str2+1);
    len1=strlen(str1+1);
    len2=strlen(str2+1);
    for(int i=2;i<=len2;i++)//next数组处理
   {
    while(i1&&str2[i1+1]!=str2[i])//如果str2[i1+1]!=str2[i]那么这串连续的相等断了,所以无法继承之前的情况
    {
        i1=n[i1];//顺着next我们可以找到能够让我们继续匹配的值,但i1不能为0并且如果我们找到了str2[i1+1]==str2[i]的地方,那么就可以从这里开始继承
    }
    if(str2[i1+1]==str2[i])
    {
        i1++;//相等就比下一个,同时这也是计数+1
    }
    n[i]=i1;//把算出的值给next
   }
    i1=0;//初始化
    for(int i=1;i<=len1;i++)//和求next差不多
    {
        while(i1&&str2[i1+1]!=str1[i])
        {
            i1=n[i1];
        }
        if(str2[i1+1]==str1[i])
        {
            i1++;
        }
        if(i1==len2)
        {
            printf("%d\n",i-len2+1);//输出str2在str1中出现的位置
            i1=n[i1];
        }
    }
    for(int i=1;i<=len2;i++)
        printf("%d ",n[i]);
}

你可能感兴趣的:(算法,数据结构)