数据结构——图的储存结构(邻接表)

                 图的储存结构(邻接表)

       图用邻接矩阵储存时,是用的一个二维数组,操作这个图的时候就相当于操作这个二维数组。但一但使用数组时就有一个很明显的缺点,那就是动态扩容性,基于邻接矩阵的图不能添加节点,只能添加边。如果图是一个节点非常多的稀疏图,比如说这个n为一亿,那么所需要的内存就是100000000 * 100000000 = 10000000000000000个单位,而其中非常多的内存是被浪费了的。因而可以使用另外一种储存结构——邻接表来储存图。邻接表是在一维的基础上进行扩展的,把节点排列成一维的线性表,然后线性表的每个元素又是一个链表,这条链的头就是当前节点,而链中的元素就是这个节点在图中的邻接节点,把邻接节点按序号排列成一个线性链。这样的好处就是只储存了有意义的关系,不会像邻接矩阵那样浪费没有连接关系的储存单元。
      下面是用邻接表来实现图
#pragma once
#ifndef ADJLISTDIRGRAPH
#define ADJLISTDIRGRAPH
#include "graph.h"
#include "linklist.h"
namespace dataStructure
{
	template
	struct AdjListGraphNode
	{
		T data;
		int tag;
		LinkList *adjLink = NULL;
	};
	template
	class AdjListDirGraph:public Graph
	{
	public:
		AdjListDirGraph();
		~AdjListDirGraph();
		bool InsertNode(const T &t);
		bool DeleteNode(const int v);
		//获取节点的值
		bool GetElem(int v, T &t);
		//设置节点的值
		bool SetElem(int v, const T &t);
		//返回节点元素
		T GetVexData(int v)const;
		//返回节点个数
		int GetVexNum()const;
		//返回边数
		int GetEdgeNum()const;
		//返回第一个邻接点
		int FirstAdjVex(int v)const;
		//返回下一个邻接点
		int NextAdjVex(int v1, int v2)const;
		//插入一条边
		void InsertEdge(int v1, int v2);
		//删除一条边
		void DeleteEdge(int v1, int v2);
		//获取节点上的标志
		bool GetTag(int v, int &tag)const;
		//设置节点上的标志
		bool SetTag(int v, const int &tag);
		//深搜
		void DFSTraverse(void(*visit)(const T &t))const;
		//广搜
		void BFSTraverse(void(*visit)(const T &t))const;
	private:
		int vexNum, edgeNum;
		LinkList*> *adjList;
	};

	template
	AdjListDirGraph::AdjListDirGraph()
	{
		adjList = new LinkList*>;
		vexNum = 0;
		edgeNum = 0;
	}

