数据结构图的常用算法总结

【数据结构与算法】图(Graph)【详解】 图(Graph)是由顶点的有穷非空集合V ( G ) 和顶点之间边的集合E ( G )组成,通常表示为: G = ( V , E ) ,其中,G表示个图,V 是图G中顶点的集合,E是图G中边的集合。若V = { v 1 , v 2 , . . . , v n } ,则用∣ V ∣表示图G中顶点的个数,也称图G的阶,E = { ( u , v ) ∣ u ∈ V , v ∈ V } ,用∣ E ∣表示图G中边的条数。注意:线性表可以是空表,树可以是空树,但图不可以是空图。 阅读详情
数据结构图的常用算法总结
本人在校期间写了一个win32应用程序,用于回顾算法导论图的常用算法(图中边的权值为两个圆心的像素点的距离)
1.dijkstra算法求两点之间最短路径:
贪心算法用优先队列实现,每次选择距离起点路径和最短的顶点弹出队列,此顶点最短路径就已经确定

初始图如下

选择起点如W

选择终点如下:

显示路线:
1)

2)

3)

4)

打开数据,第一行为W距离S点距离,剩下为边的距离一遍参考
470
A <-> D 120
D <-> C 71
C <-> E 93
E <-> G 107
G <-> B 129
B <-> A 83
F <-> C 125
C <-> A 122
C <-> G 118
X <-> O 85
O <-> Y 80
Y <-> D 113
D <-> P 101
P <-> H 112
H <-> Q 80
Q <-> R 86
R <-> I 67
I <-> E 75
E <-> H 74
H <-> I 108
I <-> Q 133
Q <-> Z 68
Z <-> P 83
P <-> C 161
C <-> H 86
E <-> J 101
J <-> S 87
S <-> R 119
I <-> S 68
I <-> J 105
G <-> J 112
J <-> T 70
T <-> K 84
K <-> G 63
G <-> T 83
F <-> K 96
G <-> U 141
U <-> F 82
F <-> B 59
B <-> L 87
L <-> U 53
L <-> V 74
V <-> B 114
B <-> M 101
M <-> W 79
W <-> N 68
N <-> A 76
A <-> M 96
M <-> N 91
M <-> V 61
N <-> X 83
X <-> A 115
A <-> O 99
O <-> D 85
Y <-> P 90
P <-> Q 86
U <-> K 103
B <-> D 147
A <-> L 157
X <-> C 211
O <-> P 137
D <-> H 89
B <-> C 104
C <-> J 181
W <-> A 130
W <-> X 143
N <-> O 128
O <-> B 169
M <-> L 113
L <-> F 65
F <-> G 89
F <-> E 172
H <-> G 167
Q <-> E 142
H <-> R 108
S <-> E 125
E <-> T 140
Q <-> D 137
D <-> E 141
E <-> B 180
O <-> C 142
Y <-> H 177
N <-> B 145
V <-> D 252

2.并查集思想求连通分量
对于原始图1:

结果为

对于实验室图2:

求出结果为:

3.贪心算法PRIM求MST

求MST用 KRUSKAL 算法如下:


主要CPP文件
// windowsDesign.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "windowsDesign.h"
#include "class.h"
#include "function.h"
#include "globalVariable.h"
#include "dis_algo_graph.h"
#include "SS_algo_graph.h"
#include <string>
#include "MST_PRIM.h"
#include "MST_KRUSKAL.h"

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;								// 当前实例
TCHAR szTitle[MAX_LOADSTRING];					// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口类名

// 全局变量 我自己的
static int nowState = CommondState::emptyState ; 
static WindowSize winsize ;
static DataSet graphData;

// 此代码模块中包含的函数的前向声明:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: 在此放置代码。
	MSG msg;
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_WINDOWSDESIGN, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSDESIGN));

	// 主消息循环:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}

	return (int) msg.wParam;
}




//  函数: MyRegisterClass()
//  目的: 注册窗口类。
//  注释:
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。

ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSDESIGN));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WINDOWSDESIGN);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中
   

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }




   long style = GetWindowLong(hWnd,GWL_STYLE);//获得窗口风格

   winsize.screenX = GetSystemMetrics(SM_CXSCREEN);//获取整个屏幕右下角X坐标
   winsize.screenY = GetSystemMetrics(SM_CYSCREEN)-40;//屏幕Y坐标
   
  
   SetWindowPos(hWnd, NULL,0,0,winsize.screenX,winsize.screenY,SWP_NOZORDER);//改变窗口位置、尺寸和Z序


   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND	- 处理应用程序菜单
