数据结构之邻接表
·
概念及介绍
首先邻接表一种图的存储结构,他是用来存储图的,接下来我将带大家手撕邻接表

依照上图,给大家解释一些名词:1的箭头指向下一个数值的时候,我们把箭头叫有向边或者叫节点,下一个数值,列如1->2的这个2我们叫他编号

1、存储方式
我们用结构体来存储
首先vertex是编号,也就是存储当前的编号,例如1->2,我们存储的2
next是节点,当我们存好了2的时候,假如要存储下一个的时候,我们要拉出来一个节点,为存储下一个编号做好准备,例如当前1->2(存好了),再来出来一个节点,为下一个做好准备1->?
注意:不要多想,如果想到1->2,为什么不是2->3,就不要去想为什么是1拉开一个节点存储3?看看下面的添加代码会解开你的疑惑
typedef struct Node {
int vertex;
//存储的是当前这条边指向的目标节点编号
// 例如1->2,存储的是2
// 例如:1指向2存的就是2,再来1指向3,存储的就是3
struct Node* next;
//指向同一个起始节点的下一条出边的节点。
// 例如:1->2,1->3.1->4
// ->就是节点
// 起始节点1
// 下一条出边:就是当前2存储了,下次要存3这个编号的节点
// 例如;1—>2(现在存好了),假设下一个要存1—>3,虽然没有存到3,但是已经拉出来了这个->节点为存3做出了准备
} Node;
2、添边
先申请一个结构体空间,申请失败就打印出问题
最后添边操作就是模拟(蓝色是申请新的结构体空间)



void add(int x, int y)
{
Node* newNode = (Node*)malloc(sizeof(Node));//申请一个结构体空间
if (newNode == NULL)
{
//如果申请失败就退出,并且打印出哪里的问题
printf("malloc fail!");
return;
}
//添边操作
newNode->vertex = y;
newNode->next = graph[x];
graph[x] = newNode;
}
3、实现排序
排序就是先把链表转换成数组,然后数组转换成链表,直接把代码给你们看,我用的是y总的快排模板去排序的,也可以用冒泡等排序,自己喜欢
//快排模板
void quick_sort(int a[], int l, int r)
{
if (l >= r)return;
int key = a[l], i = l - 1, j = r + 1;
while (i < j)
{
do {
i++;
} while (a[i] < key);
do {
j--;
} while (a[j] > key);
if (i < j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
quick_sort(a, l, j);
quick_sort(a, j + 1, r);
}
//邻接表排序
void aListsort(int x)
{
if (graph[x] == NULL)return;
//链表转换为数组
int a[N], idx = 0;
Node* curr = graph[x];
while (curr != NULL)
{
a[idx++] = curr->vertex;
curr = curr->next;
}
//邻接表排序快排
quick_sort(a, 0, idx - 1);
//数组转换为链表
curr = graph[x];
for (int i = 0;i < idx;i++)
{
curr->vertex = a[i];
curr = curr->next;
}
}
4、打印显示结果查看
直接给看代码
//显示结果
void print(int x)
{
if (graph[x] == NULL)return;
Node* curr = graph[x];
printf("%d: ", x);
while (curr != NULL)
{
printf("%d->", curr->vertex);
curr = curr->next;
}
printf("NULL\n");
}
展示所有代码
.h文件写的
#pragma once
#include <stdio.h>
#include <stdlib.h>
#define N 100005
typedef struct Node {
int vertex;
//存储的是当前这条边指向的目标节点编号
// 例如1->2,存储的是2
// 例如:1指向2存的就是2,再来1指向3,存储的就是3
struct Node* next;
//指向同一个起始节点的下一条出边的节点。
// 例如:1->2,1->3.1->4
// ->就是节点
// 起始节点1
// 下一条出边:就是当前2存储了,下次要存3这个编号的节点
// 例如;1—>2(现在存好了),假设下一个要存1—>3,虽然没有存到3,但是已经拉出来了这个->节点为存3做出了准备
} Node;
extern Node* graph[N];
void add(int x, int y);
void aListsort(int x);
void print(int x);
.c文件
#include "aList.h"
Node* graph[N];
//添边
void add(int x, int y)
{
Node* newNode = (Node*)malloc(sizeof(Node));//申请一个结构体空间
if (newNode == NULL)
{
//如果申请失败就退出,并且打印出哪里的问题
printf("malloc fail!");
return;
}
//添边操作
newNode->vertex = y;
newNode->next = graph[x];
graph[x] = newNode;
}
//快排模板
void quick_sort(int a[], int l, int r)
{
if (l >= r)return;
int key = a[l], i = l - 1, j = r + 1;
while (i < j)
{
do {
i++;
} while (a[i] < key);
do {
j--;
} while (a[j] > key);
if (i < j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
quick_sort(a, l, j);
quick_sort(a, j + 1, r);
}
//邻接表排序
void aListsort(int x)
{
if (graph[x] == NULL)return;
//链表转换为数组
int a[N], idx = 0;
Node* curr = graph[x];
while (curr != NULL)
{
a[idx++] = curr->vertex;
curr = curr->next;
}
//邻接表排序快排
quick_sort(a, 0, idx - 1);
//数组转换为链表
curr = graph[x];
for (int i = 0;i < idx;i++)
{
curr->vertex = a[i];
curr = curr->next;
}
}
//显示结果
void print(int x)
{
if (graph[x] == NULL)return;
Node* curr = graph[x];
printf("%d: ", x);
while (curr != NULL)
{
printf("%d->", curr->vertex);
curr = curr->next;
}
printf("NULL\n");
}
最后测试.c
#include "aList.h"
Node* graph[N];
void test()
{
int n, m;
scanf_s("%d%d", &n, &m);
//初始化
for (int i = 1;i <= n;i++)
{
graph[i] = NULL;
}
while (m--)
{
int x, y;
scanf_s("%d%d", &x, &y);
add(x, y);
}
for (int i = 1;i <= n;i++)
{
aListsort(i);
}
for (int i = 1;i <= n;i++)
{
print(i);
}
}
int main()
{
test();
return 0;
}
最后给大家的数据自己写完就测试一下对不对吧!
8 9
1 2
1 3
1 4
2 5
2 6
3 7
4 7
4 8
7 8

更多推荐



所有评论(0)