A. 关于数据结构中邻接表的问题
邻接表是图的一种链接存储结构。在邻接表中,对图中每个顶点建立一个带头结点的单链表,所有的头结点构成一个数组,第i个单链表中的结点表示依附于顶点vi的边。也就是说指的是点,表示的是边,因为两点决定了一条边。以下图为例:
与0号点相连的有2条边,一条与1号点相连,一条与3号点相连。所以v0后面有两个结点,前面的序号分别为1、3,3后没有了,为空;
与1号点相连的有3条边,分别与0、2、3号点相连。所以v0后面有3个结点,前面的序号分别为0、2、3,3后没有了,为空;
与2号点相连的有1条边,与1号点相连。所以v0后面有1个结点,前面的序号为1,1后没有了,为空。
对照图好好理解,应该能明白了。
B. 邻接表的存储定义 数据结构
structnode
{
intvalue;//你存放的变量
structnode*next;//邻接表
};
可以用结构体表示。
C. c语言 邻接矩阵和邻接表
/**********************邻接矩阵*****************/
#include<bits/stdc++.h>//邻接矩阵
using namespace std;
const int N=300;
int Map[N][N]={0};//邻接矩阵
int book[N]={0};//结点标记数组(1表示该点访问过了;0未访问过)
int n,m;
void dfs(int x)//深度遍历
{
for(int i=1;i<=n;i++)
{//book[i]==0:i未被访问过
// Map[x][i]==1:x到i有边连接
if(book[i]==0&&Map[x][i]==1)
{
book[i]=1;//访问标记
printf("->[%d]",i);
dfs(i);//前往下一个结点i
}
}
}
void bfs(int x)
{
int q[N]={0};
int fornt=0;
int rear=0;
q[rear++]=x;//源点入队
while(fornt<rear)
{
int k=q[fornt++];//出队
for(int i=1;i<=n;i++)
{//扩展一个点周围可以访问的点
if(book[i]==0&&Map[k][i]==1)
{
printf("->[%d]",i);
book[i]=1;//访问标记
q[rear++]=i;//入队
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);//n个结点,m条边
for(int i=0;i<m;i++)
{//构造无向图
int x,y;//输入2个结点;x->y;y->x;
scanf("%d%d",&x,&y);
Map[x][y]=1;//1代表x,y邻接
Map[y][x]=1;
}
book[1]=1;//标记结点1
printf("深度遍历路径 [%d]",1);
dfs(1);//从结点1深度遍历 (起始点可以随便选,1~n)
printf(" ");
memset(book,0,sizeof(book));//标记数组置0,用于广度遍历标记
printf("广度遍历路径 [%d]",1);
book[1]=1;//标记结点1
bfs(1);//从结点1广度遍历 (起始点可以随便选,1~n)
return 0;
}
/*5个结点,7条边
5 7
1 3
1 2
1 4
2 4
2 5
3 5
4 5
*/
/*************************邻接表*************************************/
#include<bits/stdc++.h>//万能头文件,C/C++都能用,包含了所有的头文件
using namespace std;//邻接表
const int N=300;
typedef struct st{
int v;//表头能到达的结点
struct st *next;//指向下一个结点的指针域
}*link,AK;//定义结点类型
struct sx{
AK *next;//表头指针域
}s[N];//n个结点,n个表头
int book[N]={0};//结点标记数组(1表示该点访问过了;0未访问过)
int n,m;
void create(int x,int y)
{//前插法构建邻接表
link p;
p=new AK;//开辟新结点
p->v=y;
p->next=s[x].next;
s[x].next=p;
}
void fun()
{//表头指针赋空(这一步至关重要,没有这一步无法建表)
for(int i=1;i<=n;i++)
s[i].next=NULL;
}
void dfs(int x)//深度遍历邻接表
{
link p=s[x].next;
while(p)
{
if(book[p->v]==0)
{
printf("->[%d]",p->v);
book[p->v]=1;
dfs(p->v);
}
p=p->next;
}
}
void bfs(int x)//广度遍历邻接表
{
int q[N]={0};//队列
int fornt=0;
int rear=0;
q[rear++]=x;
while(fornt<rear)
{
int k=q[fornt++];
link p=s[k].next;
while(p)
{
if(book[p->v]==0)
{
printf("->[%d]",p->v);
book[p->v]=1;
q[rear++]=p->v;
}
p=p->next;
}
}
}
void input()//打印邻接表
{//首列是表头(其后尾随的是与其邻接的结点)
//n个表头
link p;
for(int i=1;i<=n;i++)
{
p=s[i].next;
printf("[%d]",i);
while(p)
{
printf("->[%d]",p->v);
p=p->next;
}
cout<<endl;
}
}
int main()
{
fun();//调用表头置空
scanf("%d%d",&n,&m);//n个结点,m条边
for(int i=0;i<m;i++)
{//构造无向邻接表
int x,y;//输入2个结点;x->y;y->x;
scanf("%d%d",&x,&y);
create(x,y);//构建有向邻接表,只调用一个;
create(y,x);//构建无向邻接表,只调用两个;
}
book[1]=1;//标记结点1
printf("深度遍历路径 [%d]",1);
dfs(1);//从结点1深度遍历 (起始点可以随便选,1~n)
printf(" ");
memset(book,0,sizeof(book));//标记数组置0,用于广度遍历标记
printf("广度遍历路径 [%d]",1);
book[1]=1;//标记结点1
bfs(1);//从结点1广度遍历 (起始点可以随便选,1~n)
printf(" ");
printf("打印邻接表结构 ");
input();//打印邻接表
return 0;
}
/*5个结点,7条边
5 7
1 3
1 2
1 4
2 4
2 5
3 5
4 5
*/
D. c语言,关于邻接表的建立
AdjList 是自定义类型,是char类型,
第二行 typedef将char类型自定义为 VertexType,即VertexType代表了char型,
VertexType a 就相当于 char a;
同理
倒数第五行 typedef将VertexNode自定义为 AdjList[MaxVertexNum]类型,也就是说现在AdjList就代表了一个 “结构体数组” 类型
AdjList adjlist 相当于 VertexNode adjlist[MaxVertexNum]
这里主要是typedef关键字的使用 希望能帮到你
E. c语言图的遍历,邻接表存储,深度,广度优先遍历
(1) 图的建立,按采用邻接表作为存储结构。
(2) 从指定顶点出发进行深度优先搜索遍历。
(3) 从指定顶点出发进行广度优先搜索遍历。
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"math.h"
#define MAX_INT 1000
#define MAX_VERTEX_NUM 20
#define MAX_QUEUE_NUMBER 20
typedef struct ArcNode
{
int adjvex;
double adj;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VexNode
{
char szName[40];
ArcNode *firstarc;
}VexNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vexs;
int vexnum,arcnum;
}Net;
//定义队列
typedef struct{
int *elem;
int front, rear;
}Queue;
void InitQueue(Queue &Q)
{
Q.elem = new int[MAX_QUEUE_NUMBER];
Q.front = Q.rear = 0;
}
int EmptyQueue(Queue Q)
{
if(Q.front==Q.rear)
return 0;
else
return 1;
}
void DestroyQueue(Queue &Q){
delete []Q.elem;
Q.front = Q.rear = 0;
}
void EnterQueue(Queue &Q, int e)
{
if((Q.rear + 1)%MAX_QUEUE_NUMBER != Q.front)
Q.elem[Q.rear ] = e;
else
printf("队列满!\n");
Q.rear = (Q.rear + 1)%MAX_QUEUE_NUMBER;
}
void LeaveQueue(Queue &Q, int &e)
{
if(Q.rear != Q.front)
e = Q.elem[Q.front];
else
printf("队列空!\n");
Q.front = (Q.front+1)%MAX_QUEUE_NUMBER;
}
int LocateVex(Net ga,char *name)
{
int i;
for(i=0;i<ga.vexnum;i++)
if(strcmp(name,ga.vexs[i].szName)==0)
return i;
return -1;
}
void crt_net(Net &ga)
{
ArcNode *p;
char name1[40],name2[40];
int i,j,k;
double w;
printf("请输入顶点数和弧数:");
scanf("%d%d",&ga.vexnum,&ga.arcnum);
printf("请依次输入顶点名:\n");
for(i=0;i<ga.vexnum;i++)
{
scanf("%s",ga.vexs[i].szName);
ga.vexs[i].firstarc=NULL;
}
for(k=0;k<ga.arcnum;k++)
{
printf("请输入相邻的两个定点和权值:");
scanf("%s%s%lf",name1,name2,&w);
i=LocateVex(ga,name1);
j=LocateVex(ga,name2);
p=new ArcNode;
p->adjvex=j;
p->adj=w;
p->nextarc=ga.vexs[i].firstarc;
ga.vexs[i].firstarc=p;
}
}
void DFS(Net ga,char *name,int *visited)
{
int v,w;
ArcNode *p;
v=LocateVex(ga,name);
visited[v]=1;
printf("%s ",ga.vexs[v].szName);
p=ga.vexs[v].firstarc;
while(p!=NULL)
{
w=p->adjvex;
if(visited[w]==0)
DFS(ga,ga.vexs[w].szName,visited);
p=p->nextarc;
}
}
void DFSTravel(Net ga,char *name)
{
int v,k=0;
int visited[20];
for(v=0;v<ga.vexnum;v++)
visited[v]=0;
for(v=LocateVex(ga,name);k!=2;v=(v+1)%(ga.vexnum-1))
{
if(v+1==LocateVex(ga,name))
k++;
if(visited[v]==0)
DFS(ga,ga.vexs[v].szName,visited);
}
}
void BFSTravel(Net ga,char *name)
{
ArcNode *p;
int v,w,u,k=0;
Queue Q;
int visited[20];
for(v=0;v<ga.vexnum;v++)
visited[v]=0;
InitQueue(Q);
for(v=LocateVex(ga,name);k!=2;v=(v+1)%(ga.vexnum-1))
{
if(v+1==LocateVex(ga,name))
k++;
if(visited[v]==0)
{
visited[v]=1;
printf("%s ",ga.vexs[v].szName);
EnterQueue(Q,v);
while(EmptyQueue(Q)!=0)
{
LeaveQueue(Q,u);
p=ga.vexs[u].firstarc;
while(p!=NULL)
{
w=p->adjvex;
if(visited[w]==0)
{
printf("%s ",ga.vexs[w].szName);
visited[w]=1;
EnterQueue(Q,w);
}
p=p->nextarc;
}
}
}
}
}
void main()
{
char name[40];
Net ga;
crt_net(ga);
printf("请输入深度优先遍历开始点的名:");
scanf("%s",name);
printf("深度优先遍历:");
DFSTravel(ga,name);
printf("\n");
printf("请输入广度优先遍历开始点的名:");
scanf("%s",name);
printf("广度优先遍历:");
BFSTravel(ga,name);
printf("\n");
}
F. 请教编程大神数据结构题目:c语言使用邻接链表存储结构实现用户输入的无向图的连通性判断
#include<stdio.h>
#include<stdlib.h>
#defineMAX_VERTEX_NUM100
typedefstructArcNode{
intadjvex;//该边的另一个顶点的位置
structArcNode*nextarc;//指向下一条边
}ArcNode;
typedefstructVNode{
intdata;//顶点的值
ArcNode*firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct{
AdjListvertices;//顶点数组
intvexnum,arcnum;
}ALGraph;
intLocateVex(ALGraphG,intv){//定位函数
for(inti=0;i<G.vexnum;i++){
if(v==G.vertices[i].data)returni;
}
}
voidCreateUDG(ALGraph&G){
ArcNode*p,*q;
inti,j,k,v1,v2;
printf("分别输入顶点个数和边的数目: ");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("分别输入各个顶点值: ");
for(i=0;i<G.vexnum;i++){
scanf("%d",&G.vertices[i].data);
G.vertices[i].firstarc=NULL;//初始化
}
printf("分别输入各条边的两个顶点: ");
for(k=0;k<G.arcnum;k++){
scanf("%d%d",&v1,&v2);
i=LocateVex(G,v1);j=LocateVex(G,v2);//定位
p=(ArcNode*)malloc(sizeof(ArcNode));//申请一个结点
p->adjvex=j;p->nextarc=NULL;//赋值
p->nextarc=G.vertices[i].firstarc;//连接结点
G.vertices[i].firstarc=p;//连接结点
q=(ArcNode*)malloc(sizeof(ArcNode));
q->adjvex=i;q->nextarc=NULL;
q->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=q;
}
}
voidPrintUDG(ALGraphG){//输出邻接表
inti,j;
for(i=0;i<G.vexnum;i++){
printf("%d:",i);
ArcNode*p;
p=G.vertices[i].firstarc;
while(p!=NULL){
printf("->%d",p->adjvex);
p=p->nextarc;
}
printf(" ");
}
}
intmain(){
ALGraphG;
CreateUDG(G);
PrintUDG(G);
return0;
}
G. C语言中怎样用链表保存结构体数据(动态数据结构)
链表有多种形式,如:单向链表,双向链表,单向循环链表,双向循环链表。将链表结构定义为list_t,则该类型中一定(至少)存在一个指向下一节点的指针list_t
*next;除了这个指针,list_t
中可以包含其它类型的数据,包括结构体变量。比如:typedef
struct
{
struct
usr_struct
data;
list_t
*next;
}
list_t;
H. 求一段c语言代码,题目:建立图的存储结构,能够输入图的顶点和边的信息,并存储到相应存储结构中
代码
/*输入:先输入两个数,代表点的数量和边的数量,
再输入各个边,起点编号 > 终点编号,编号从0开始
例子:
6 10
0 3
0 4
1 4
1 3
3 5
0 1
4 5
5 2
4 2
4 3
输出:
0 1 4 3 5 2
思路:
用vector建立邻接表
计算每个点的入度
如果是偏序无环的,一定存在入度为0的点,输出并且删除它,同时删除它出发的边,更新其他点的入度
循环直到移除所有点,输出顺序就是拓扑排序
*/
#include<iostream>
#include<vector>
using namespace std;
int main() {
freopen("in.txt","r",stdin);//重定向输入流//in.txt 建在程序所在的文件夹里
int M,N;
scanf("%d%d",&M,&N);//M个点,N条边
vector<int> maps[M];
int innode[M]={0};//入度
for(int i=0;i<N;i++)
{
int tx,ty;
scanf("%d%d",&tx,&ty);
maps[tx].push_back(ty);
++innode[ty];
}
for(int time=0;time<M;time++)
for(int i=0;i<M;i++)
{
if(innode[i]==0)
{
printf("%d ",i);
for(vector<int>::iterator it = maps[i].begin(); it != maps[i].end(); ++it)
{
--innode[*it];
}
innode[i]=-1;
break;
}
}
}
I. 请编写一个完整的程序,建立有向图的邻接表存储结构,要求:
给你一个邻接表的完整程序:
#include <iostream.h>
struct node
{
int data;
node *next;
};
class list
{
public:
list(){head=NULL;};
void MakeEmpty();
int Length();
void Insert(int x,int i);//将x插入到第i个结点(不含头结点)的之后
void Insertlist(int a,int b);//将节点b插入a之前
int Delete(int x);
int Remove(int i);
int Find(int x);
void Display();
private:
node *head;
};
void list::Display()
{
node *current=head;
while (current!=NULL)
{
cout<<current->data<<" ";
current=current->next;
}
cout<<endl;
}
void list::MakeEmpty()
{
head=NULL;
}
int list::Length()
{int n=1;
node *q=head;
if(q==NULL)
n=1;
else
while(q!=NULL)
{
n++;
q=q->next;
}
return n;
}
int list::Find(int x)//在链表中查找数值为x的结点,成功返回1,否则返回0
{
node *p=head;
while(p!=NULL&&p->data!=x)
p=p->next;
if(p->data==x)
return 1;
else
return 0;
}
void list::Insert (int x,int i)//将x插入到第i个结点(不含头结点)的之后;
{
node *p;//p中放第i个结点
node *q;//q中放i后的结点
node *h;//h中存要插入的结点
h=new node;
h->data =x;
p=head;
if(p->next !=NULL) //链表不是只有一个结点或者空链表时候
{
int n=1;
while(p->next !=NULL)
{
n++;
p=p->next ;
}// 得到链表的结点的个数
p=head;//使p重新等于链首
if(i==n)//i=n时,直接加在最后面就行了
{
while(p->next !=NULL)
p=p->next;
p->next=h;
h->next =NULL;
}
else if(i<n&&i>1)//先找到第i个结点,用p存第i个结点,用q存i后的结点,用h存要插入的结点
{
for(int j=1;j<i;j++)
p=p->next;//找到第i个结点,用p存第i个结点
q=p->next;//q存i后的结点
p->next=h;
h->next=q;
}
else
cout<<"超出链表结点个数的范围"<<endl;
}
else
cout<<"这个链表是空链表或者结点位置在首位"<<endl;
}
void list::Insertlist(int a,int b)//将b插入到结点为a之前
{
node *p,*q,*s;//p所指向的结点为a,s所指为要插入的数b,q所指向的是a前的结点
s=new node;
s->data=b;
p=head;
if(head==NULL)//空链表的时候
{
head=s;
s->next=NULL;
}
else
if(p->data==a)//a在链首时候
{
s->next=p;
head=s;
}
else
{
while(p->data!=a&&p->next!=NULL)//使p指向结点a,q指向a之前的结点
{
q=p;
p=p->next;
}
if(p->data==a)//若有结点a时候
{
q->next=s;
s->next=p;
}
else//没有a的时候
{
p->next=s;
s->next=NULL;
}
}
}
int list::Delete(int x)//删除链表中值为x的结点,成功返回1,否则返回0;
{
node *p,*q;
p=head;
if(p==NULL)
return 0;
if(p->data==x)
{
head=p->next;
delete p;
return 1;
}
else
{
while(p->data!=x&&p->next!=NULL)
{ q=p;
p=p->next;
}
if(p->data==x)
{
q->next =p->next;
delete p;
return 1;
}
else
return 0;
}
}
int list::Remove(int i)
{
node *p,*q;
p=head;
if(p!=NULL)
{ int n=1;
while(p->next !=NULL)
{
n++;
p=p->next ;
}//得到链表结点的个数
p=head;
if(i==n)//i结点在结尾的时候
{
while(p->next!=NULL)
{
q=p;
p=p->next;
}
q->next=NULL;
delete p;
return 1;
}
else if(i<n&&i>1)//i结点在中间的时候
{
for(int j=1;j<i;j++)
{
q=p;//q中放i前的结点
p=p->next ;//p中放第i个结点
}
q->next=p->next;
delete p;
return 1;
}
else if(i==1)//i结点在首位的时候
{
q=p->next;
head=q;
delete p;
return 1;
}
else
return 0;
}
else
return 0;
}
void main()
{
list A;
int data[10]={1,2,3,4,5,6,7,8,9,10};
A.Insertlist(0,data[0]);
for(int i=1;i<10;i++)
A.Insertlist(0,data[i]);
A.Display();
menu:cout<<"1.遍历链表"<<'\t'<<"2.查找链表"<<'\t'<<"3.插入链表"<<endl;
cout<<"4.删除链表"<<'\t'<<"5.链表长度"<<'\t'<<"6.置空链表"<<endl;
int m;
do
{
cout<<"请输入你想要进行的操作(选择对应操作前面的序号):"<<endl;
cin>>m;
}while(m<1||m>6);//当输入的序号不在包括中,让他重新输入
switch(m)
{
case 1:
{
A.Display ();
goto menu;
};break;
case 2:
{
cout<<"请输入你想要找到的结点:"<<endl;
int c;
cin>>c;//输入你想要找到的结点
if(A.Find (c)==1)
{
cout<<"可以找到"<<c<<endl;
A.Display ();//重新显示出链表A
}
else
{
cout<<"链表中不存在"<<c<<endl;
A.Display ();//重新显示出链表A
}
goto menu;
};break;
case 3:
{
cout<<"请选择你要插入的方式(选择前面的序号进行选择)"<<endl;
cout<<"1.将特定的结点加入到特定的结点前"<<'\t'<<"2.将特定的结点加到特定的位置后"<<endl;
int b1;
do
{
cout<<"请输入你想要插入的方式(选择前面的序号进行选择):"<<endl;
cin>>b1;
}while(b1<1||b1>2);//当输入的序号不在包括中,让他重新输入
if(b1==1)
{
cout<<"请输入你想要插入的数和想要插入的结点(为此结点之前插入):"<<endl;
int a1,a2;
cin>>a1>>a2;
A.Insertlist (a1,a2);//将a1插入到结点为a2结点之前
cout<<"此时链表为:"<<endl;
A.Display ();//重新显示出链表A
}
else
{
cout<<"请输入你想要插入的数和想要插入的位置(为此结点之后插入):"<<endl;
int a1,a2;
cin>>a1>>a2;
A.Insert (a1,a2);//将a1插入到结点位置为a2的结点之后
cout<<"此时链表为:"<<endl;
A.Display ();//重新显示出链表A
}
goto menu;
};break;
case 4:
{
cout<<"请选择你要删除的方式(选择前面的序号进行选择)"<<endl;
cout<<"1.删除特定的结点"<<'\t'<<"2.删除特定位置的结点"<<endl;
int b1;
do
{
cout<<"请输入你想要插入的方式(选择前面的序号进行选择):"<<endl;
cin>>b1;
}while(b1<1||b1>2);//当输入的序号不在包括中,让他重新输入
if(b1==1)
{
cout<<"请输入你想要删除的结点:"<<endl;
int a;
cin>>a;//输入你想要删除的结点
if(A.Delete (a)==1)
{
cout<<"成功删除"<<a<<endl;
cout<<"删除后的链表为:"<<endl;
A.Display ();
}
else
{
cout<<"此链表为:"<<endl;
A.Display ();//重新显示出链表A
cout<<"链表中不存在"<<a<<endl;
}
}
else
{
cout<<"请输入你想要删除的结点位置:"<<endl;
int b;
cin>>b;//输入你想要删除的结点的位置
if(A.Remove(b)==1)
{
cout<<"成功删除第"<<b<<"个结点"<<endl;
cout<<"删除后的链表为:"<<endl;
A.Display ();//重新显示出链表A
}
else
{
cout<<"当前链表的结点个数为:"<<A.Length ()<<endl;
cout<<"您输入的结点位置越界"<<endl;
}
}
goto menu;
};break;
case 5:
{
cout<<"这个链表的结点数为:"<<A.Length ()<<endl;
goto menu;
};break;
case 6:
{
A.MakeEmpty ();
cout<<"这个链表已经被置空"<<endl;
goto menu;
};break;
}
}
评论(3)|1
sunnyfulin |六级采纳率46%
擅长:C/C++JAVA相关Windows数据结构及算法网络其它产品
按默认排序|按时间排序
其他1条回答
2012-04-23 17:41121446881|六级
我写了一个C语言的,只给你两个结构体和一个初始化函数:
#include "stdio.h"
#include "malloc.h"
struct adjacentnext//邻接表项结构体
{
int element;
int quanvalue;
struct adjacentnext *next;
};
struct adjacenthead//邻接表头结构体
{
char flag;
int curvalue;
int element;
struct adjacenthead *previous;
struct adjacentnext *son;
};
//初始化图,用邻接表实现
struct adjacenthead *mapinitialnize(int mapsize)
{
struct adjacenthead *ahlists=NULL;
struct adjacentnext *newnode=NULL;
int i;
int x,y,z;
ahlists=malloc(sizeof(struct adjacenthead)*mapsize);
if(ahlists==NULL)
return NULL;
for(i=0;i<mapsize;i++)
{
ahlists[i].curvalue=0;
ahlists[i].flag=0;
ahlists[i].previous=NULL;
ahlists[i].son=NULL;
ahlists[i].element=i+1;
}
scanf("%d%d%d",&x,&y,&z);//输入源结点,目的结点,以及源结点到目的结点的路权值
while(x!=0&&y!=0)//x,y至少有一个零就结束
{
newnode=malloc(sizeof(struct adjacentnext));
newnode->element=y;
newnode->quanvalue=z;
newnode->next=ahlists[x-1].son;
ahlists[x-1].son=newnode;
scanf("%d%d%d",&x,&y,&z);
}
return ahlists;//返回邻接表头
}