《数据结构》复习之图

考研复习之数据结构表树图的基本操作 考研复习之数据结构表树图的基本操作 现在开始准备考研复习了,跨考到妓院去,之前写的一些数据结构的代码写的还算中规中矩,现在拿出来复习倒是挺能理清思路的,分享下。 栈 #pragma once #ifndef __CSTACK_H #define __CSTACK_H #include <cstdlib> #include <iostream> /** 阅读详情

1.图的存储结构

1.1邻接矩阵

  邻接矩阵是图的顺序存储结构,由邻接矩阵的行数和列数可知图中的顶点数。对于无向图,邻接矩阵是对称的,矩阵中“1”的个数为图中总边数的2倍,矩阵中第i行或第i列的元素之和即为顶点i的度。对于有向图,矩阵中“1”的个数为图的边数,矩阵中第i行的元素之和即为顶点i的出度,第j列元素之和即为顶点j的入度。
  邻接矩阵一般用二维数组表示。

1.2邻接表

  邻接表是图的一种链式存储结构。所谓的邻接表就是对图中的每个顶点i建立一个单链表,每个单链表的第一个节点存放有关顶点的信息,把这一个节点看作链表的表头,其余节点存放有关边的信息。如下图所示:
  邻接表的结构
  邻接表的存储表示的定义如下:

typedef struct ArcNode//边结点 
{ 
  int adjvex;  //该边所指向节点的 位置 
  double info; //边的信息存储权值
  struct ArcNode *next; //下一条边的指针 
}ArcNode; 

typedef struct VNode //顶点结点 
{ 
  int data;  //存储节点信息
  ArcNode *firstarc; //边表头指针 
}VNode; 

typedef struct
{
    VNode adjlist[Maxsize]; //邻接表
    int n;      //顶点数
    int e;            //边数
}AGraph;

当然也有简化的定义,比如不需要知道顶点信息,只需要知道边信息的简化邻接表如下:

typedef struct  //简化的邻接表的边
{
    int to;    //该边指向的点
    int val;    //边的权值
    int next;   //下一条边序号,序号为el数组的下标
}edge;
int head[n];  //存储的是初始边的序号
edge el[e];   //边的数组

2.图的遍历

  图的遍历算法主要有深度优先搜索遍历(DFS)和广度优先搜索遍历(BFS),具体的思想不再做阐述,这边我们给出邻接矩阵形式的图的遍历和邻接表的图的遍历。

  • 邻接矩阵的图的遍历代码:
#include<iostream>
#include<queue>
using namespace std;

int visit[50];
int map[50][50];

void dfs(int k,int n)  //深搜,参数n为图的顶点数
{
    int i;
    cout<<k<<" ";
    visit[k]=1;//千万不要忘 
    for(i=0;i<n;i++)
    {
        if(map[k][i]==1&&visit[i]==0)
            dfs(i,n); 
    }
}

void bfs(int n)   //广搜
{
    int temp,i;
    queue<int> q;
    visit[0]=1;        //注意广搜的时候必须是先访问后入队
    cout<<0<<" ";
    q.push(0);
    while(!q.empty())
    {
        temp=q.front();
        q.pop();
        for(i=0;i<n;i++)
        {
            if(map[temp][i]==1&&visit[i]==0)
            {
                visit[i]=1;
                cout<<i<<" ";
                q.push(i);
            }
        }
    }
}

int main()
{
    int n,i,j;
    cin>>n;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            cin>>map[i][j];
        }
    }
    for(i=0;i<n;i++)
    {
        visit[i]=0;
    }
    for(i=0;i<n;i++)   //每个顶点都要访问到 
    {
        if(visit[i]==0)
        {
            bfs(n);
            //dfs(n);
        }
    }
    cout<<endl; 
    return 0;
} 
  • 邻接表的图的遍历代码:
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;

typedef struct  //简化的邻接表的边
{
    int to;
    int next;
}edge;

int ednum;
int *head;
int *visit;
edge *el;