//  WM_PAINT	- 绘制主窗口
//  WM_DESTROY	- 发送退出消息并返回

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static Point * myPoint = new Point();
	static TCHAR greet[] = TEXT("A");
	static Line * myline = new Line();
	static Point start,end;
	static list<Line> result;
	static list<Line> result_kruskal;
	



	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择:
		switch ( wmId )
		{
		case IDM_GRAPH_CLEAR:
			{			
				clearWindow( hWnd,winsize );
				graphData.lineList.clear();
				graphData.pointList.clear();
			}
			break;
		case IDM_MST_PRIM:
			{
				//1.得到所有边
				//2.显示所有边
				if(! result_kruskal.empty())
				{
					for( list<Line>::iterator it = result_kruskal.begin(); it != result_kruskal.end(); it++ )
					{
						it -> penColor = green ;
						drawLine( hWnd,*it ) ;
					}
					result_kruskal.clear();
				}
				result_kruskal = mstPrim( graphData, graphData.pointList.front() );
				if( ! result_kruskal.empty() )
				{
					for( list<Line>::iterator it = result_kruskal.begin(); it != result_kruskal.end(); it++ )
					{
						it -> penColor = red ;
						drawLine( hWnd,*it ) ;
						Sleep(1000);
					}
				}

			}
			break;

		case IDM_MST_KEUSKAL:
			{
				////1.得到所有边
				////2.显示所有边
				if(! result_kruskal.empty())
				{
					for( list<Line>::iterator it = result_kruskal.begin(); it != result_kruskal.end(); it++ )
					{
						it -> penColor = green ;
						drawLine( hWnd,*it ) ;
					}
					result_kruskal.clear();
				}
				result_kruskal = mstKruskal( graphData );
				if( ! result_kruskal.empty() )
				{
					for( list<Line>::iterator it = result_kruskal.begin(); it != result_kruskal.end(); it++ )
					{
						it -> penColor = red ;
						drawLine( hWnd,*it ) ;
						Sleep(1000);
					}
				}
			}
			break;

		case IDM_SET_SEARCH:
			{
				int* ssdata = setSsearchAlgorithm( graphData );
				int i=0;
				for( list<Point>::iterator it=graphData.pointList.begin(); it != graphData.pointList.end(); it++)
				{
					(*it).brushColor = RGB(255-ssdata[i]*70,ssdata[i]*70,100+ssdata[i]*70);
					i++;
					drawPoint(hWnd,*it);
				}
			}
			break;
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		case IDM_FILE_SAVE:
			{
				saveGraph( graphData ) ;
			}
			break;
		case IDM_FILE_OPEN:
			{
				graphData.pointList.clear( );
				graphData.lineList.clear( );
				result_kruskal.clear( );
				clearWindow( hWnd,winsize );
				openGraph( graphData );
				drawGraph( hWnd,graphData );
			}
			break;
		case IDM_INSERT_NODE:
			nowState = CommondState::insertNodeState ;
			break ;
		case IDM_INSERT_OVER:
			nowState = CommondState::emptyState ;
			break ;
		case IDM_INSERT_LINE:
			nowState = CommondState::insertLineState ;
			break;
		case IDM_SEARCH_START :
			nowState = CommondState::selectStartState ;
			break;
		case IDM_SEARCH_END :
			nowState = CommondState::selectEndState ;
			break ;
		case IDM_SEARCH_OVER :
			nowState = CommondState::emptyState ;
			{
				if( ! result.empty() )
				{
					for( list<Line>::iterator it = result.begin(); it != result.end(); it++ )
					{
						it->penColor = green ;
						drawLine( hWnd,*it ) ;
					}
				}

				if( start.legal(winsize) && end.legal(winsize) )
				{
					result = singleDistance( graphData.pointList,graphData.lineList,start,end );
					if( ! result.empty() )
					for( list<Line>::iterator it = result.begin();it != result.end(); it++ )
					{
						Sleep(1000);
						it->penColor = red;
						drawLine( hWnd,*it );
					}


				}

			}
			break;
		case IDM_DATA_OPEN:
			{
				if( AllocConsole() )
				{
					freopen("CONOUT$","w",stdout);
					cout<<graph_data[start.key-'A'][end.key-'A']<<endl;
					for(list<Line>::iterator  it=graphData.lineList.begin(); it != graphData.lineList.end(); it++)
					{
						cout<<(*it).start.key<<" <-> "<<(*it).end.key<<" "<<(*it).weight<<endl;
					}
				}
				else
				{
					FreeConsole();
					AllocConsole() ;

					freopen("CONOUT$","w",stdout);
					cout<<graph_data[start.key-'A'][end.key-'A']<<endl;
					for(list<Line>::iterator  it=graphData.lineList.begin(); it != graphData.lineList.end(); it++)
					{
						cout<<(*it).start.key<<" <-> "<<(*it).end.key<<" "<<(*it).weight<<endl;
					}

				}
			}
			break;
		case IDM_DATA_CLOSE:
			{
				FreeConsole();
			}
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam) ;
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		  
		// TODO: 在此添加任意绘图代码...
		{
			//1.画出边界
			//2.画出所有节点
			//3.画出所有边
			//Line bianjie ;
			//bianjie.start.x = winsize.screenX / 4 * 3;
			//bianjie.start.y = 0;

			//bianjie.end.x = winsize.screenX / 4 * 3 ;
			//bianjie.end.y = winsize.screenY ;
			//drawLine( hWnd,bianjie );


			//drawGraph(hWnd,graphData);
		}

		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	case WM_LBUTTONDOWN:
		switch( nowState  )
		{
		// 插入节点
		case CommondState::insertNodeState:
			{
				// 获取位置
				myPoint->x = LOWORD(lParam);
				myPoint->y = HIWORD(lParam);
				if( myPoint->legal(winsize) )
				{
					drawPoint(hWnd,*myPoint);

					// 制作关键字
					if(! graphData.pointList.empty())
						greet[0] = TCHAR(graphData.pointList.back().key+1);
					myPoint->key = (char)greet[0];
					TextOut( GetDC(hWnd),myPoint->x - 5,myPoint->y - myPoint->r * 3,greet,1 ) ;
					

					//greet[0] ++;

					// 保存节点
					graphData.pointList.push_back(*myPoint);
				}

			}
			break;

		case CommondState::insertLineState:
			{
				if(myline->down == false)
				{
					// 获取位置
					Point point ;
					point.x = LOWORD(lParam) ;
					point.y = HIWORD(lParam) ;

					// 检查模糊节点
					bool  result = checkPointInList(point,graphData.pointList) ;

					if( result )
					{
						// 标记按下
						myline -> down = true ;
						myline -> start = point;
						myline -> end = point;
					}
				}
			}
			break ;	

		case CommondState::selectStartState:
			{
				//1.获取坐标
				//2.检查坐标
				//3.如果是节点:保存起点
				//4.否则继续寻找

				Point point ;
				point.x = LOWORD(lParam) ;
				point.y = HIWORD(lParam) ;


				bool result = checkPointInList( point,graphData.pointList );
				if( result )
				{
					if( start.legal(winsize) )
					{
						start.brushColor = green;
						drawPoint(hWnd,start);
					}

					start = point;
					start.brushColor = red;
					drawPoint(hWnd,start);
				}
			}
			break;

		case CommondState::selectEndState:
			{
				//1.获取坐标
				//2.检查坐标
				//3.如果是节点:保存起点
				//4.否则继续寻找

				Point point ;
				point.x = LOWORD( lParam ) ;
				point.y = HIWORD( lParam ) ;

				bool result = checkPointInList( point,graphData.pointList );
				if( result && checkTwoPoint( point,start ) == false )
				{
					if( end.legal( winsize ) )
					{
						end.brushColor = green ;
						drawPoint( hWnd,end ) ;
					}
					
					end = point;
					end.brushColor = blue ;
					drawPoint(hWnd,end) ;
				}
			}
			break;
		}

		break;

	case WM_MOUSEMOVE:
		{
			if( nowState == CommondState::insertLineState && myline->down == true )
			{
				drawLine(hWnd,*myline);
				Point point ;
				point.x = LOWORD(lParam) ;
				point.y = HIWORD(lParam) ;
				myline->end = point;
				drawLine( hWnd,*myline);
			}
		}

		break;

	case WM_LBUTTONUP:
		{
			if( nowState == CommondState::insertLineState && myline->down == true)
			{
				// 擦除上一条
				drawLine( hWnd,*myline) ;
				Point point ;
				point.x = LOWORD(lParam) ;
				point.y = HIWORD(lParam) ;

			
				// 检测节点
				bool result = checkPointInList(point,graphData.pointList);
				if( result && checkTwoPoint(point,myline->start) == false )
				{
					myline->end = point ;
					myline->down = false ;
					myline->realLine = true ;
					myline->weight = disTwoPoint(myline->start,myline->end);
					drawLine( hWnd,*myline ) ;					
					graphData.lineList.push_back( *myline ) ;	
					myline ->realLine = false ;

				}	

				// 错误抬起
				else if(result == false) 
				{
					drawLine( hWnd,*myline);
				}
			}		
		}
		break;


	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

