int* adjacent_mat(int v, int e, int direct)
{
int* mat = (int*)malloc(sizeof(int) * v * v); //分配空间
if (!mat) return NULL;
int i, start, end, weight;
for (i = 0; i < v * v; i++)
mat[i] = INF; //节点全部初始化为无穷大(设无穷为65535)
for (i = 0; i < e; i++) //输入边信息
{
printf("输入起始 终止 权值:");
scanf_s("%d %d %d", &start, &end, &weight);
direct == 0 ? mat[start * v + end] = mat[end * v + start] = weight : mat[start * v + end] = weight; //direct=0时生成无向图,对称赋值;等于1生成有向图
}
for (i = 0; i < v * v; i++) {
mat[i] == INF ? printf("0 ") : printf("%d ", mat[i]);
if ((i + 1) % v == 0)
printf("\n");
}
return mat;
}
2.2邻接表
适用于稀疏矩阵
对每个节点建立一个链表,把与之相连的点存入节点,连接起来
一个图的邻接矩阵唯一,邻接表不唯一 每个节点的链表的结构
无向图的邻接表,顶点的度=该节点链表子结点个数:
有向图的邻接表和逆邻接表:
空间复杂度(n+e) 点数加边数
代码:
cpp复制代码
node* adjacency_list(int v, int e, int direct)
{
headnode* headlist = (headnode*)malloc(sizeof(headnode) * v);
if (!headlist) return NULL;
int i;
for (i = 0; i < v; i++)
{
headlist[i].data = i;
headlist[i].next = NULL;
}
int start, end, weight;
node* p, * newnode;
for (i = 0; i < e; i++)
{
printf("输入起始 终止 权值:");
scanf_s("%d %d %d", &start, &end, &weight);
if (direct != 2)
{
newnode = (node*)malloc(sizeof(node));
newnode->adjvex = newnode->data = end;
newnode->next = NULL;
p = headlist[start].next;
if (!p) {
headlist[start].next = newnode;
}
else {
while ((p->next) != NULL)
p = p->next;
p->next = newnode;
}
}
if (direct == 0 || direct == 2)
{
newnode = (node*)malloc(sizeof(node));
newnode->adjvex = newnode->data = start;
newnode->next = NULL;
p = headlist[end].next;
if (!p) {
headlist[end].next = newnode;
}
else {
while ((p->next) != NULL)
p = p->next;
p->next = newnode;
}
}
}
for (i = 0; i < v; i++) {
printf("%d:", headlist[i].data);
p = headlist[i].next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
}
2.3十字链表
考试没要求,先不写
三、图的遍历
图的遍历是从给定的源点出发,每个节点仅访问一次
基本算法有深度遍历和广度遍历两种
3.1深度优先DFS
沿着一条路一直走,没路了再回头找最近的分岔路口
如上图,从v1开始DFS,可得到v1-v2-v4-v8-v5-v3-v6-v7
cpp复制代码
void DFS(int*mat, int v, int num, int*& visited) //深度优先,递归版。需要传入邻接矩阵,点数,起始点编号,已访问数组
{
printf("%d", num); //输出起始节点
visited[num] = 1; //标记起始节点
for (int i = 0; i < v; i++) //在起始节点这一行从头搜索未遍历过的邻接点,进行递归
if (!visited[i] && mat[num * v + i] != INF)
DFS(mat, v, i, visited);
}
void DFS2(int* mat, int v)
{
int head = 0, i;
int* stack = (int*)malloc(sizeof(int) * v); //创建栈
if (!stack) return;
int* visited = (int*)malloc(sizeof(int) * v); //创建标记数组,初始化为0
if (!visited) return;
for (i = 0; i < v; i++)
visited[i] = 0;
int num;
printf("输入开始节点编号:");
scanf_s("%d", &num);
//循环中,入栈在最后,所以先入栈一个点
stack[head++] = num; //入栈,标记, 输出
visited[num] = 1;
printf("%d", num);
int temp;
while (head) //栈空时结束
{
temp = stack[head - 1]; //获取栈顶
for (i = 0; i < v; i++) //对栈顶对应的邻接矩阵所在行进行遍历,有未标记且相邻的就赋值退出,找不到则退栈
{
if (visited[i] == 0 && mat[temp * v + i] != INF) {
temp = i;
break;
}
}
if (i == v) //找不到退栈,找到入栈
head--;
else {
stack[head++] = i;
visited[i] = 1;
printf("%d", i);
}
}
}
void DFS3(int* mat, int v)
{
int top = -1, i;
int* stack = (int*)malloc(sizeof(int) * v); //创建栈
if (!stack) return;
int* visited = (int*)malloc(sizeof(int) * v); //创建标记数组,初始化为0
if (!visited) return;
for (i = 0; i < v; i++) //标记数组初始化为0
visited[i] = 0;
int num;
printf("输入开始节点编号:");
scanf_s("%d", &num);
//循环中,入栈在最后,所以先入栈一个点
stack[++top] = num; //入栈,top指向栈顶元素
visited[num] = 1; //标记
int temp;
while (top >= 0) //栈空时结束
{
temp = stack[top]; //获取栈顶
printf("%d", temp);
for (i = 0; i < v; i++) //对栈顶对应的邻接矩阵所在行进行遍历,有未标记且相邻的就赋值退出,找不到则退栈
{
if (visited[i] == 0 && mat[temp * v + i] != INF) {
stack[++top] = i;
visited[i] = 1;
break;
}
}
if (i == v) //该节点所有相邻节点访问完毕,退栈
top--;
}
}