void adde(int x, int y)   //增加边数
{
    el[ednum].to = y;
    el[ednum].next = head[x];
    head[x] = ednum;
    ednum++;
}

void dfs(int x)   //深搜
{
    int i;
    visit[x] = 1;
    cout << x << " ";
    for (i = head[x]; i != -1; i = el[i].next)
    {
        if (visit[el[i].to] == 0)
        {
            dfs(el[i].to);
        }
    }
}

void bfs(int x)   //广搜
{
    int temp, temp2;
    queue<int> q;
    cout << x << " ";
    visit[x] = 1;
    q.push(x);
    while (!q.empty())
    {
        temp = q.front();
        q.pop();
        temp2 = head[temp];
        while (temp2 != -1)
        {
            if (visit[el[temp2].to] == 0)
            {
                cout << el[temp2].to << " ";
                visit[el[temp2].to] = 1;
                q.push(el[temp2].to);
            }
            temp2 = el[temp2].next;
        }
    }
}

int main()
{
    int n, m, temp, x, y, i, flag;

    while (cin >> n >> m, n != 0)
    {
        flag = 0;
        head = new int[n + 1];
        visit = new int[n + 1];
        el = new edge[2 * m];
        memset(head, -1, sizeof(int)*(n + 1));
        memset(visit, 0, sizeof(int)*(n + 1));
        temp = m;
        ednum = 0;
        while (temp > 0)
        {
            cin >> x >> y;
            adde(x, y);
            adde(y, x);
            temp--;
        }
        for (int i = 1; i <= n; ++i)   //深搜
        {
            if (visit[i] == 0)
            {
                dfs(i);
                // bfs(i);
            }

        }
        cout << endl;
        delete[] head;
        delete[] visit;
        delete[] el;
    }
    return 0;
}

  不管是深搜还是广搜都是图的算法的重要组成部分,也是解决很多图的问题模板方法。

3.图的特殊算法

  归纳一下,图的特殊算法包括,最小生成树算法(Prim算法和Kruskal算法),最短路径算法( Dijkstra算法和Floyd算法),拓扑排序和关键路径。如图所示:
  图的特殊算法

3.1最小生成树算法

  • Prim算法
    算法思想:
    从图中任意取出一个顶点,把它当做一棵树,然后从与这棵树相接的边中选取一条最短(权值最小)的边,并将这条边及其所连接的顶点也并入这棵树中,此时得到了一棵有两个顶点的树。然后从与这棵树相接的边中选取一条最短的边,并将这条边及其所连顶点并入当前树中,得到一棵3个顶点的树。以此类推,直到图中所有顶点都被并入树中为止,此时得到的生成树就是最小生成树。
    程序的过程可以如下表示:
    Prim算法流程
    算法的代码如下:
#define MaxSize 100
#define INFINITE 9999

#include<iostream>
using namespace std;

int Graph[MaxSize + 1][MaxSize + 1];

int Prim(int n)   //Prim算法的时间复杂度只与图中的顶点有关系,与边数没有关系。
{
    int sum = 0;
    int mincost[MaxSize + 1];
    int minset[MaxSize + 1];
    bool set[MaxSize + 1];
    set[1] = true;            //假设从1开始
    for (int i = 2; i <= n; i++)  //算出第一个点的情况
    {
        mincost[i] = Graph[1][i];
        minset[i] = 1;
        set[i] = false;
    }
    for (int i = 1; i < n; i++)  //循环n-1次  1.选最小的 2.加入集合 3.更新边
    {
        int min = INFINITE;
        int j = 1;
        for (int k = 2; k <= n; k++)  //找出最小的边
        {
            if (mincost[k] < min && (!set[k]))
            {
                min = mincost[k];
                j = k;
            }
        }
        cout << j << " " << minset[j] << endl;
        set[j] = true;
        sum += min;
        for (int k = 2; k <= n; k++)
        {
            if (Graph[j][k] < mincost[k] && (!set[k]))  //为什么不会有回路,因为每次加入的点都是不在集合中的
            {
                mincost[k] = Graph[j][k];
                minset[k] = j;
            }
        }
    }
    return sum;
}