class.h
#ifndef class_h
#define class_h



#include <list>
#include <iostream>
using namespace std;

#define green RGB(50,205,50)
#define red RGB(255,0,0)
#define blue RGB(0,0,255)
#define white RGB(255,255,255)


#define al_red 1
#define al_white 2
#define al_black 3


class WindowSize
{
public:
	int screenX ;
	int screenY ;
	WindowSize()
	{
		screenX = screenY = 0;
	}

};





class Point
{
public:
	int x;
	int y;
	int r;
	char key;
	COLORREF brushColor;


	

	Point( )
	{
		x = 0;
		y = 0;
		r = 10;
		key = '*';
		brushColor =  green;
	}

	Point(const int & x,const int & y,const char &key )
	{
		this->x = x;
		this->y = y;
		r = 10;
		this->key = key ;
		brushColor =   green;

	}

	Point(const int &x,const int & y)
	{
		this->x = x;
		this->y = y;
		r = 10;
		this->key = '*' ;
		brushColor =   green;


	}

	Point(const Point & point)
	{
		this->x = point.x;
		this->y = point.y;
		r = 10;
		this->key = point.key;
		brushColor = point.brushColor;
	}

	bool legal(const WindowSize  &mywin)
	{
		bool result = true ;
		if(x <= 0 || x >= mywin.screenX || y <= 0 || y >= mywin.screenY)
		{
			result = false;
		}
		return result;
	}

};


class Line
{
public:
	Point start;
	Point end;
	int weight;
	bool down ;
	bool realLine;
	int penWidth;
	COLORREF penColor;
	Line()
	{
		realLine = false;
		penWidth = 2;
		penColor = green;
		down = false;
		weight = -1;
	}




};





class DataSet
{
public:
	list<Point>  pointList ;
	list<Line>  lineList ;
};


#endif

dijkstra算法
dis_algo_graph.h
#ifndef ALGO_H
#define ALGO_H


#include <iostream>
#include <list>
#include "class.h"
#include <utility>
#include <queue>
#include "function.h"
#include <string>
#include <map>
using namespace std;

static int ** graph_data ;
static char startkey;

class Node 
{
public: 
	
	char key;



	Node( char key )
	{
		this -> key = key;
	}
	
	Node()
	{
		key = '*';
	}


};

bool operator< (const Node & a,const Node & b)
{
	return graph_data[startkey-'A'][a.key-'A'] > graph_data[startkey-'A'][b.key-'A'];
}
list<Line> findByMap( list<char> & road, list<Line>& linelist );


