(十)数据结构之十字链表

1,内容概述

 主要介绍数据结构图的存储结构之一:十字链表的实现。

2,什么是十字链表

 十字链表是图的邻接表与逆邻接表相结合的一种存储结构。(传送门 :邻接表、邻接矩阵数据结构
 特点:源于邻接表、逆邻接表却胜于它们,十字链表将弧尾节点相同的弧串联在一条链表上,将弧首节点相同的弧同样串联在一条链表上。同时表头节点也做了改变,有第一条指向和第一条指出该表头结点的指针域,这样我能方便的知道那些边指向了目标节点啊,哪些边由此节点出发指向其他节点,这是相当方便的。

3,十字链表应用

 应用:一个地图,我们想知道从某个地点出发有多少个去向,或者说有多少个地方通向这里,这是我们用十字链表来处理就显得很轻松,只需要遍历链表即可。(例子举得不好,见谅)

4,十字链表算法分析

 与邻接表和逆邻接表的建立相同,我们的主要算法集中在输入数据之后,根据弧的首尾节点进行节点建立或者连接的操作。具体实现可以看下面的代码(不难,就是稍微麻烦)

5,实现代码

c++代码:

#include <iostream>
using namespace std;

//-----------------------------------十字链表存储结构实现---------------------------------//
#define MAXNUM 20

typedef struct Arc {
	int 		head, tail;
	struct Arc *headarc, *tailarc;
	Arc(int x, int y, struct Arc *p1 = nullptr, struct Arc *p2 = nullptr) : tail(x), head(y), tailarc(p1), headarc(p2){}
	//int weight; 仅实现十字链表结构,不用给弧赋权重 
} Arc, *pArc;

typedef struct TableHead {
	//int num;
	pArc firIn, firOut;
	TableHead(){firIn = nullptr; firOut = nullptr;}
} TableHead, TableHeadArray[MAXNUM]; 

class DGraph {
	public:
		DGraph(int x, int y) : nodeNum(x), edgeNum(y) {}
		int createList();
		void displayList() const;
	private:
		TableHeadArray arr; //考虑初始化 
		int nodeNum, edgeNum;
};

int DGraph::createList() {
	cout << "请输入尾节点和头节点以表示一条弧" << endl;
	
	int tailVertex, headVertex; pArc p1, p2; bool mark;
	for (int i = 0, mark = false; i < edgeNum; ++i) {
		cin >> tailVertex >> headVertex;
		(p1 = arr[tailVertex - 1].firOut) ? mark = true : (arr[tailVertex - 1].firOut = new Arc(tailVertex, headVertex, nullptr, nullptr), p2 = arr[tailVertex - 1].firOut, 1);
		if (mark) {while(p1->tailarc) p1 = p1->tailarc; p1->tailarc = new Arc(tailVertex, headVertex); p2 = p1->tailarc; mark = false;}
		(p1 = arr[headVertex - 1].firIn) ? mark = true : (arr[headVertex - 1].firIn = p2, 1);
		if (mark) {while(p1->headarc) p1 = p1->headarc; p1->headarc = p2; mark = false;} //headarc表示弧首节点相同 
	}
	return 0; //ok
}
void DGraph::displayList() const {
	pArc p; bool mark;
	for (int j = 0; j < 2; ++j, cout << endl)
		for (int i = 0; i < nodeNum; ++i) {
			cout << i + 1 << " -> ";
			p = (arr[i].firOut ? mark = false, arr[i].firOut : (mark = true, nullptr));
			if ((p = arr[i].firOut) != nullptr && !j) {while(p) {cout << p->head << " -> "; p = p->tailarc;} cout << "null" << endl;}
			else						 {if (mark) {mark = false; cout << "null" << endl;continue;}if (p = arr[i].firIn) {while(p) {cout << p->tail<< " -> "; p = p->headarc;} cout << "null" << endl;}}
		}
}
int main() {
	int node, edge;
	cout << "请输入节点数和边数 :";
	cin >> node >> edge;
	DGraph G(node, edge);
	
	G.createList(); G.displayList();
	
	return 0;
}

6,运行截图

运行后是这样的,
运行截图
分别按指出节点和指入节点的顺序打印链表,以空格隔开。(空格上面是指出节点,下面是指入节点)

7,一点注意

注意邻接表的存储结构中,链表的节点代表节点,而这里,链表的节点代表弧!!这一点从结构体定义处就能看出。

8,ending

进度太慢了,不得不摒弃一些琐事来加快进度!!加油哇~

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值