int main()
{
    int n, m;
    int x1, x2, x3;
    cout << "创建图,请输入顶点个数:" << endl;
    cin >> n;
    cout << "请输入边条数:" << endl;
    cin >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            Graph[i][j] = INFINITE;
        }
    }
    cout << "现在请输入相连的信息(格式:顶点1(空格)顶点2(空格)权值):" << endl;
    for (int i = 1; i <= m; i++)
    {
        cin >> x1 >> x2 >> x3;
        Graph[x1][x2] = x3;
        Graph[x2][x1] = x3;
    }

    cout << "最小生成树是:" << endl;
    int sum = Prim(n);
    cout << "最小权值是:" << sum << endl;
    return 0;
}

  时间复杂度分析:
  Prim算法主要是一个双重循环,因此时间复杂度为O(n2)。由算法可见,Prim算法的时间复杂度只与图中的顶点有关系,与边数没有关系,因此Prim算法适用于稠密图。

  • Kruskal算法
    算法思想:
    将图中边按照权值从小到大排序,然后从最小边开始扫描各边,并检测当前边是否为候选边,即是否该边的并入会构成回路,如不构成回路,则将该边并入当前的生成树,直到所有边都被检测完为止。
    判断回路需要用到并查集。并查在这里不做多的介绍,可参考http://blog.youkuaiyun.com/dellaserss/article/details/7724401/
    算法代码如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef struct L
{
    int i;
    int j;
    int val;    
}L;

int map[50][50];

bool compare(L a,L b)
{
    return a.val<b.val;
}

int find(int r,int pre[])
{
    while(r!=pre[r])
        r=pre[r];
    return r;

}

int main()
{
    int sum=0;
    int n,i,j;
    cin>>n;
    vector <L> eu;
    L temp;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            cin>>map[i][j];
            if(map[i][j]&&i>j)  //无向图,只要记住一条边就行,用i>j来筛选 
            {
                temp.val=map[i][j];
                temp.i=i;
                temp.j=j;
                eu.push_back(temp); 
            }
        }
    }
    int length=eu.size();
    int pre[length];
    sort(eu.begin(),eu.end(),compare);

    for(i=0;i<length;i++)
    {
        pre[i]=i;
    }
    int k;
    for(k=0;k<length;k++)
    {
        if(find(eu[k].i,pre)!=find(eu[k].j,pre))
        { 
            pre[eu[k].i]=eu[k].j;
            sum+=eu[k].val;
        }
    } 
    cout<<sum<<endl; 
    return 0;
} 

  时间复杂度分析:
  从上述代码可以发现,Kruskal算法的时间主要话费在sort()函数和单循环上,由于循环是线性的,可以认为算法时间主要花费在sort()函数上。因此Kruskal算法的时间复杂度由排序算法决定。排序算法所处理数据规模由图的边数e决定,与顶点数无关,因此Kruskal算法适用于稀疏图。

3.2最短路径算法

  • Dijkstra算法

    算法思想:
    设有两个顶点集合S和T,集合S中存放图中已找到最短路径的顶点,集合T存放图中剩余顶点。初始状态时,集合S中只包含源点v0,然后不断从集合T中选取到顶点v0路径长度最短的顶点vu并入到集合S中。集合S每并入一个新的顶点vu,都要修改顶点v0到集合T中顶点的最短路径长度值。不断重复此过程,直到集合T的顶点全部并入到S中为止。
    算法代码如下:

#define INF 99999
#include<iostream>
#include<set>
using namespace std;

int map[50][50];

