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
进度太慢了,不得不摒弃一些琐事来加快进度!!加油哇~