list<Line> singleDistance( list<Point> & pointlist,list<Line> & linelist,const Point & start,const Point & end)
{
	//disktra algorithm
	//1.利用邻接矩阵存储数据
	//2.利用优先队列:
	//	1)放入起点
	//	2)以此寻找终点

	int* color = new int[pointlist.size()];
	int* parent = new int[pointlist.size()];

	for(int i=0; i<pointlist.size(); i++)
	{
		color[i] = al_white;
		parent[i] = -1;
	}
	
	graph_data = new int*[ pointlist.size() ];
	for( int i=0; i<pointlist.size(); i++ )
		graph_data[i] = new int[ pointlist.size() ];

	for( int i=0; i<pointlist.size(); i++)
		for( int j=0; j<pointlist.size(); j++)
		{
			graph_data[i][j] = -1;
			if( i == j )
				graph_data[i][j] = 0;
		}

	for(list<Line>::iterator it = linelist.begin(); it != linelist.end(); it ++)
	{
		graph_data[(*it).start.key-'A'][(*it).end.key-'A'] = disTwoPoint((*it).start,(*it).end);
		graph_data[(*it).end.key-'A'][(*it).start.key-'A'] = disTwoPoint((*it).start,(*it).end);
	}
	
	priority_queue<Node,vector<Node>,less<vector<Node>::value_type>> Q;
	list<char> result ;

	Node first(start.key);
	color[start.key-'A'] = al_red;
	Q.push( first );
	Node now ;
	startkey = start.key;
	while(! Q.empty() )
	{
		now = Q.top();
		color[now.key-'A'] = al_black;
		Q.pop();
		
		if( now.key == end.key )
			break;
		for(int i=0; i<pointlist.size(); i++)
		{
			if(  now.key - 'A' != i && graph_data[now.key-'A'][i] != -1 )
			{
				if( color[i] == al_white )
				{
					parent[i] = now.key - 'A';

					graph_data[start.key-'A'][i] = graph_data[now.key-'A'][i] + graph_data[start.key-'A'][now.key-'A'] ;
					first.key = 'A' + i ;
					color[i] = al_red;
					Q.push( first ) ;
				}

				else if( color[i] = al_red )
				{

					if( graph_data[start.key-'A'][i] > graph_data[now.key-'A'][i] + graph_data[start.key-'A'][now.key-'A'] )
					{
						list<Node> zhongjian;
						while(! Q.empty() )
						{
							zhongjian.push_back(Q.top());
							Q.pop();
						}
						parent[i] = now.key - 'A';
						graph_data[start.key-'A'][i] = graph_data[now.key-'A'][i] + graph_data[start.key-'A'][now.key-'A'] ;
						while( ! zhongjian.empty() )
						{
							Q.push( zhongjian.front() );
							zhongjian.pop_front();
						}		
					}
			
				}
			}
		}
	}

	char road = end.key;
	while( road != start.key )
	{
		if( parent[road-'A'] == -1)
			break;
		result.push_front( road );
		road = 'A'+ parent[road-'A'];
	}
	if(! result.empty())
	result.push_front(road);
	
	return findByMap(result,linelist);

}


list<Line> findByMap( list<char> & road,list<Line>& linelist )
{
	//1.实用map保存数据
	//2.搜素数据
	//3.返回结果

	string strnull;
	map<string,Line> mymap;
	for(list<Line>::iterator it=linelist.begin();it != linelist.end(); it++)
	{
		mymap.insert( make_pair(strnull +(*it).start.key + (*it).end.key,*it) );
		mymap.insert( make_pair(strnull +(*it).end.key + (*it).start.key,*it) );
	}

	list<Line> result;

	if(road.size() > 1)
		while(  road.size()>1 )
		{

			strnull = road.front();
			road.pop_front();
			strnull += road.front();
			 
			result.push_back( mymap.find( strnull )->second );
		}
	return result;
}















#endif

function.h
#ifndef function_h
#define function_h


#include<iostream>
#include<math.h>
#include<fstream>
#include<list>
#include "class.h"
#include<map>
using namespace std;



void drawLine(HWND hwnd,Line  myline)
{
	HPEN pen,oldpen;
	pen = CreatePen(PS_SOLID,myline.penWidth,myline.penColor);
	HDC hdc = GetDC(hwnd);
	oldpen = (HPEN)SelectObject(hdc,pen);
	if(myline.realLine == false)
		SetROP2(hdc,R2_NOTXORPEN);
	else 
		SetROP2(hdc,R2_COPYPEN);
	MoveToEx(hdc,myline.start.x,myline.start.y,NULL);
	LineTo(hdc,myline.end.x,myline.end.y);


	SelectObject(hdc,oldpen);
	DeleteObject(pen);
	ReleaseDC(hwnd,hdc);
}


void drawPoint(HWND hwnd,const Point & mypoint)
{

	HBRUSH brush ;
	HPEN hpen,oldpen;
	hpen = CreatePen(PS_SOLID,4,mypoint.brushColor);
	brush = CreateSolidBrush(mypoint.brushColor);
	HDC hdc = GetDC(hwnd);
	oldpen = (HPEN) SelectObject( hdc,hpen);
	SelectObject( hdc,brush );
	SetROP2( hdc,R2_COPYPEN );

	Ellipse( hdc,mypoint.x - mypoint.r , mypoint.y - mypoint.r , mypoint.x + mypoint.r , mypoint.y + mypoint.r );

	SelectObject(hdc,oldpen);
	DeleteObject(hpen);
	ReleaseDC(hwnd,hdc);
}


bool checkTwoPoint(const Point & a,const Point & b)
{
	bool result = false;
	int abx = abs(a.x - b.x);
	int aby = abs(a.y - b.y);

	if(abx*abx + aby*aby < a.r*a.r )
		result = true ;
	return result;
}


bool checkPointInList( Point &a, list<Point> mylist )
{
	bool result = false ;
	list<Point>::iterator it ;
	if(! mylist.empty())
		for( it = mylist.begin(); it != mylist.end(); it ++ )
		{
			if( checkTwoPoint(a,*it) == true )
			{
				result = true ;
				a = (*it) ;
				break ;
			}
		}
	return result;
}

int disTwoPoint(const Point & start,const Point & end)
{
	int x_w = abs(end.x - start.x);
	int y_w = abs(start.y - end.y);
	return (int)sqrt(float(x_w*x_w + y_w*y_w));
}


