idk why these stuffs get stashed for so long and I didn't ever commit them

This commit is contained in:
2025-11-06 09:43:54 +08:00
parent 5dbdfef1a1
commit e01c041259
232 changed files with 22806 additions and 1256 deletions

View File

@@ -0,0 +1,132 @@
//#include<string>
#include <iostream>
#include "ALGraph.h"
#include "LinkQueue.h"
using namespace std;
void DispMenu()
{
cout<<"\n请选择你要的操作"<<endl;
cout<<" 1. 建立无向图"<<endl;
cout<<" 2. 图的连通信息"<<endl;
cout<<" 3. 求顶点v最远点"<<endl;
cout<<" 4. 显示图"<<endl;
cout<<" 0. 退出"<<endl;
}
//算法6.16
template<class DT>
void DFS3(ALGraph<DT> G,int v) // 连接表存储的图的深度优先遍历
{
int w;
ArcNode* p;
visited[v]=true; // 做访问标志
cout<<G.vertices[v].data; // 输出顶点
p=G.vertices[v].firstarc; // 找第一未访问邻接点
while(p) // 顶点非空
{
w=p->adjvex; // 未被访问过
if(!visited[w])
DFS3(G,w); // DFS遍历
p=p->nextarc; // 新启点DFS遍历
}
}
template<class DT>
void ConnectVex(ALGraph<DT> G) // 图的连通信息
{
int k,num=0; // num连通分量计数
for(k=0;k<G.vexnum;k++) // 访问标志初始化
visited[k]=false;
for(k=0;k<G.vexnum;k++) // 连通图遍历调用次数为连通分量数
if(!visited[k])
{
num++;
cout<<"\n"<<num<<"个连通分量序列为:";
DFS3(G,k);
}
}
// 算法6.17 求距离最远顶点
template<class DT>
int Maxdist( ALGraph<DT> G, int v)
{
int i,w;
ArcNode *p;
LinkQueue<int> Q; // 创建一个队列
InitQueue(Q);
for(i=0;i<G.vexnum;i++) // 访问标志初始化
visited[i]=false;
EnQueue(Q,v); // v入队
visited[v]=true; // 做访问标志
while(!QueueEmpty(Q)) // 队不空
{
DeQueue(Q,v); // 出队
p=G.vertices[v].firstarc; // 遍历 v 的邻接点
while(p)
{
w=p->adjvex;
if(!visited[w]) // 未被访问
{
visited[w]=true; // 做访问标志
EnQueue(Q,w); // 入队
}
p=p->nextarc; // 下一个邻接点
}
}
return v;
}
bool visited[MAX_VEXNUM]={false};
void main()
{
char u,v;
int k;
ALGraph<char> G;
int choice;
do
{
DispMenu();
cin>>choice;
switch(choice)
{
case 1: // 创建无向图
CreateUDG(G);
cout<<endl;
cout<<"创建的图为:"<<endl;
DispG(G);
break;
case 2: // 图的连通信息
ConnectVex(G);
cout<<endl;
break;
case 3: // 求距离最远顶点
cout<<"\n输入顶点信息v:"<<endl;
cin>>v;
k=LocateVex(G,v);
if(k==-1)
cout<<"\n顶点"<<v<<"不存在!"<<endl;
else
{
k=Maxdist(G, k);
GetVex(G,k,u);
cout<<""<<v<<"的最远点为"<<u<<endl;
}
break;
case 4: // 显示图
DispG(G);
cout<<endl;
break;
case 0:
cout<<"\n结束运行Bye-Bye!"<<endl;
break;
default:
cout<<"\n无效选择,请重选!"<<endl;
}
}while(choice!=0);
}

View File