int main()
{
    int n, i, j, s;
    cin >> n >> s;
    int *dis=new int[n];
    for (i = 0; i<n; i++)
    {
        for (j = 0; j<n; j++)
        {
            cin >> map[i][j];  //要注意输入的时候0相当于无穷不能直接用
            if (map[i][j] == 0)
            {
                map[i][j] = INF;
            }
            if (i == s)
            {
                dis[j] = map[i][j];
            }
        }
    }

    set <int> uion;
    uion.insert(s);
    int minval;
    int flag;
    while (uion.size() != n)
    {
        minval = INF;
        for (i = 0; i<n; i++)
        {
            if ((uion.find(i) == uion.end()) && dis[i]<=minval)  //==才是没有找到,!=是找到了
            {
                minval = dis[i];
                flag = i;
            }
        }

        uion.insert(flag);

        for (i = 0; i<n; i++)
        {
            if ((uion.find(i) == uion.end()) && dis[i]>dis[flag] + map[flag][i])
            {
                dis[i]=dis[flag] + map[flag][i];
            }
        }
    }

    for (i = 0; i<n; i++)
    {
        if (i != s)
        {
            cout << dis[i] << " ";
        }
    }
    cout << endl;
    return 0;
}

  Dijkstra算法和Prim算法的异同点:
  可以看到Dijkstra算法和Prim算法非常相似,它们都有如下的过程:
  这里写图片描述
  但是它们的目的是不同的,Prim算法是求最小生成树,Dijkstra算法是求最短路径,Prim算法是找当前树到树之外其余点的最小边,Dijkstras算法是找起点到其余点的距离最小值,必须要搞清楚其区别不能搞混。
  Dijkstra算法的时间复杂度:O(n2)(双重循环)
  Dijkstra算法的另一种变形:SPFA算法
  SPFA(Shortest Path Faster Algorithm)(队列优化)算法是求单源最短路径的一种算法。很多时候,给定的图存在负权边,这时类似Dijkstra算法等便没有了用武之地。这时就可以用SPFA算法。直接贴代码:
  

#define INF 99999
#include<iostream>
#include<queue>
using namespace std;

int map[50][50];
int *dis;
int visit[50];

int relax(int u, int v)
{
    if (dis[v]>dis[u] + map[u][v])
    {
        dis[v] = dis[u] + map[u][v];
        return 1;
    }
    else
    {
        return 0;
    }
}

void SPFA(int src, int n)
{
    int i, x, temp;
    dis[src] = 0;
    queue<int> q;
    q.push(src);
    visit[src] = 1;
    while (!q.empty())
    {
        x = q.front();
        q.pop();
        visit[x] = 0;
        for (i = 0; i<n; i++)
        {
            if (map[x][i] != -1&&visit[i]==0&&relax(x, i))
            {
                q.push(i);
            }
        }
    }
}

int main()
{
    int n, i, j, s;
    cin >> n >> s;
    dis = new int[n];
    for (i = 0; i<n; i++)
    {
        for (j = 0; j<n; j++)
        {
            cin >> map[i][j];  //要注意输入的时候0相当于无穷不能直接用
            if (map[i][j] == 0)
            {
                map[i][j] = -1;
            }
        }
    }
    for (i = 0; i<n; i++)
    {
        dis[i] = INF;
        visit[i] = 0;
    }

    SPFA(s, n);

    for (i = 0; i<n; i++)
    {
        if (i != s)
        {
            if (dis[i] != INF)
            {
                cout << dis[i] << " ";
            }
            else
            {
                cout << -1 << " ";
            }

        }
    }
    cout << endl;
    return 0;
}
  • Floyd算法

    Floyd算法代码相对简单,但时间复杂度较高。它的算法思想是以k为中间点对所有的顶点{i,j}进行检测和修改
    代码如下:

#define INF 99999
#include<iostream>
using namespace std;

int map[50][50];
int path[50][50];  //用于记录路径