void drawGraph(HWND hWnd, DataSet & graphData)
{
	TCHAR greet[1] ;
	if(! graphData.pointList.empty())
	{
		for(list<Point>::iterator it = graphData.pointList.begin(); it != graphData.pointList.end(); it++)
		{
			greet[0] = (*it).key ;
			TextOut( GetDC(hWnd),(*it).x - 5,(*it).y - (*it).r*3,greet,1 ) ;
			drawPoint(hWnd,*it) ;
		}
	}


	if(! graphData.lineList.empty())
	{
		for(list<Line>::iterator it = graphData.lineList.begin(); it!=graphData.lineList.end(); it++)
		{
			drawLine(hWnd,*it);
		}
	}
}

void saveGraph( DataSet & graphData )
{
	//1.保存所有节点
	//2.保存所有边

	ofstream writer;
	writer.open("graph.txt");
	writer<<graphData.pointList.size()<<endl;
	for(list<Point>::iterator it = graphData.pointList.begin();it != graphData.pointList.end();it++)
	writer<<(*it).key<<" "<<(*it).x<<" "<<(*it).y<<endl;
	writer<<graphData.lineList.size()<<endl;
	for(list<Line>::iterator it = graphData.lineList.begin(); it != graphData.lineList.end(); it++)
	writer<<(*it).start.key<<" "<<(*it).end.key<<endl;
	writer.close();
}

void openGraph( DataSet & graphData )
{
	//1.读取所有节点
	//2.读取所有边

	ifstream reader;
	reader.open("graph.txt");
	map<char,Point> mymap;
	int i;
	Point point ;
	Line line ;
	for( reader>>i;i>0;i-- )
	{
		reader>>point.key;
		reader>>point.x;
		reader>>point.y;
		graphData.pointList.push_back( point );
		mymap.insert( make_pair( point.key,point ) );
	}

	for( reader>>i; i>0; i-- )
	{
		reader>>line.start.key ;
		line.start = ( mymap.find(line.start.key) )-> second ;
		reader>>line.end.key ;
		line.end = ( mymap.find(line.end.key) )-> second ;

		line.realLine = true ;
		line.weight = disTwoPoint( line.start,line.end ) ;
		graphData.lineList.push_back( line );

	}

	reader.close();
}

void clearWindow( HWND hwnd,const WindowSize & winsize )
{
	HBRUSH brush;
	brush = CreateSolidBrush( white );
	SelectObject( GetDC(hwnd),brush );
	Rectangle( GetDC(hwnd),0,0,winsize.screenX,winsize.screenY );
	DeleteObject( brush );
}

#endif

globalVariable.h
#ifndef globalVariable_h
#define globalVariable_h



#include <list>
#include "class.h"


class CommondState
{
public:
	static const int emptyState = 0;
	static const int insertNodeState = 1;
	static const int insertLineState = 2;
	static const int selectStartState = 3;
	static const int selectEndState = 4;

};









#endif

MST_KRUSKAL.h
#ifndef mst_kruskal
#define mst_kruskal

#include "class.h"
#include "function.h"
#include <iostream>
#include <list>
using namespace std;


int * mark;

bool linecom (const Line & a,const Line & b)
{
	return a.weight < b.weight;
}


void kruskal_union(const int & a,const int & b,const int & n);

list<Line> mstKruskal( DataSet dataset )
{
	/*
	1.对所有边排序
	2.依次找出最小的边,在保证不成环的情况下并连接
	3.返回边集合
	*/

	// 1
	const int n = dataset.pointList.size();
	mark = new int[n];
	for(int i=0;i<n;i++)
	{
		mark[i] = i;
	}
	dataset.lineList.sort( linecom );

	// 2 
	list<Line> result;
	Line edge;
	while( ! dataset.lineList.empty() )
	{
		edge = dataset.lineList.front();
		dataset.lineList.pop_front();
		if( mark[ edge.start.key - 'A' ] != mark[ edge.end.key - 'A' ] )
		{
			result.push_back(edge);
			kruskal_union(mark[ edge.start.key - 'A' ],mark[ edge.end.key - 'A' ],n);
		}
	}

	// 3
	return result;
}

void kruskal_union( const int & a,const int & b,const int & n )
{
	int min_num = min(a,b);
	int max_num = max(a,b);
	for(int i=0;i<n;i++)
	{
		if( mark[i] == max_num )
			mark[i] = min_num;
	}
}














#endif

MST_PRIM.h
#ifndef MST_PRIM
#define MST_PRIM

#include <iostream>
#include <list>
#include "class.h"
#include <utility>
#include <queue>
#include "function.h"
#include <string>
#include <map>
using namespace std;


static int * mst_prior_queue_key;
static int ** mst_graph_data;
static int n;

class PriorNode
{
public:
	int data;
	PriorNode()
	{
		data = MAXINT;
	}


};

bool operator < ( const PriorNode & a , const PriorNode & b )
{
	return mst_prior_queue_key[a.data] > mst_prior_queue_key[b.data] ;
}

list<Line> findByMapWithMST( list<pair<char,char>> & road,list<Line>& linelist );

