【数据结构】图的存储结构之十字链表的创建(C语言)

定义

对于有向图图来说,邻接表是有缺陷。关心了出度问题,想了解入度就必须要遍历整个图才可以知道,反之,逆邻接表解决了入度却不了解出度的情况。有没有可能把邻接表与逆邻接表结合起来呢?答案是肯定的,就是把它们整合在一起、这就是有向图一种存储方法:十字链表

定义顶点结构如图1-1所示。
在这里插入图片描述

图1-1

firstin表示入边表头指针,指向该顶点的入边表中第一个结点,firstout表示出边表头指针,指向该顶点的出边表中的第一个结点。

边表结点结构如图1-2所示。
在这里插入图片描述

图1-2

tailvex是指弧起点在顶点表的下标,headvex是指弧终点在顶点表中的下标,headlink是指入边表指针域,指向终点相同的下一条边,taillink是指边表指针域,指向结点相同的下一条边。如果是网,还可以增加一个weight域来存储权值。

十字链表的优点:

  1. 十字链表是把邻接表和逆邻接表整合在一起,这样既容易找到以Vi为尾的弧,也容易找到以Vi为头的弧,因而容易求的顶点的出度和入度。
  2. 十字链表创建图算法的时间复杂度和邻接表是相同的。

代码

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
using namespace std;
#define MAX_VERTEX_NUM 20
#define OVERFLOW -2
#define OK 1
typedef int Status;
typedef char VertexType[MAX_VERTEX_NUM];
typedef char InfoType;
//弧(边)的结构体
typedef struct ArcBox
{
	int tailvex,headvex;  						//该弧的尾和头顶点的位置
	struct ArcBox *hlink, *tlink;  				//分别为弧头同样和弧尾同样的弧的链域
	InfoType *info;  							//该弧的相关信息的指针
}ArcBox;

//顶点的结构体
typedef struct VexNode
{
	VertexType data;
	ArcBox *firstin, *firstout;  //分别指向该顶点的第一条入弧和出弧
}VexNode;

//有向图的结构体
typedef struct  
{
	VexNode xlist[MAX_VERTEX_NUM];  	//表头向量
	int vexnum, arcnum;  				//有向图的当前顶点数和弧数
}OLGraph;

int LocateVex(OLGraph &G, VertexType u)
{
	for(int i = 0; i < G.vexnum; ++i)
		if(strcmp(G.xlist[i].data, u) == 0)
			return i;
	return -1;
}

//构造有向图G;
Status CreateDG(OLGraph &G)
{
	
	int i,j,k;
	printf("请输入有向图的顶点数以及弧数:\n");
	scanf("%d%d",&G.vexnum, &G.arcnum);
	printf("请输入%d个顶点的值,之间有空格隔开:\n",G.vexnum);
	for(i=0; i<G.vexnum; ++i) //构造表头向量
	{
		getchar();
		scanf("%s",G.xlist[i].data);  //输入顶点值
		G.xlist[i].firstin = NULL;
		G.xlist[i].firstout = NULL;
	}
	
	VertexType v1,v2;
	ArcBox *p;
	printf("请依次输入%d条弧各自依附的两个顶点(输入格式:v1 v2)\n",G.arcnum);
	for(k=0; k < G.arcnum; ++k)  //输入各弧并构造十字链表
	{
		getchar();
		scanf("%s%s",v1,v2);
		i=LocateVex(G,v1);
		j=LocateVex(G,v2);
		p = (ArcBox *)malloc(sizeof(ArcBox));
		if(!p)
			exit(OVERFLOW);
		p->tailvex = i;
		p->headvex = j;
		p->hlink = G.xlist[j].firstin;
		p->tlink = G.xlist[i].firstout;
		p->info = NULL;
		G.xlist[j].firstin = G.xlist[i].firstout = p;  //完毕在入弧和出弧链头的插入
	}
	getchar();
	return OK;
}

void DisplayArc(OLGraph &G)
{
	ArcBox *p;
	for(int i=0; i < G.vexnum; ++i)
	{
		p=G.xlist[i].firstout;
		while(p)
		{
			printf("<%s,%s> ",G.xlist[p->tailvex].data, G.xlist[p->headvex].data);
			p = p->tlink;
		}
	}
	printf("\n");
}


