【图】邻接表

目录

无向图的邻接表

 链表(存相邻顶点下标)的类

数组里放的顶点

邻接表(操作)

构造和析构(创建销毁邻接表)

插入顶点

插入边

获取下标

插v1、v2之间的边

删除顶点

删除边

输出:

其他图邻接表


         

        邻接表用一个一维数组存图的顶点和指针,指针指向一个链表,链表里存放与当前顶点相连的顶点在数组中的下标。如下图(无向图邻接表):

无向图的邻接表

 链表(存相邻顶点下标)的类

class Edge
{
public:
	Edge() :m_next(nullptr) {}
	Edge(int v) :m_destindex(v), m_next(nullptr) {}
	int m_destindex;//下标
	Edge* m_next;//下一个邻接顶点的结点
};

数组里放的顶点

class Vertex
{
public:
	Vertex() :m_list(nullptr) {}
	Vertex(int v) :m_VerValue(v), m_list(nullptr) {}
	char m_VerValue;//顶点值
	Edge* m_list;//指针指向邻接顶点的链表
};

邻接表(操作)

插入顶点,插入边,删除顶点,删除边,获取顶点在数组中的下标(前面的操作需要用)

#define SIZE 10
class GraphLink
{
public:
	GraphLink();
	~GraphLink();
	void InsertVertex(char v);//插顶点
	void InsertEdge(char v1, char v2);//插边
	void PrintGraph();//打印
	void DelVertex(char v);//删顶点
	void DelEdge(char v1, char v2);//删边
	int GetVertexIndex(char v);//获取顶点下标
private:
	int m_MaxVertex;//最多结点数
	int m_NumVertex;//当前结点数
	int m_NumEdge;//边数
	Vertex* m_VerArr;//存顶点的数组(指针指向数组头)
};

构造和析构(创建销毁邻接表)

创建:给m_VerArr指针new最大顶点数m_MaxVertex个顶点Vertex大小的空间;

销毁:释放指向数组起始的指针的空间。

GraphLink::GraphLink() :m_MaxVertex(SIZE), m_NumVertex(0), m_NumEdge(0)
{
	m_VerArr = new Vertex[m_MaxVertex];
}
GraphLink::~GraphLink()
{
	if (m_VerArr != nullptr)
	{
		delete[]m_VerArr;
		m_VerArr = nullptr;
	}
}

插入顶点

        首先确定顶点数(不能超过设定的最大顶点数)。

        若可插:将顶点值赋到数组中最后一个位置m_VerArr[m_NumVertex],顶点个数++。

void GraphLink::InsertVertex(char v)
{
	if (m_NumVertex >= m_MaxVertex)return;
	m_VerArr[m_NumVertex++].m_VerValue = v;
}

插入边

插入顶点v1到顶点v2的边时,由于链表中记录的是顶点的下标,所有首先需要有一个获取下标的函数:

获取下标

        遍历数组记录下标,找到顶点即可找到下标返回,若没找到:返回-1。

int GraphLink::GetVertexIndex(char c)
{
	for (int i = 0; i < m_NumVertex; i++)
	{
		if (m_VerArr[i].m_VerValue == c)
			return i;
	}
	return -1;
}

插v1、v2之间的边

        注意:无向图插一条边需要改两个表。

获取下标后,插入方法与链表头插相同。

void GraphLink::InsertEdge(char v1, char v2)
{
	int p1 = GetVertexIndex(v1);
	int p2 = GetVertexIndex(v2);
	if (p1 == -2 || p2 == -1)return;

	//v1->v2 既是在v1的边链表中插入值为p2的边节点
	Edge* edge = new Edge(p2);
	edge->m_next = m_VerArr[p1].m_list;
	m_VerArr[p1].m_list = edge;
	//v2->v1
	edge = new Edge(p1);
	edge->m_next = m_VerArr[p2].m_list;
	m_VerArr[p2].m_list = edge;

	m_NumEdge++;
}

删除顶点

用覆盖删除的方法:数组最后一个顶点覆盖要删的,并修改链表内受影响下标的值。

void GraphLink::DelVertex(char v)
{
	int p = GetVertexIndex(v);
	if (p == -1)return;
	Edge* pp = m_VerArr[p].m_list;
	char destvalue;
	while (pp)
	{
		destvalue = m_VerArr[pp->m_destindex].m_VerValue;
		DelEdge(v, destvalue);
		pp = m_VerArr[p].m_list;
	}
	//覆盖
	m_NumVertex--;
	m_VerArr[p].m_VerValue = m_VerArr[m_NumVertex--].m_VerValue;
	//修改
	Edge* q = nullptr;
	pp = m_VerArr[p].m_list;
	while (pp != nullptr)
	{
		int k = pp->m_destindex;
		q = m_VerArr[k].m_list;
		while (q)
		{
			if (q->m_destindex == m_NumVertex)
			{
				q->m_destindex = p;
				break;
			}
			q = q->m_next;
		}
		pp = pp->m_next;
	}
}

删除边

void GraphLink::DelEdge(char v1, char v2)
{
	int p1 = GetVertexIndex(v1);
	int p2 = GetVertexIndex(v2);
	if (p1 == -2 || p2 == -1)return;
	//在p1里面删p2
	Edge* pf = m_VerArr[p1].m_list;
	if (m_VerArr[p1].m_list->m_destindex == p2)
	{
		m_VerArr[p1].m_list = m_VerArr[p1].m_list->m_next;
		delete pf;
		pf = nullptr;
	}
	else
	{
		while (pf->m_next->m_destindex != p2 && pf != nullptr)
		{
			pf = pf->m_next;
		}
		if (pf == nullptr)return;

		Edge* p = pf->m_next;
		pf->m_next = p->m_next;
		delete p;
		p = nullptr;
	}
	//v2->v1
	pf = m_VerArr[p2].m_list;
	if (m_VerArr[p2].m_list->m_destindex == p1)
	{
		m_VerArr[p2].m_list = m_VerArr[p2].m_list->m_next;
		delete pf;
		pf = nullptr;
	}
	else
	{
		while (pf->m_next->m_destindex != p1 && pf != nullptr)
		{
			pf = pf->m_next;
		}
		if (pf == nullptr)return;

		Edge* p = pf->m_next;
		pf->m_next = p->m_next;
		delete p;
		p = nullptr;
	}

	m_NumEdge--;
}

输出:


void GraphLink::PrintGraph()
{
	Edge* p = nullptr;
	for (int i = 0; i < m_NumVertex; i++)
	{
		cout << i << " " << m_VerArr[i].m_VerValue << " ";
		p = m_VerArr[i].m_list;
		while (p)
		{
			cout << p->m_destindex << "->";
			p = p->m_next;
		}
		cout << "nul" << endl;
	}
	cout << endl;
}

其他图邻接表

        有向图注意边的数量修改,网需要在链表结点中加上存边权值的部分。

 网结构如下:

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曦樂~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值