list<Line> mstPrim(DataSet & dataset ,const Point & start)
{
	//1.初始化优先队列和key值
	//2.以此取出最小的邻边,并不断更新key值
	//3.返回结果边集合

	// 1
	priority_queue<PriorNode,vector<PriorNode>,less<vector<PriorNode>::value_type>> Q;
	PriorNode node,innode;
	int num_node = dataset.pointList.size();
	n = num_node; 
	int *al_color = new int[dataset.pointList.size()];

	mst_graph_data = new int*[num_node];
	for( int i=0; i<num_node; i++ )
	{
		mst_graph_data[i] = new int[num_node];
		for( int j=0;j<num_node;j++ )
		{
			mst_graph_data[i][j] = MAXINT;
			if( i == j )
				mst_graph_data[i][j] = 0;
		}
	}	
	for(list<Line>::iterator it = dataset.lineList.begin(); it != dataset.lineList.end();  it ++)
	{
		mst_graph_data[(*it).start.key-'A'][(*it).end.key-'A'] = (*it).weight;
		mst_graph_data[(*it).end.key-'A'][(*it).start.key-'A'] = (*it).weight;
	}
	mst_prior_queue_key = new int[num_node];
	for(int i=0;i<num_node;i++)
		mst_prior_queue_key[i] = MAXINT;
	mst_prior_queue_key[start.key - 'A'] = 0;

	// 2
	list<pair<char,char>> result;
	int * parent = new int[num_node];
	for(int i=0;i<num_node;i++)
	{
		parent[i] = MAXINT;
		al_color[i] = al_white;
	}
	node.data = start.key-'A';
	al_color[node.data] = al_red;
	Q.push( node );
	while( ! Q.empty() )
	{
		node = Q.top();
		al_color[node.data] = al_black ;
		if( node.data != start.key - 'A' )
			result.push_back( make_pair( parent[node.data]+'A' , node.data+'A' ) );
		Q.pop();
		
		for( int i=0; i < num_node; i++ )
		{		
			if( al_color[i] == al_red )
			{
				if( mst_graph_data[node.data][i] < mst_prior_queue_key[i] )
				{
					list<PriorNode> zhongjian ;
					while(! Q.empty() )
					{
						zhongjian.push_back(Q.top());
						Q.pop();
					}
					mst_prior_queue_key[ i ] = mst_graph_data[node.data][i] ;
					parent[i] = node.data ;
					while( ! zhongjian.empty() )
					{
						Q.push( zhongjian.front() );
						zhongjian.pop_front();
					}
				}
			}
			else if( al_color[i] == al_white )
			{
				if( mst_graph_data[node.data][i] < mst_prior_queue_key[i] )
				{
					mst_prior_queue_key[ i ] = mst_graph_data[node.data][i] ;
					parent[i] = node.data ;					
					al_color[i] = al_red;
					innode.data =  i;
					Q.push( innode );				
				}
			}
		}
	}

	return findByMapWithMST(result,dataset.lineList);
}


list<Line> findByMapWithMST( list<pair<char,char>> & road,list<Line>& linelist )
{
	//1.实用map保存数据
	//2.搜素数据
	//3.返回结果

	string strnull;
	map<string,Line> mymap;
	for(list<Line>::iterator it=linelist.begin();it != linelist.end(); it++)
	{
		mymap.insert( make_pair(strnull +(*it).start.key + (*it).end.key,*it) );
		mymap.insert( make_pair(strnull +(*it).end.key + (*it).start.key,*it) );
	}

	list<Line> result;

	while(  road.size()>0 )
	{

		strnull = road.front().first;		
		strnull += road.front().second;
		road.pop_front();

		result.push_back( mymap.find( strnull )->second );
	}
	return result;
}


#endif


并查集算法
SS_algo_graph.h
#ifndef SS_H
#define SS_E

#include <iostream>
#include <list>
#include "class.h"
using namespace std;

//0.并查集
//1.给每个节点设置标志颜色位
//2.检查每一条边,是否可以合并
//3.合并边中的两个点所在的集合
//4.返回图的颜色集合

void set_union(const int & a,const int & b,const int & n);

int * pointset;
int * setSsearchAlgorithm( DataSet & graph ) 
{
	const int n = graph.pointList.size();
	const int m = graph.lineList.size();
	pointset = new int[ n ];
	bool ** edgeset = new bool*[ m ];
	for ( int i=0;i<n;i++ )
		pointset[i] = i;	
	for( int i=0;i<m;i++ )
	{
		edgeset[i] = new bool[m];
		for (int j =0;j<m;j++)
		{
			edgeset[i][j] = true;
		}
	}

	for(list<Line>::iterator it = graph.lineList.begin();it != graph.lineList.end();it++)
	{
		if(edgeset[(*it).start.key-'A'][(*it).end.key-'A'] == true)
		{
			if(pointset[(*it).start.key-'A'] != pointset[(*it).end.key-'A'])
			{
				set_union(pointset[(*it).start.key-'A'] , pointset[(*it).end.key-'A'],n);
			}
			edgeset[(*it).start.key-'A'][(*it).end.key-'A'] = false;
		}		
	}

	return pointset;
}

void set_union(const int & a,const int & b,const int & n)
{
	int min_num = min(a,b);
	int max_num = max(a,b);
	for(int i=0;i<n;i++)
	{
		if( pointset[i] == max_num )
			pointset[i] = min_num;
	}
}

#endif

源程序打包下载地址: http://pan.baidu.com/s/1kTxFiZl


常用数据结构图--拓扑排序 图 在数学中,一个图(Graph)是表示物件与物件之间的关系的数学对象,是图论的基本研究对象。 图是十分重要的数据结构,常常被应用于实际生活的应用之中。生活中常见的问题例如交通路线图、任务指定分配、工期计算、航空网络等,都可以使用图相关的理论来建立模型。下面是《数据结构与算法分析》对图的若干定义 一个图(Graph)G = (V, E)由顶点(vertex)集和边(Edge)集E组成。每一条 阅读详情

相关推荐

ENSP之配置静态路由

ENSP之配置静态路由 两台路由器两台PC 拓扑图如下: 配置AR1线路上的两条IP地址 配置AR2线路上的两条IP地址 3.AR2上 配置静态IP 路由 AR1上 配置静态IP 路由 设置两台PC 的IP地址 网关 PC1 PC2 全部配置好了之后 现在测试PC1是否ping 得通PC2 在命令行输入 成功的话如下图 ...

浪友与泪的博客 3545

数据结构--图总结(八大算法)