//顶点的度:入度+出度
int VexDegree(OLGraph &G, VertexType v)
{
	
	int k = LocateVex(G,v);
	if(k<0)
		exit(OVERFLOW);
	int id=0,od=0;  //入度,出度

	ArcBox *pin = G.xlist[k].firstin;
	ArcBox *pout = G.xlist[k].firstout;
	while(pin)  //求入度
	{
		++id;
		pin = pin->hlink;
	}

	while(pout)  //求出度
	{
		++od;
		pout = pout->tlink;
	}

	return id+od; //顶点的度
}

int main()
{
	int flag = 1;
	OLGraph G;
	CreateDG(G);
	printf("=========================================\n");
	printf("该有向图的弧例如以下:\n");
	DisplayArc(G);
	VertexType v;
	printf("\n=========================================\n");
	while(1)
	{
		if(flag == 0)
				break;
		printf("请输入随意顶点,将输出该顶点度的值:");
		scanf("%s",v);
		getchar();
		printf("顶点 %s 的度为 :%d\n",v,VexDegree(G,v));
		printf("结束请输入 0 以回车键结束\n\n");
		cin>>flag;
	}
	printf("=========================================\n");
	return 0;
}



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
稀疏矩阵的十字链表是一种用于压缩稀疏矩阵的数据结构。它通过链表的方式来存储矩阵中非零元素的位置和值,并且可以快速地进行插入和删除操作。在C语言中,可以使用结构体和指针来实现稀疏矩阵的十字链表。具体实现如下: ``` #include <stdio.h> #include <stdlib.h> typedef struct Node { int row; int col; int value; struct Node* right; struct Node* down; } Node; typedef struct CrossList { Node* rhead; Node* chead; int rows; int cols; int nums; } CrossList; void InitCrossList(CrossList* crosslist, int rows, int cols); void InsertCrossList(CrossList* crosslist, int row, int col, int value); void PrintCrossList(CrossList* crosslist); void InitCrossList(CrossList* crosslist, int rows, int cols) { crosslist->rhead = (Node*)malloc(sizeof(Node) * rows); crosslist->chead = (Node*)malloc(sizeof(Node) * cols); crosslist->rows = rows; crosslist->cols = cols; crosslist->nums = 0; for (int i = 0; i < rows; i++) { crosslist->rhead[i].right = NULL; } for (int i = 0; i < cols; i++) { crosslist->chead[i].down = NULL; } } void InsertCrossList(CrossList* crosslist, int row, int col, int value) { if (row >= crosslist->rows || col >= crosslist->cols) { return; } Node* node = (Node*)malloc(sizeof(Node)); node->row = row; node->col = col; node->value = value; Node* p = &crosslist->rhead[row]; while (p->right && p->right->col < col) { p = p->right; } if (p->right && p->right->col == col) { p->right->value = value; free(node); } else { node->right = p->right; p->right = node; } p = &crosslist->chead[col]; while (p->down && p->down->row < row) { p = p->down; } if (p->down && p->down->row == row) { p->down->value = value; } else { node->down = p->down; p->down = node; } crosslist->nums++; } void PrintCrossList(CrossList* crosslist) { printf("稀疏矩阵的十字链表表示:\n"); for (int i = 0; i < crosslist->rows; i++) { Node* p = crosslist->rhead[i].right; for (int j = 0; j < crosslist->cols; j++) { if (p && p->col == j) { printf("%d ", p->value); p = p->right; } else { printf("0 "); } } printf("\n"); } } int main() { CrossList crosslist; int rows, cols; printf("请输入稀疏矩阵的行数和列数:"); scanf("%d %d", &rows, &cols); InitCrossList(&crosslist, rows, cols); int row, col, value; printf("请输入稀疏矩阵中非零元素的行、列和值(以-1 -1 -1结束):\n"); while (1) { scanf("%d %d %d", &row, &col, &value); if (row == -1 && col == -1 && value == -1) { break; } InsertCrossList(&crosslist, row, col, value); } PrintCrossList(&crosslist); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值