int main()
{
    int n, i, j;
    cin >> n ;
    for (i = 0; i<n; i++)
    {
        for (j = 0; j<n; j++)
        {
            cin >> map[i][j];  //要注意输入的时候0相当于无穷不能直接用
            if (map[i][j] == 0&&i!=j)
            {
                map[i][j] = INF;
            }
            result[i][j] = map[i][j];
            path[i][j]=-1;
        }
    }
    for (int k = 0; k < n; k++)
    {
        for (i = 0; i < n; i++)
        {
            for (j = 0; j < n; j++)
            {
                if (result[i][j] > result[i][k] + result[k][j])
                {
                    result[i][j] = result[i][k] + result[k][j];
                    path[i][j]=k;
                }
            }
        }
    }

    for (i = 0; i<n; i++)
    {
        for (j = 0; j < n; j++)
        {
            if (result[i][j] != INF)
            {
                cout << result[i][j] << " ";
            }
            else{
                cout << -1 << " ";
            }
        }
        cout << endl;
    }

    cout << endl;
    return 0;
}

  Floyd算法的时间复杂度:O(n3)(三层循环)
  Floyd算法和Dijkstra算法用法的区别:Dijkstra算法是求图中某一顶点都其余各顶点的最短路径,而Floyd算法是求图中任意一对顶点间的最短路径。当然Dijkstra算法的时间复杂度要远远小于Floyd算法。
  

3.3关键路径算法

  介绍一下拓扑排序算法:
  在一个有向图中找到一个拓扑排序序列的过程如下:
  1) 从有向图中选择一个没有前驱(入度为0)的顶点输出
   2) 删除1)中的顶点,并且删除从该顶点发出的全部边
   3) 重复上述两步,直到剩余的网中不存在没有前驱的顶点为止。
   拓扑排序可以判断是否有环路,若顶点均被删除(有拓扑排序)则无环路,(无拓扑排序)否则有环路。(其实深搜就能判断是否有环路,对于无向图来说,若深搜的过程中遇到了回边,即检测到visit[i]不为0,则必定存在回环。对于有向图则不那么简单,如果从有向图中的某个顶点v出发进行深搜,若在顶点v处遍历其他邻接顶点过程结束前出现一条从顶点u指向v的回边,则有向图必定包含v和u的环)。
   拓扑排序若以邻接表为结构,则根据上述过程,要在顶点结点出加count来统计当前结点的入度,顶点结点结构体如下:

typedef struct VNode
{
    int data;
    int count;   //用来统计顶点当前入度
    ArcNode *firstarc;
}VNode;

算法代码如下:

int TopSort(AGraph *G)
{
    int i,j,n=0;
    int stack[maxSize],top=-1;
    ArcNode *p;
    for(i=0;i<=G->n;i++)//将图中入度为0的顶点入栈
    {
        if (G->adjlist[i].count==0)
        {
            stack[top++]=i;
        }
        while(top!=-1)
        {
            i=stack[top--];
            ++n;
            cout<<i<<" ";
            p=G->adjlist[i].firstarc;
            /*下面的循环实现了将所有由此顶点引出的边所指向的顶点的入度都减少1,并将这个过程中入度变为0的顶点入栈*/
            while(p!=NULL)
            {
                j=p->adjvex;
                --(G->adjlist[j].count)
                if (G->adjlist[j].count==0)
                {
                    stack[++top]=j;
                }
                p=p->nextarc;
            }
        }
        if (n==G->n)
        {
            return 1;//n==顶点数,说明拓扑排序成功
        }
        else
        {
            return 0;
        }
    }
}

关键路径核心算法:关键路径的算法由于篇幅太长,暂时没有写。

数据结构复习之【图】 一、基本术语 图:由有穷、非空点集和边集合组成,简写成G(V,E); Vertex:图中的顶点; 无向图:图中每条边都没有方向; 有向图:图中每条边都有方向; 无向边:边是没有方向的,写为(a,b) 有向边:边是有方向的,写为 有向边也成为弧;开始顶点称为弧尾,结束顶点称为弧头; 简单图:不存在指向自己的边、不存在两条重复的边的图; 无 阅读详情

相关推荐

Android以太网开关流程分析