图总结 本章主要讲诉一些图的经典算法以及容易忘记的概念便于以后进行复习。 文章目录图总结一、易混淆的概念二、经典算法1.DFS与BFS2.读入数据总结 一、易混淆的概念 边,弧:顶点到顶点之间有向叫做边,无向叫做弧。 完全图,连通图:任意两个顶点之间都有边是完全图,任意两个顶点之间存在路劲是连通图(如果是有向的话叫强连通图)。 生成树,有向树,生成深林:无向联通图中如果只有n个顶点n-1条边(没有环)叫生成树,有向图中只有一个顶点入度为0,其余顶点入度为1叫做有向树。一个有向图由若干个有向树构成生成深林

qq_41409979的博客 2890

当LightGBM推理遇上GPU:3种替代方案性能对比(含ONNX实战代码)

本文针对LightGBM官方不支持GPU推理的性能瓶颈,深度评测了RAPIDS cuML、ONNX Runtime GPU和Triton Inference Server三种GPU加速推理替代方案。通过详尽的性能对比和实战代码,为高并发、低延迟的在线预测场景提供了清晰的选型指南,帮助工程师打破推理性能枷锁,实现显著的吞吐量提升。

salt9的博客 813

数据结构算法--图详解

图G由顶点集合V和边集合E组成,记为。:有向图和无向图。,如果,则G’为G的子图。:n(n - 1)条边的有向图。:n(n - 1) / 2条边的无向图。:图的每条边带有权值。:无向图,一条边的两点互为邻接点。:顶点v到顶点v'的边的权值和为路径长度。:无向图G,如果顶点v到顶点v'存在路径,则两顶点连通。G是一个连通图, G中的极大连通子图为连通分量。:有向图G,如果顶点v到顶点v'存在路径,则两顶点强连通。强连通图只有一个连通分量。

jy18817386398的博客 1551

千兆以太网PHY设计:PCB原理图完整示例

深入解析千兆以太网PHY电路设计要点,提供完整的PCB原理图设计实例,帮助工程师掌握高速信号布局与电源去耦等关键技术,提升设计稳定性与信号完整性。

weixin_30633869的博客 628

基于TI MSPM0的PS2双轴按键摇杆模块ADC+GPIO驱动移植实战

本文详细介绍了在TI MSPM0微控制器上驱动PS2双轴按键摇杆模块的完整实战流程。通过SysConfig图形化工具配置ADC与GPIO引脚,并编写了包含ADC采样、按键检测及数据处理的驱动代码,实现了对摇杆X/Y轴模拟量及按键数字量的稳定读取,为嵌入式控制项目提供了可直接移植的解决方案。

weixin_42465140的博客 83

数据结构:图及相关算法讲解

图及相关算法讲解

2301_76269963的博客 1860

Veritas NetBackup 10.1 Windows安装指南:从账户配置到完整部署

本文详细介绍了Veritas NetBackup 10.1在Windows系统上的完整安装流程,从账户配置到部署验证。重点讲解了创建专用服务账户、安装组件选择、许可证输入等关键步骤,并提供了常见问题排查和进阶配置建议,帮助用户顺利完成企业级备份解决方案的部署。

weixin_26765287的博客 453

30.图