@@ -0,0 +1,405 @@
/*----------------------图的邻接表示存储------------------------*/
//无向图
#define MAX_VEXNUM 20 // 最大顶点数
struct ArcNode{
int adjvex; // 该弧所指向的顶点的位置
ArcNode *nextarc; // 指向下一条弧的指针
};
template <class DT>
struct VNode{
DT data; // 顶点信息
ArcNode *firstarc; // 指向第一条依附该顶点的指针
};
template <class DT>
struct ALGraph{
VNode<DT> vertices[MAX_VEXNUM]; //顶点集
int vexnum;//顶点数
int arcnum;//边数
};
template <class DT>
void DispG(ALGraph<DT> G)
{
int i;
ArcNode *p;
cout<<G.vexnum<<"个顶点:"<<endl; //输出顶点
for(i=0;i<G.vexnum;i++)
{
cout<<G.vertices[i].data<<" ";
}
cout<<endl;
cout<<G.arcnum<<"条弧(边):"<<endl;
for(i = 0;i<G.vexnum;i++)
{
p = G.vertices[i].firstarc;
while(p)
{
if(i<p->adjvex) //避免了无向的时候一条边被输出两次
{
cout<<"("<<G.vertices[i].data<<","
<<G.vertices[p->adjvex].data<<")"<<'\t';
}
p = p->nextarc;
}
}
cout<<endl;
}
//算法6.4 顶点定位
template <class DT>
int LocateVex(ALGraph<DT> G, DT v)
{
for(int i=0;i<G.vexnum;i++)
{
if(G.vertices[i].data == v)
{
return i;
}
}
return -1;
}
//算法6.5 创建无向图
template <class DT>
void CreateUDG(ALGraph<DT> &G)
{
int i,j,k;
DT v1,v2;
ArcNode *p;
cout<<"请输入无向图的顶点数 "; // 1. 输入顶点数、边数
cin>>G.vexnum ;
cout<<"请输入无向图的边数 ";
cin>>G.arcnum ;
cout<<"请输入"<<G.vexnum<<"个顶点的值"<<endl; // 2. 输入顶点值
for(i = 0;i<G.vexnum;i++) // 初始化顶点结点
{
cin>>G.vertices[i].data;
G.vertices[i].firstarc = NULL;
}
for(k=0;k<G.arcnum;k++) //构造表结点链表
{
cout<<"请输入边的两个顶点值: "<<endl;
cin>>v1>>v2;
i = LocateVex(G,v1);
j = LocateVex(G,v2);
if(i<0 || j<0 || i==j)
{
cout<<"顶点信息错,重新输入!"<<endl;
k--;
continue;
}
p = new ArcNode; // 创建一个新的边
p->adjvex = j;
p->nextarc = G.vertices[i].firstarc; // 在v1链表表头插入新边结点
G.vertices[i].firstarc = p;
p = new ArcNode; // 创建一个新的边
p->adjvex = i;
p->nextarc = G.vertices[j].firstarc; // 在v2链表表头插入新边结点
G.vertices[j].firstarc = p;
}
}
template <class DT>
void DestroyGraph(ALGraph<DT> G) // 销毁边结点
{
int i;
ArcNode *p,*q;
for(i = 0;i<G.vexnum;i++) // 从顶点序号为0的顶点开始依次释放掉相应的邻接表
{
p = G.vertices[i].firstarc;
while(p)
{
q = p->nextarc;
delete p; // 删除边结点
p = q;
}
}
G.arcnum = 0;
G.vexnum = 0;
}
template <class DT>
bool GetVex(ALGraph<DT> G, int k,DT &v) // 获取第 k 个顶点的值
{
if(k<0||k>=G.vexnum) // 顶点不存在返回false
return false;
v=G.vertices[k].data; // 顶点存在,获取第 k 个顶点的值
return true; // 返回true
}
template <class DT>
bool PutVex(ALGraph<DT> &G, DT &u,DT v) // 修改顶点 u 的值
{
int k = LocateVex(G,u);
if(k<0) // 顶点 u 不存在
return false;
G.vertices[k].data = v; // 重置顶点u的值
return true;
}
template <class DT>
int FirstAdjVex(ALGraph<DT> G, int u) // 求顶点 u 的第一个邻接点
{
ArcNode * p;
if(u<0 || u>=G.vexnum) // 顶点 u 不存在
return -1;
p = G.vertices[u].firstarc; // 顶点u存在有邻接点p 为第一个邻接点位序
if(p)
{
return p->adjvex;
}
else
{
return -1;
}
}
template <class DT>
int NextAdjVex(ALGraph<DT> G, int u,int w) // 求顶点 u 相对于 w 的下一个邻接点
{
ArcNode *p;
if(u<0 || u>=G.vexnum || w<0
|| w>=G.vexnum ) // 参数不合理
return -1;
p = G.vertices[u].firstarc; // 从 u 的边链表出发
while( p && (p->adjvex!=w)) // 找 w 边结点
{
p = p->nextarc;
}
if(!p||!p->nextarc) // 没找到 w 或 w 是最后一个顶点
return -1;
else // 否则,返回下一个邻接点位序
{
return p->nextarc->adjvex;
}
}
template <class DT>
bool InsertVex(ALGraph<DT> &G, DT v) // 增加顶点
{
int j;
char ans;
DT w;
if(G.vexnum > MAX_VEXNUM) // 顶点数为最多顶点数,不能增加新顶点
{
cout<<"无存储空间,不能插入!"<<endl;
return false;
}
G.vertices[G.vexnum].data = v; // 在顶点信息表中新增顶点
G.vertices[G.vexnum].firstarc = NULL;
G.vexnum++; // 顶点数增1
cout<<"创建边吗Y/N)?"<<endl; // 创建顶点相关的边
cin>>ans;
while(ans=='Y'|| ans=='y')
{
cout<<"输入另一个顶点值:"<<endl; // 输入边另一相邻顶点
cin>>w;
j=LocateVex(G,w);
if(j>=0) // 顶点存在,增加边
InsertArc(G,v,w);
else
cout<<w<<"\n顶点不存在!";
cout<<"继续创建边吗Y/N)?"<<endl;
cin>>ans;
};
return true;
}
template <class DT>
bool InsertArc(ALGraph<DT> &G, DT v,DT w) // 增加边(v,w)
{
ArcNode *p;
int i,j;
i = LocateVex(G,v);
j = LocateVex(G,w);
if(i<0||j<0 || i==j) // 顶点不存在或两端点相同,不能插入
{
cout<<"\n顶点不存在或两顶点相同,不能插入!"<<endl;
return false;
}
p=G.vertices[i].firstarc; // 边已存在,不能新增
while(p)
{
if(p->adjvex==j)
{
cout<<"边存在,不能插入!"<<endl;
return false;
}
p=p->nextarc;
}
G.arcnum++; // 边数增 1
p = new ArcNode;
p->adjvex = j;
p->nextarc = G.vertices[i].firstarc; // (v,w)边结点插在第i条链表表头
G.vertices[i].firstarc = p;
p = new ArcNode;
p->adjvex = i; // (w,v)边结点插在第j链表表头
p->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p;
return true;
}
template <class DT>
bool DeleteArc(ALGraph<DT> &G, DT v,DT w) // 删除边(v,w)
{
ArcNode *p,*q;
int i,j;
cout<<"Hello DeleteArc!"<<endl;
cout<<"删除边顶点为:"<<endl;
cout<<"("<<v<<","<<w<<")"<<endl;
i = LocateVex(G,v);
j = LocateVex(G,w);
if(i<0||j<0||i == j) // 边(v,w)不存在,不能删除
{
cout<<"\n边不存在!"<<endl;
return false;
}
p = G.vertices[i].firstarc; // 寻找边(v,w)的边结点
while(p && p->adjvex!=j) // p 不空且 p 指向的不是待删弧结点
{
q = p;
p = p->nextarc;
}
if(p&&p->adjvex ==j) // 找到边(v,w)
{
if(p == G.vertices[i].firstarc) // 第 1 个边结点
{
G.vertices[i].firstarc = p->nextarc;
}
else // 非第 1 个边结点
{
q->nextarc = p->nextarc;
}
delete p;
G.arcnum--;
p = G.vertices[j].firstarc;
while(p&&p->adjvex!=i) // p不空且q指向的不是待删弧结点
{
q = p;
p = p->nextarc;
}
if(p == G.vertices[j].firstarc) // 第 1 个边结点
{
G.vertices[j].firstarc = p->nextarc;
}
else // 非第1个边结点
{
q->nextarc = p->nextarc;
}
delete p;
}
cout<<"Bye-bye DeleteArc!"<<endl;
return true;
}
template <class DT>
bool DeleteVex(ALGraph<DT> &G, DT v) // 删除顶点v
{
int i,j;
ArcNode *p;
DT w;
i = LocateVex(G,v);
if(i<0)
{
cout<<"顶点不存在!"<<endl; // 顶点不存在
return false;
}
p = G.vertices[i].firstarc;
while(p) // 删除以 v 为邻接点边
{
j=p->adjvex;
GetVex(G,j,w);
DeleteArc(G,v,w);
p=G.vertices[i].firstarc;
}
for(j=i+1;j<G.vexnum;j++) // 顶点v后面的顶点前移
{
G.vertices[j-1].data = G.vertices[j].data;
G.vertices[j-1].firstarc=G.vertices[j].firstarc;
}
G.vexnum--; // 顶点数减一
return true;
}
// 算法6.8
template <class DT>
void DFS(ALGraph<DT> G, int v) // 连通图的深度优先遍历
{
int w;
visited[v] = true; // 标识已访问
cout<<G.vertices[v].data; // 访问顶点
for(w = FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)) // 遍历v的邻接点w
{
if(!visited[w]) // 未访问调用DFS
DFS(G,w);
}
}
// 算法6.9
template <class DT>
void DFSTraverse(ALGraph<DT> G) // 邻接表存储的图的深度优先遍历
{
int i ;
for(i = 0;i<G.vexnum;i++) // 初始化访问标志
visited[i] = false;
for(i = 0;i<G.vexnum;i++) // 对每个未被访问的顶点进行DFS
{
if(!visited[i])
DFS(G,i);
}
return;
}
// 算法6.13
template <class DT>
void BFS(ALGraph<DT> G, int v) // 连通图的广度优先遍历
{
int w;
ArcNode *p;
LinkQueue<int> Q;
InitQueue(Q);
cout<<G.vertices[v].data;
visited[v]=true;
EnQueue(Q,v);
while(!QueueEmpty(Q))
{
DeQueue(Q,v);
p=G.vertices[v].firstarc;
while(p)
{
w=p->adjvex;
if(!visited[w])
{
cout<<G.vertices[w].data;
visited[w]=true;
EnQueue(Q,w);
}
p=p->nextarc;
}
}
}
template <class DT>
bool BFSTraverse(ALGraph<DT> G) // 邻接表存储的图的广度优先遍历
{
int i;
for(i = 0;i<G.vexnum;i++) // 初始化访问标志
visited[i] = false;
for(i = 0;i<G.vexnum;i++) // 对每个未被访问的顶点进行BFS
if(!visited[i])
BFS(G,i);
//cout<<endl;
return true;
}