Android以太网开关流程分析 一、引言   在Android 以太网服务启动流程中我们启动了EthernetService(ES),NetworkManagementService(NMS)等服务,其中ES作为Binder的服务端,向客户端EthernetManger提供了调用接口的引用。因此,应用可以通过EthernetManger来访问以太网的相关接口。本篇文章将从APP调用以太网的使能和关闭的接口流程作为切入点来分析,以太网框架中,上层app是如何将指令传递到底层。图1-1所示为以太网使能和关闭

franc521的博客 6112

数据结构——图最全总结(期末复习必备)

数据结构——图最全总结(期末复习必备)

weixin_65049289的博客 1万+

stm32入门 点亮TFTLCD(NT35510驱动)

正点原子stm32f407探索者开发板屏幕使用正点原子4.3寸TFTLCDstm32f407开发使用标准库本文参考正点原子例程和NT35510的data sheet,尽量使用最少的代码点亮屏幕。

tangliang_cn的博客 1981

数据结构——第四章图:02图的存储结构

1.数组表示法(邻接矩阵表示法):用两个数组分别存储数据元素(顶点)的信息和数据元素(顶点)之间关系的信息。若图G是一个具有n个顶点的无权图,G的邻接矩阵是具有如下性质的n × n矩阵A:A[i, j] = 1(若<vi, vj> ∈ VR),反之为0。若图G是一个有n个顶点的网,则它的邻接矩阵是具有如下性质的n× n的矩阵A:A[i, j] = wij(若<vi, vj&gt...

weixin_30814319的博客 457

说说PSTN、ISDN、 ADSL三种互联网接入方式的区别。

互联网的接入方式: 电话拨号接入(PSTN) ISDN接入 ADSL接入 Cable MODEM接入 局域网接入 光纤接入(FDDI) 卫星接入 DDN专线 目前来说,ADSL和Cable MODEM比较常用,今天我们就先来说说PSTN、ISDN和ADSL的区别。 电话拨号接入(PSTN/POTS,Public Switched Telephone Network / Public Oold Telephone Service) 数据终端设备(DTE)通过数据通信设备(DCE)再连

Winyaz的博客 2万+

OPCUA二(通过OPCUA服务器访问CPU)

摘要:本文介绍了使用UaExpert软件连接西门子PLC的OPC UA配置方法,包括IP地址设置(默认端口4840)、安全认证和证书信任流程。详细说明了数据访问操作,如变量拖拽监控和属性解读(NodeId、Value、状态码等)。特别强调连接仿真Advance7时需先启动实例。最后预告下章将讲解通过KerServer访问CPU。文章涵盖配置步骤、常见问题处理及实用技巧,适合工业自动化开发者参考。

欢迎来到RaymondLeigh的知识共享基地 1336

【数据结构】图

图 1.1定义 图(Graph)结构是一种非线性的数据结构。 由一组顶点和一组能够将两个顶点相连的边组成的。 1.2.存储结构 存储结构分两种 一种是邻接矩阵(二维数组)另一种是邻接表 1.2.1邻接矩阵 二维数组索引的值表示顶点 二维数组存储的值表示是否连接 若连接 则存储1 否则存储0 2图的遍历 2.1深度优先遍历 2.1.1例题 P1135 奇怪的电梯 输入格式 共二行。 第一行为33个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N

qq_52784066的博客 197

特征提取 Features Extraction

介绍了特征提取的基本概念,从分类变量,文本信息和图片信息中进行特征提取的方法,以及实现特征提取的类库

JasonH2021的博客 1万+

《数据结构复习笔记》图

概要:掌握图的定义与基本术语掌握图的存储方式掌握图的两种遍历方式掌握图的最小生成树,最短路径,拓扑排序,关键路径的生成方式与算法1,图的基本概念    图的特点,图中的关系可以是任意的:任意一个节点都可以有零个或多个前驱,也可以有零个或多个后继,也都可以作为起始结点或终结结点。1.1 图的定义与基本术语    1,图的定义    Graph = (V,E)  其中V为顶点的有限集合,E是边的有限集...

小白菜的博客 383

Ollama教程——模型:如何将模型高效导入到ollama框架

本教程详细介绍了如何将GGUF、PyTorch和Safetensors格式的模型导入到ollama框架中。通过一系列步骤,从环境准备、模型转换和量化,到最终的模型创建和运行,我们为开发者提供了一个清晰的指南。此外,我们还探讨了如何发布模型到ollama平台,使得模型可以被更广泛地分享和应用。ollama框架提供了一个灵活、高效的解决方案,帮助开发者在各种环境中部署和运行机器学习模型。无论您是想将现有模型快速部署到生产环境,还是希望探索新的模型架构,ollama都能为您提供所需的工具和资源。

walkskyer的博客 1万+

爬取Unsplash高清壁纸:Python爬虫实战教程(最新技术)

在当今数字化时代,高清壁纸已经成为人们个性化设备的重要元素。Unsplash作为全球最知名的免费高质量图片网站,汇集了数百万张由全球摄影师贡献的高清图片。然而,Unsplash官网的下载方式需要手动操作,对于需要批量下载壁纸的用户来说效率较低。本文将带你深入探索如何使用Python爬虫技术高效爬取Unsplash高清壁纸,从基础到进阶,全面掌握图片爬取的核心技术。Unsplash成立于2013年,是一个完全免费的图片分享平台。高质量内容:所有图片均由专业摄影师上传,分辨率普遍达到4K以上免费商用。

2201_76125261的博客 935

数据结构——图

提示:以下内容不适合零基础人员,仅供笔者复习之用。 一、图的定义         图是由顶点的有穷非空集合和顶点之间边的集合组成, 通常表示为: G(V,E), 其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。 线性结构中,元素仅有线性关系,每个元素只有一个直接前驱和直接后继;树形结构中,数据元素(结点)之间有着明显的层次关系,每层上的元素可能和下一层中多个元素

厚积而薄发,谋定而后动 2万+

顶级AI大模型白嫖ChatGPT Plus1个月,0成本薅顶配功能

Chat*** Plus限时免费1个月!原价20美元/月的顶配功能

BUG猿的博客 7266

数据结构之【图】部分复习题

第六章 图 一、选择题 1.图中有关路径的定义是(A )。 A.由顶点和相邻顶点序偶构成的边所形成的序列 B.由不同顶点所形成的序列 C.由不同边所形成的序列 D.上述定义都不是 2.设无向图的顶点个数为n,则该图最多有(B)条边。 A.n-1 B.n(n-1)/2 C. n(n+1)/2...

weixin_30897233的博客 945

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【数据结构复习总结】—— 图

1. 完全图 - 无向图中任意两个顶点之间都存在边,称为无向完全图。 n个顶点,n(n-1)/2 条边 - 有向图中任意两个顶点之间都存在相反的两条弧,称为有向完全图。 n个顶点, n(n-1)条边 ## 2. 连通图/强连通图 - **无向图** 中顶点v到顶点w有路径存在,称v和w连通。若任意两个顶点都连通,`连通图` 若一个图有n个顶点,并且边数小于n-1,则此图必是非连通图 若一个图有n个顶点,并且边数大于n-1,则此图必有回路 - **有向图** 中顶点v到顶点w和顶点w到顶点v之间都有

小牛肉的博客 3562

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【数据结构复习之路】图(严蔚敏版)两万余字&超详细讲解

图(Graph)是一种复杂的非线性数据结构,由顶点集合及顶点间的关系(也称弧或边)集合组成。可以表示为:GVVR其中V是顶点的有穷非空集合;VR是顶点之间关系的有穷集合,也叫做弧或边集合。弧是顶点的有序对,边是顶点的无序对。⚠️注意:线性表可以是空表,树可以是空树,但图不可以是空。上图中画红叉的图是不符合图的定义的!1.1 有向图若vw>∈VR,则vw表示从v到w的一条弧,且称v为弧尾,称w为弧头。

m0_74215326的博客 2566

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

数据结构复习指导之图的遍历

图算法的难度较大,主要掌握深度优先搜索与广度优先搜索。掌握图的基本概念及基本性质、图的存储结构(邻接矩阵、邻接表、邻接多重表和十字链表)及特性、存储结构之间的转化、基于存储结构上的各种遍历操作和各种应用(拓扑排序、最小生成树、最短路径和关键路径)等。 图的相关算法较多,通常只需掌握其基本思想和实现步骤,而实现代码不是重点。

心碎烤肠的博客 1427

数据结构复习——树、图等

文章目录一、树 此文章基于C语言实现的,参考书籍:《数据结构(C语言版)》——清华大学出版社 严蔚敏 吴伟民 编著 一、树

weixin_43773038的博客 1153

数据结构复习(图)

图 选择题 邻接表是图的一种( )。 A 顺序存储结构 B 链式存储结构 C 索引存储结构 D 散列存储结构 对于一个不带权的无向图的邻接矩阵而言,( )。 A 矩阵中非零元素的数目等于图中边的数目 B 矩阵中非零的行的数目等于图中顶点的数目 C 第i行的非零元素的数目与第i列的非零元素的数目相等 D 第i行与第i列的非零元素的总数等于第i个顶点的度数 最小生成树指的是( )。 A 由连通图所得到的边数最少的生成树 B 由连通图所得到的顶点相对较少的生成树 C 连通图的所有生成树中权值之和最小的生成树 D

努力的程序员 3495

数据结构/第六章 图/数据结构习题/图的习题/考研/期末复习

1. 在下图中,顶点a到e的距离是( )。A. 10 B. 6 C. 6或10 D. 无法确定2. 对于一个6个顶点的无向图,至少有( )条边能构成一个连通图。3. 对于一个5个顶点的无向图,有( )条边能确保是一个连通图。4. 一个图的邻接矩阵表示是( ),邻接表表示是( )。A. 不唯一,不唯一 B. 不唯一,唯一 C. 唯一,不唯一 D. 唯一,唯一。

qq_45767840的博客 653

【数据结构】图_复习笔记总结

图由两个集合 V 和 E 组成,记为 G = (V,E), V 是顶点集,E 是边集顶点对 有序,意为一条由点 x 指向点 y 的有向边。 和 是不同的两条边在 中,x 是始点 / 弧尾,y 是终点 / 弧头顶点对(x, y) 无序,(x, y) 和 (y, x) 指的是同一条。

Texcavator的博客 417

数据结构总结复习(图)

所以采用了邻接表的形式,这个的概念就是,图的每个顶点都作为一个结构体结点,结构体内包含,当前结点的值和与它相连的结点的指针。图是由点和线组成的,也就意味着它的关系基本上就是由线来指引的点与点、点与线,线与线之间的关系。所以需要能够表示它们相互关系的结构来指示,矩阵就是一个很简单的方法,比如a[i][j]=1可以表示i、j之间存在边,a[i][j]=0表示不存在。先定一个结点,然后从那个结点开始,然后找最短的路线。确定最短路线对应的结点,将该结点纳入已经处理过的结点,然后再进行处理,找最短路线,进行循环。

allfortoday的博客 425

[数据结构复习]图

1.图的表示 1)邻接矩阵    对于普通图,0 /1     对于网络(或带权图),邻接矩阵的值  0/N 2)邻接表     如果点多边少,用邻接矩阵很浪费存储空间,这时候用邻接表。    用邻接表的话,如果想得到顶点的入度,必须检测其他所有顶点对应的边链表,这时候可以建立逆邻接表。   3.邻接多重表 邻接多重表在要求每条边处理一次的实际应用中特别有用。

沈鸿斌的博客 862
上一篇: 《数据结构》复习之二叉树
下一篇: 《数据结构》复习之排序算法
King来写代码
博客等级 码龄12年 68粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值