问题:为什么要有图? 前面我们学了线性表(一对一)和树(一对多) 线性表局限于一个直接前驱和一个直接后继的关系 树也只能有一个直接前驱也就是父节点 当我们需要 表示多对多的关系时, 这里我们就用到了 图 图的举例说明: 图是一种数据结构,其中结点可以具有零个或多个相邻元素。两个结点之间的连接称为边。 结点也可以称为顶点。如图: 图的常用概念 顶点(verte...

weixin_43719015的博客 379

夸克缓存视频合并小工具

原理 使用windows的命令行的copy命令来合并 copy /b 0+1+2+3 new.ts 分析缓存目录结构,发现都是一个m3u8文件带一个同名文件夹 所以分析m3u8并把原来的路径换成这个缓存文件夹路径并按顺序合并即可。 其中碰到的难点是Qprocess在windows不好使,索性直接存成.bat批处理文件再执行 还有就是中文问题,具体在代码里都说了。 代码 (环境Qt5.7.0) 这是mainwindow.h #ifndef MAINWINDOW_H #defin.

natural_Caduceus 1万+

【制作100个unity游戏之30】使用unity实现一款2d俯视角RPG战斗游戏,主要使用InputSystem+有限状态机+A*寻路实现(完结,附带项目源码)

【制作100个unity游戏之30】使用unity实现一款2d俯视角RPG战斗游戏,主要使用InputSystem+有限状态机+A*寻路实现

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 4652

数据结构图的经常使用算法总结

数据结构图的经常使用算法总结 本人在校期间写了一个win32应用程序,用于回想算法导论图的经常使用算法(图中边的权值为两个圆心的像素点的距离) 1.dijkstra算法求两点之间最短路径: 贪心算法用优先队列实现,每次选择距离起点路径和最短的顶点弹出队列,此顶点最短路径就已经确定 初始图例如以下 选择起点如W 选择终点例如以下: 显示路线: ...

weixin_30896511的博客 234

OpenClaw安卓手机攻略

想在安卓手机上安装 OpenClaw,目前主要有两种主流方法:一种是使用专门的,操作简单直观;另一种是在命令行环境下进行,自由度更高。你可以根据自己的偏好和动手能力来选择。

suny8的专栏 2899

unet网络自定义训练代码_OCR模型训练

点击上方“蓝字”关注我们作者 |李虎编辑 |张婵OCR 从流程上包括两步:文本检测和文本识别,即将图片输入到文本检测算法中得到一个个的文本框,将每个文本框分别送入到文本识别算法中得到识别结果。1.基于深度学习的文本检测算法大致分为两类:基于候选框回归的算法和基于分割的算法。基于候选框回归的文本检测,是源于目标检测算法,然后结合文本框的特点改造而成的,包括 CTPN、EAST 和 ...

weixin_39894233的博客 1047

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

软件概要设计与详细设计的区别

概要设计与详细设计的区别 概要设计就是设计软件的结构,包括组成模块,模块的层次结构,模块的调用关系,每个模块的功能等等。同时,还要设计该项目的应用系统的总体数据结构和数据库结构,即应用系统要存储什么数据,这些数据是什么样的结构,它们之间有什么关系。 详细设计阶段就是为每个模块完成的功能进行具体的描述,要把功能描述转变为精确的、结构化的过程描述。 概要设计阶段通常得到软件结构图 详细设计阶段常用的描述方式有:流程图、N-S图、PAD图、伪代码等 概要设计和详细设计 在软件设计中,大家经常问到的一个问题是:概要

qq_43842093的博客 4837

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

科研绘图工具与可视化

本文介绍了科研绘图的常用工具:1PPT/Visio适合流程图和神经网络结构图;2Matlab支持高质量数学图形;3OriginPro是科学绘图首选;4algorithm-visualizer可可视化算法;5Python+Matplotlib/Seaborn提供灵活可视化方案;6Adobe Illustrator用于专业矢量图;7神经网络可视化推荐Netron等工具。各工具均提供下载方式和使用参考链接。(149字)

2301_76610365的博客 983

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

WPF基础系列之 控件与布局

WPF基础系列之 控件与布局 WPF控件设计的理念    程序的本质是“数据+算法”:用户输入原始数据,算法处理原始数据并得到结果数据。问题在于程序如何将结果数据显示给用户。同样一组数组,可以用不同的形式进行显示。可以用控制台的方式。也可以用图形化用户界面的方式。GUI的方便之处在于它对数据表达的直观性,有效避免了一堆抽象数据的痛苦,提高了工作效率...

LHL62411570的专栏 454

【数据结构-图】图的常用算法

手工模拟图的各大常用算法

Mount256的博客 949

数据结构图题库

王道压缩矩阵的题在栈与队列里 网络课课后题 1、有向图G如下图所示,请写出所有拓扑排序序列。所有的顶点都直接用其数字标号表示,如拓扑排序序列为,那么请写成1234(中间没有空格)。不同的拓扑排序序列按照字典序排序,中间用一个空格隔开。 解析: 根据拓扑排序的定义,顶点1必须在顶点3前,顶点1、顶点2和顶点3必须在顶点4前,故排列可以为1234、1324、2134 答案: 1234 1...

闲狗的博客 1万+

数据结构图算法

图的算法题多种多样,但都是最基本的算法而来,只要深入理解图的数据结构与基本的算法,任何问题只要稍加思考就可以解决.

qq_55383558的博客 1605

数据结构图的主要算法

数据结构定义 #define maxsize 100 邻接矩阵 typedef struct { int no; }VertexType; typedef struct { int edges[maxsize][maxsize]; int n,e; VertexType vex[maxsize]; }MGraph; 邻接表 typedef struct ArcNode { int adj...

weixin_42708521的博客 1460

Yolov3、v4、v5、Yolox模型权重及网络结构图资源下载

大白在之前写过关于Yolo相关算法的文章,比如: (1)Yolov3&Yolov4的《深入浅出Yolo系列之Yolov3&Yolov4核心基础完整讲解》 (2)Yolov5的《深入浅出Yolo系列之Yolov5核心基础完整讲解》 其中提到很多网络模型的权重,由于不是国内资源,很多同学反馈不好下载。 而且文章中很多网络结构高清图,有些同学也想要下载,因此大白将整体的资源汇总,便于大家下载。 下载方式:关注微信公众号《江大白》,回复关键词 Yolo,提取下面所有资源的下载方式。 Yolov

江南研习社 12万+

【数据结构与算法】图的应用

1.Prim算法每次是选择一个顶点,Kruskal算法每次是选择一条边。2.Prim算法的时间复杂度只和顶点的个数有关,时间复杂度为,Kruskal算法的时间复杂度只和边有关,时间复杂度为。所以。

2301_79279099的博客 1218

蓝桥杯知识点汇总:基础知识和常用算法

此系列包含蓝桥杯(软件类)所考察的绝大部分知识点,算法,和写算法题必备的JAVA的基础语法,API,对想从C/C++转到JAVA组以及初学算法的同学会有帮助。

GD_ONE的博客 12万+

一文搞懂数据结构图:原理、分类、应用及C语言算法实现

图是一种非线性数据结构,它由顶点(Vertex,也称为节点)和边(Edge)组成。可以用二元组 $ G=(V, E) $ 来表示一个图,其中 $ V $ 是顶点的有限非空集合, $ E $ 是边的集合,边用于表示顶点之间的关系。边可以是有向的,也可以是无向的。在有向图中,边具有方向,用有序对 $ langle u, v rangle $ 表示从顶点 $ u $ 到顶点 $ v $ 的一条有向边;

李熠专用博客_白帽子一枚,人称低危终结者。免费收徒,有意者私信!!! 1157

数据结构图---拓扑结构

数据结构图---拓扑结构 【1】拓扑排序 在一个表示工程的有向图中,有顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为AOV网。 AOV网中的弧表示活动之间存在的某种制约关系。 所谓拓扑排序,其实就是对一个有向图构造拓扑序列的过程。 【2】拓扑排序算法 对AOV网进行拓扑排序的基本思路: 从AOV网中选择一个入度为0的顶点输出; 然后删除此顶...

凯凯王的博客 1万+
上一篇: stl prior_queue 插入bug
下一篇: c 接口学习与实现
p11323
博客等级 码龄14年 79粉丝 197原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值