目录
前言
此专栏包含408考研数据结构全部内容,除其中使用到C++引用外,全为C语言代码。使用C++引用主要是为了简化指针的使用,避免二重指针的出现。
已完成内容
[数据结构]:01-顺序表(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:02-单链表(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:03-栈(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:04-循环队列(数组)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:05-循环队列(链表)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:06-队列(链表带头结点)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:07-二叉树(无头结点)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:08-顺序查找(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:09-二分查找(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:10-二叉排序树(无头结点)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:11-冒泡排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:12-快速排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:13-插入排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:14-选择排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:15-堆排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:16-归并排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:17-双链表(带头结点)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:18-链栈(不带头结点)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:19-串KMP模式匹配(数组)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:20-线索二叉树(无头结点)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:21-并查集(数组)(C语言实现)_Chandni.的博客-CSDN博客
[数据结构]:22-图(邻接矩阵)(C语言实现)_Chandni.的博客-CSDN博客
图实现
01-开发环境
语言:C/C++14
编译器:MinGW64
集成开发环境:CLion2022.1.3
02-文件布局
请在CLion集成开发环境中创建C++可执行程序,否则无法运行,原因上面已解释。
03-代码
01-主函数
用于测试。
// 默认为无向图,若为有向图或网,请适当修改
#include "./Head/AdjList.h"
#include "./Source/AdjListCommon.cpp"
#include "./Source/AdjListFunction.cpp"
int main() {
ALGraph AdjList;
InitGraph(AdjList);
CreateGraph(AdjList);
PrintGraph(AdjList);
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 判断两结点是否存在某边
if (Adjacent(AdjList, 0, 1)) {
printf("true\n");
} else {
printf("false\n");
}
if (Adjacent(AdjList, 2, 3)) {
printf("true\n");
} else {
printf("false\n");
}
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 列出与x邻接的边
int Edge[MAXSIZE] = {-1, -1, -1, -1, -1};
Neighbors(AdjList, 0, Edge);
for (int i = 0; Edge[i] != -1; i++) {
printf("%3d", Edge[i]);
}
printf("\n");
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 删除顶点
DeleteVertex(AdjList, 0);
PrintGraph(AdjList);
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 添加顶点
InsertVertex(AdjList, 4);
// 添加边
AddEdge(AdjList, 1, 4);
PrintGraph(AdjList);
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 删除边
RemoveEdge(AdjList, 0, 1); // 不执行
RemoveEdge(AdjList, 1, 2);
PrintGraph(AdjList);
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 寻找第一个邻接点
int Neighbor = FirstNeighbor(AdjList, 1);
printf("FirstNeighbor = %d\n", Neighbor);
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
// 寻找除4之外的下一个邻接点
Neighbor = NextNeighbor(AdjList, 1, 4);
printf("FirstNeighbor = %d\n", Neighbor);
printf("VertexNum = %d,ArcNum = %d\n", AdjList.VexNum, AdjList.ArcNum);
printf("-----------------------------------\n");
return 0;
}
02-头文件
用于存储结构体和常量等。
//
// Created by 24955 on 2023-04-02.
// 默认为无向图,若为有向图或网,请适当修改
//
#ifndef INC_01_ADJACENTList_ADJList_H
#define INC_01_ADJACENTList_ADJList_H
// 头文件
#include <stdio.h>
#include <stdlib.h>
// 常量
#define MAXSIZE 5
typedef int VertexType;
typedef int EdgeType;
// 结构体-弧结点
typedef struct ArcNode {
VertexType AdjVertex;
struct ArcNode *next;
} ArcNode;
// 结构体-顶点
typedef struct {
VertexType data;
ArcNode *first;
} VertexNode, AdjL[MAXSIZE];
// 结构体-图
typedef struct {
AdjL AdjList;
int VexNum, ArcNum;
} ALGraph;
#endif //INC_01_ADJACENTList_ADJList_H
03-AdjListCommon.cpp
用于存储初始化图、输出图等操作。
//
// Created by 24955 on 2023-04-02.
// 默认为无向图,若为有向图或网,请适当修改
//
// 初始化图
void InitGraph(ALGraph &Graph) {
// 初始化顶点和边表
for (int i = 0; i < MAXSIZE; i++) {
Graph.AdjList[i].data = -1;
Graph.AdjList[i].first = NULL;
}
Graph.VexNum = 0;
Graph.ArcNum = 0;
}
// 创建图 - 主要方便测试,并非图的正确创建方式,应根据具体情况具体分析
void CreateGraph(ALGraph &Graph) {
Graph.VexNum = 4;
ArcNode *arcNode[4];
for (int i = 0; i < Graph.VexNum; i++) {
Graph.AdjList[i].data = i;
ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
p->AdjVertex = i;
p->next = NULL;
arcNode[i] = p;
}
// 无向图
/*
* 1. 0->1->3
* 2. 1->0->2
* 3. 2->1
* 4. 3->0*/
Graph.AdjList[0].first = arcNode[1];
arcNode[1]->next = arcNode[3];
Graph.AdjList[1].first = arcNode[0];
arcNode[0]->next = arcNode[2];
// 顶点1已经使用过,应重新申请空间
ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
p->AdjVertex = 1;
p->next = NULL;
Graph.AdjList[2].first = p;
ArcNode *p1 = (ArcNode *) malloc(sizeof(ArcNode));
p1->AdjVertex = 0;
p1->next = NULL;
Graph.AdjList[3].first = p1;
Graph.ArcNum = 3;
}
// 输出邻接矩阵
void PrintGraph(ALGraph Graph) {
for (int i = 0; i < MAXSIZE; i++) {
printf("%2d\t", Graph.AdjList[i].data);
ArcNode *p = Graph.AdjList[i].first;
while (p) {
printf("%2d", p->AdjVertex);
p = p->next;
}
printf("\n");
}
}
04-AdjListFunction.cpp
用于存储图的基本操作。
//
// Created by 24955 on 2023-04-02.
// 默认为无向图,若为有向图或网,请适当修改
//
// 获取元素下标
int GetIndex(ALGraph Graph, VertexType x) {
/*
* 1. 获取元素真实下标*/
int xIndex = -1;
for (int i = 0; i < MAXSIZE; i++) {
if (Graph.AdjList[i].data == x) {
xIndex = i;
break;
}
}
return xIndex;
}
// 判断图中是否存在边<x,y>
bool Adjacent(ALGraph Graph, VertexType x, VertexType y) {
/*
* 1. 判断x->y是否存在边
* 2. 存在返回true*/
// 避免访问到不存在顶点
if (x >= MAXSIZE || y >= MAXSIZE) {
return false;
}
int xIndex = GetIndex(Graph, x);
ArcNode *p = Graph.AdjList[xIndex].first;
while (p) {
if (p->AdjVertex == y) {
return true;
}
p = p->next;
}
return false;
}
// 列出图中与顶点x邻接的边
void Neighbors(ALGraph Graph, VertexType x, int *Edge) {
/*
* 1. 遍历x所在行
* 2. 用数组存储与之邻接的边另一个顶点*/
int xIndex = GetIndex(Graph, x);
// 未找到顶点x
if (xIndex == -1) {
return;
}
// 找到顶点x,统计x邻接顶点
ArcNode *p = Graph.AdjList[xIndex].first;
for (int i = 0; p; i++) {
Edge[i] = p->AdjVertex;
p = p->next;
}
}
// 插入顶点x
void InsertVertex(ALGraph &Graph, VertexType x) {
/*
* 1. 插入,顶点个数+1*/
if (Graph.VexNum == MAXSIZE) {
return;
}
for (int i = 0; i < MAXSIZE; i++) {
if (Graph.AdjList[i].data == -1) {
Graph.AdjList[i].data = x;
break;
}
}
Graph.VexNum++;
}
// 删除边表某结点
void DeleteArcNode(ALGraph &Graph, int xIndex, VertexType x) {
ArcNode *pre = Graph.AdjList[xIndex].first, *p;
if (pre == NULL) {
return;
}
// 若为第一个元素
if (pre->AdjVertex == x) {
Graph.AdjList[xIndex].first = pre->next;
free(pre);
} else {
// 不是第一个元素
p = pre->next;
while (p) {
if (p->AdjVertex == x) {
pre->next = p->next;
free(p);
break;
}
p = p->next;
}
}
}
// 删除顶点x
void DeleteVertex(ALGraph &Graph, VertexType x) {
/*
* 1. 清除顶点,并修改顶点个数
* 2. 清除边,并修改边个数*/
// 清除顶点,将其值设为-1表示该顶点为空,并清除相应边
int xIndex = GetIndex(Graph, x);
if (xIndex == -1) {
return;
}
ArcNode *p = Graph.AdjList[xIndex].first;
while (p) {
DeleteArcNode(Graph, xIndex, p->AdjVertex);
p = Graph.AdjList[xIndex].first;
Graph.ArcNum--;
}
Graph.AdjList[xIndex].data = -1;
Graph.VexNum--;
// 清除其余边
for (int i = 0; i < MAXSIZE; i++) {
if (Graph.AdjList[i].data != -1) {
DeleteArcNode(Graph, i, x);
}
}
}
// 在边表中插入某顶点-尾部插入(也可头部插入)
void AddArcNode(ALGraph &Graph, int xIndex, VertexType x) {
ArcNode *NewNode = (ArcNode *) malloc(sizeof(ArcNode));
NewNode->AdjVertex = x;
NewNode->next = NULL;
ArcNode *p = Graph.AdjList[xIndex].first;
if (p == NULL) {
Graph.AdjList[xIndex].first = NewNode;
} else {
while (p->next) {
p = p->next;
}
p->next = NewNode;
}
// 头部插入
// NewNode->next = Graph.AdjList[xIndex].first;
// Graph.AdjList[xIndex].first = NewNode;
}
// 添加边
void AddEdge(ALGraph &Graph, VertexType x, VertexType y) {
/*
* 1. 获取顶点值实际下标
* 2. 插入边*/
int xIndex = GetIndex(Graph, x);
int yIndex = GetIndex(Graph, y);
if (xIndex == -1 || yIndex == -1) {
return;
}
// 添加边
AddArcNode(Graph, xIndex, y);
AddArcNode(Graph, yIndex, x);
Graph.ArcNum++;
}
// 删除边
void RemoveEdge(ALGraph &Graph, VertexType x, VertexType y) {
/*
* 1. 获取顶点值实际下标
* 2. 删除边*/
int xIndex = GetIndex(Graph, x);
int yIndex = GetIndex(Graph, y);
if (xIndex == -1 || yIndex == -1) {
return;
}
// 删除边
DeleteArcNode(Graph, xIndex, y);
DeleteArcNode(Graph, yIndex, x);
Graph.ArcNum--;
}
// 寻找图中顶点x的第一个邻接点
int FirstNeighbor(ALGraph Graph, VertexType x) {
/*
* 1. 寻找第一个不为0的值,并返回顶点值*/
int xIndex = GetIndex(Graph, x);
if (xIndex == -1) {
return -1;
}
ArcNode *p = Graph.AdjList[xIndex].first;
if (p != NULL) {
return p->AdjVertex;
}
return -1;
}
// 图的下一个邻接点-除y以外的下一个邻接点顶点号
int NextNeighbor(ALGraph Graph, VertexType x, VertexType y) {
/*
* 1. 寻找y之后第一个不为0的值,并返回顶点值*/
int xIndex = GetIndex(Graph, x);
if (xIndex == -1) {
return -1;
}
// 寻找y之后的下一个邻接点
ArcNode *p = Graph.AdjList[xIndex].first;
while (p) {
if (p->AdjVertex == y) {
break;
}
p = p->next;
}
if (p) {
p = p->next;
if (p) {
return p->AdjVertex;
}
}
return -1;
}
结语
此博客主要用于408考研数据结构C语言实现记录,内有不足,可留言,可讨论。