View File

@@ -0,0 +1,112 @@
template <class DT>
struct QNode //结点
{
DT data; //数据域,存储数据元素值
QNode *next;//指针域,指向下一个结点
};
template<class DT>
struct LinkQueue
{
QNode<DT> * front;
QNode<DT> * rear;
};
//【算法3.19】
template <class DT>
void InitQueue(LinkQueue<DT> &Q)//创建空队列
{
Q.front=new QNode<DT>; //创建头结点
if(!Q.front) exit(1); //创建失败,结束运行
Q.front->next=NULL;
Q.rear=Q.front;
}
//【算法3.20】
template <class DT>
void DestroyQueue(LinkQueue<DT> &Q)//释放链队
{
QNode<DT> *p;
while(Q.front)//从头结点开始,依次释放结点
{
p=Q.front;
Q.front=Q.front->next;
delete p;
}
}
//【算法3.21】 入队
template<class DT>
bool EnQueue(LinkQueue<DT> &Q,DT e)
{
QNode<DT> *p;
p=new QNode<DT>; // 创建新结点
if(!p) return false; // 创建失败,结束运行
p->data=e; // 新结点赋值
p->next=NULL; // 链在队尾
Q.rear->next=p;
Q.rear=p;
return true; // 入队成功返回true
}
//【算法3.22】 出队
template<class DT>
bool DeQueue(LinkQueue<DT> &Q,DT &e)
{
QNode<DT> *p;
if(Q.front==Q.rear) return false; //队空返回false
p=Q.front->next; // 取出队元素
e=p->data;
Q.front->next=p->next; //队首元素出队
if(Q.rear==p) //只有一个元素时出队,
Q.rear=Q.front; // 修改队尾
delete p;
return true; // 出队成功返回true
}
//【算法3.23】 取队头元素
template<class DT>
bool GetHead(LinkQueue<DT> Q,DT &e)
{
if(Q.front==Q.rear) return false; // 队空返回false
e=Q.front->next->data;
return true; // 删除成功返回true
}
//取队尾元素
template<class DT>
bool GetTail(LinkQueue<DT> Q,DT &e)
{
if(Q.front==Q.rear) // 队空
return false; // 返回false
e=Q.rear->data; // 获取队尾元素
return true; // 返回true
}
//测队空
template<class DT>
bool QueueEmpty(LinkQueue<DT> Q)
{
if(Q.front==Q.rear) // 队空
return true; //返回true
else //非空
return false; //返回false
}
//显示队列内容
template<class DT>
void DispQueue(LinkQueue<DT> Q)
{
QNode<DT> *p;
p=Q.front->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}