	template
	AdjListDirGraph::~AdjListDirGraph()
	{
		if(adjList)
		{
			delete adjList;
		}
	}
	template
	bool AdjListDirGraph::InsertNode(const T &t)
	{
		AdjListGraphNode *newNode = new AdjListGraphNode;
		newNode->data = t;
		newNode->adjLink = new LinkList;
		adjList->Add(newNode);
		++vexNum;
		return true;
	}
	template
	bool AdjListDirGraph::DeleteNode(const int v)
	{
		if(v >=0 && v < vexNum)
		{
			AdjListGraphNode *node = NULL;
			bool result = adjList->Delete(adjList->Length() - 1, node);
			if (node) 
			{
				--vexNum;
				return true;
			}
		}
		return false;
	}
	//获取节点的值
	template
	bool AdjListDirGraph::GetElem(int v, T &t)
	{
		if(v >=0 && v < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v, node);
			if (node)
			{
				t = node->data;
				return true;
			}
			else 
			{
				return false;
			}
		}
		return false;
	}

	//设置节点的值
	template
	bool AdjListDirGraph::SetElem(int v, const T &t)
	{
		if (v >= 0 && v < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v, node);
			if (node)
			{
				node->data = t;
				return true;
			}
			else
			{
				return false;
			}
		}
		return false;
	}

	//返回节点元素
	template
	T AdjListDirGraph::GetVexData(int v)const
	{
		if (v >= 0 && v < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v, node);
			if (node)
			{
				return node->data;
			}
			else
			{
			}
		}
	}

	//返回节点个数
	template
	int AdjListDirGraph::GetVexNum()const
	{
		return vexNum;
	}

	//返回边数
	template
	int AdjListDirGraph::GetEdgeNum()const
	{
		return edgeNum;
	}

	//返回第一个邻接点
	template
	int AdjListDirGraph::FirstAdjVex(int v)const
	{
		if(v >=0 && v  *node = NULL;
			adjList->GetElem(v, node);
			if(node)
			{
				int firstV = -1;
				node->adjLink->GetElem(0, firstV);
				return firstV;
			}
		}
		return -1;
	}

	//返回下一个邻接点
	template
	int AdjListDirGraph::NextAdjVex(int v1, int v2)const
	{
		if (v1 >= 0 && v1 < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v1, node);
			if(node)
			{
				if (v2 >= 0 && v2 < node->adjLink->Length())
				{
					int nextV = -1;
					int index = -1;
					int v = -1;
					for (int i = 0;i < node->adjLink->Length();i++)
					{
						node->adjLink->GetElem(i, v);
						if (v == v2 && i + 1 < node->adjLink->Length()) 
						{
							index = i + 1;
						}
					}
					node->adjLink->GetElem(index, nextV);
					return nextV;
				}
			}
		}
		return -1;
	}

	//插入一条边
	template
	void AdjListDirGraph::InsertEdge(int v1, int v2)
	{
		if (v1 >= 0 && v1 < vexNum && v2 >= 0 && v2 < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v1, node);
			if (node)
			{
				//查找添加边的节点的位置
				int index = -1;
				int k = -1;
				for (int i = 0;i < node->adjLink->Length();i++)
				{
					node->adjLink->GetElem(i, k);
					if(v2 < k && i == 0)//比第一个节点的值都小
					{
						index = 0;
						break;
					}
					if(v2 > k )//v2比当前节点的值要大
					{
						if ((i + 1) < node->adjLink->Length())//后面还有一个节点
						{
							node->adjLink->GetElem(i + 1, k);
							if(k > v2)//index应该在i和i+1之间
							{
								index = i + 1;
								break;
							}
						}
					}
				}
				if(index < 0)
				{
					index = node->adjLink->Length();
				}
				node->adjLink->Insert(index, v2);
				++edgeNum;
			}
		}
	}

	//删除一条边
	template
	void AdjListDirGraph::DeleteEdge(int v1, int v2)
	{
		if (v1 >= 0 && v1 < vexNum && v2 >= 0 && v2 < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v1, node);
			if (node) 
			{
				int index = -1;
				int value = -1;
				for (int i = 0;i < node->adjLink->Length();i++)
				{
					node->adjLink->GetElem(i, value);
					if(value == v2)
					{
						index = i;
						break;
					}
				}
				if(index >= 0)
				{
					int k = -1;
					node->adjLink->Delete(index, k);
					++edgeNum;
				}
			}
		}
	}

	//获取节点上的标志
	template
	bool AdjListDirGraph::GetTag(int v, int &tag)const
	{
		if(v >=0 && v < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v, node);
			if(node)
			{
				tag = node->tag;
				return true;
			}
		}
		return false;
	}

	//设置节点上的标志
	template
	bool AdjListDirGraph::SetTag(int v, const int &tag)
	{
		if (v >= 0 && v < vexNum)
		{
			AdjListGraphNode *node = NULL;
			adjList->GetElem(v, node);
			if (node)
			{
				node->tag = tag;
				return true;
			}
		}
		return false;
	}



	//深搜
	template
	void AdjListDirGraph::DFSTraverse(void(*visit)(const T &t))const
	{

	}



	//广搜
	template
	void AdjListDirGraph::BFSTraverse(void(*visit)(const T &t))const
	{

	}
}
#endif
下面是测试代码,同样可以用断点调试的方式查看生成的图的结构
#include "stdafx.h"
#include 
#include "adjlistdirgraph.h"
using namespace std;
using namespace dataStructure;


int main()
{
	AdjListDirGraph *graph = new AdjListDirGraph;
	char a = 'A';
	char b = 'B';
	char c = 'C';
	char d = 'D';
	char e = 'E';
	graph->InsertNode(a);
	graph->InsertNode(b);
	graph->InsertNode(c);
	graph->InsertNode(d);
	graph->InsertNode(e);
	graph->InsertEdge(0, 2);
	graph->InsertEdge(0, 3);
	graph->InsertEdge(1, 2);
	graph->InsertEdge(1, 4);
	graph->InsertEdge(2, 0);
	graph->InsertEdge(2, 1);
	graph->InsertEdge(2, 4);
	graph->InsertEdge(3, 0);
	graph->InsertEdge(3, 4);
	graph->InsertEdge(4, 1);
	graph->InsertEdge(4, 2);
	graph->InsertEdge(4, 3);
	system("pause");
	return 0;
}



你可能感兴趣的:(学习,数据结构)