Data structure shortest path course design (source code + experiment report + video explanation) (use self-collection)

XI`AN TECHNOLOGICAL UNIVERSITY

Curriculum Design Report

Experiment Course Name    Algorithms and Data Structures   

Major :         

class :              

Name :               

Student ID :         

Experimental hours :                        

Instructor :                     

Achievement :                        

        

  January  7 ,     2023    _

Table of contents

1. Experiment report

        1. Introduction

        2. Basic requirements

        3. Information description

        5. Detailed design

        6. Debugging and testing:

        8. Summary

 source code:

Video uploading is troublesome, students who need it can contact me


1. Experiment report

1. Introduction

Dijy Tesla algorithm thinking:

Let G=(V,E) be a weighted directed graph, divide the vertex set V into two groups, and find the vertex set of the shortest path (indicated by S, initially there is only one source point in S, and each time a source point is obtained in the future The shortest path will be added to the set S. Until all vertices are added to S, the algorithm will end). The second group is the remaining vertex collection (denoted by U) whose shortest path has not been determined, and the vertices of the second group are added to S in the ascending order of the shortest path length. During the joining process, the shortest path length from the source point V to each vertex in S is always greater than the shortest path length from the source point V to any vertex in V. In addition, each vertex corresponds to a distance. The distance of the vertex in S is the shortest path length from V to this vertex. The distance of the vertex in V is the current shortest distance from V to this vertex, which only includes the vertex in S as the intermediate vertex. path length.

2. Basic requirements

(1) Design the shortest path, including the following aspects:

1. Use the adjacency matrix to store a weighted directed graph.

2. Perform the shortest path from a source point to other vertices on the graph

3. Output the final result (path name, path length).

3. Information description

The establishment of the adjacency matrix includes: storing information with a two-dimensional array. There is no direct path to infinity.

Use a loop to determine the minimum value.

The final result is stored in a one-dimensional array. D[] stores the length of the shortest path from the source point to other vertices, P[] stores the subscript of the predecessor vertex of the shortest path of the vertex, and visit[] is the visit identifier. All the initial values ​​are set to F, firstly set the ID of the source point to T, and then each time the shortest path from a source point to other vertices is found, the ID corresponding to the subscript of the vertex is set to T. until all vertices are executed.

Output one-dimensional arrays D[] and P[], showing the final result.

  • overall design

5. Detailed design

  • The first part is to initialize the adjacency matrix. First, the distance from itself to itself must be 0, and then the rest of the nodes are initialized to MAX. Then, through a for loop, data is stored in the edge, and the printing function is used for verification.

  • The second part is for the creation of node classes (construction, copy construction, assignment operator overloading, and overloading of comparison methods). The subscript, shortest path length, and predecessor node of each node are stored in the class.

  •  Part 3: Print result function

  •  Dijkstra algorithm part (core)

After completing the initialization of the adjacency matrix, enter the coordinates of our starting point. For the starting point, the distance from the starting point to the starting point must be 0, and then put the starting point coordinates into the priority queue and enter the loop. The exit condition of the loop is that the priority queue is null

Every time you take the top element of the heap, use cur to save it, and then pop this node

Use cur to find all the nodes that can be reached from cur, save these nodes in the set S, and perform the following for all nodes in the set:

newlength = node[Index]._length + Graph[Index][back];

// If the new distance is less than the minimum distance before cur, cur will be reassigned and put into the queue

   if (newlength < node[back]._length)

   {

    node[back]._length = newlength;

    node[back]._prev = Index;

    q.push(node[back]);

   }

6. Debugging and testing:

When I write code, most of the problems can be solved by looking up information. How to use vector, if you use priority queue, and the source of ideas are also based on online information viewing, video explanation, the most time-consuming should be for custom types The determination of the comparison method of the third parameter of the priority queue, originally my code was implemented through structure and function pointers in this way, but there was also a problem of type mismatch, and finally written by using the overload of the comparison relationship in the class The bool type is overloaded with respect to the > symbol (because a large heap needs to be built).

7. Program list and execution results: There should be sufficient notes in the list

operation result:

source code:

//(1) Design the shortest path, including the following aspects:

//1 . Use the adjacency matrix to store a weighted directed graph.

//2 . Perform the shortest path from a source point to other vertices on the graph

// Yes, output the final result (path name, path length).

// 3. Information description

// The establishment of the adjacency matrix includes: storing information with a two-dimensional array. None if there is no direct path

// poor

// Use a loop to determine the minimum value

// The final result is stored in a one-dimensional array. D[] stores the shortest path from the source point to other vertices

// Length, P[] stores the subscript of the predecessor vertex of the shortest path of the vertex

// 0 1 2   0 4 10  1 2 3  1 4 7  2 0 4  2 3 4  3 4 5  4 2 3

#include<functional>

#include<stdlib.h>

#include<iostream>

using namespace std;

#include<vector>

#include<queue>

#define MAX 1000 // unreachable

int V, E, S; // number of vertices, number of edges, starting point

vector<vector<int>> Graph;

void CreateMyGraph() // Initialize the adjacency matrix

{

    cout << " Please enter the number of vertices and edges" << endl;

    cin >> V >> E;

    Graph.resize(V);

    for (int i = 0; i < V; i++)

    {

        Graph[i].resize(V);

        for (int j = 0; j < V; j++)

        {

            if (i == j)

                Graph [ i ][ j ] = 0; // Assign 0 to yourself

            else

                Graph [ i ][ j ] = MAX ;   // Default initialization until the rest of the vertices are MAX

        }

    }

    /*Graph[0][1] = 2;

    Graph[0][3] = 1;

    Graph[1][3] = 3;

    Graph[1][4] = 7;

    Graph[2][0] = 4;

    Graph[3][2] = 2;

    Graph[3][4] = 2;

    Graph[3][5] = 8;

    Graph[3][6] = 4;

    Graph[4][6] = 1;

    Graph[6][5] = 1;

    Graph[2][5] = 5;*/

    int begin, end;

    int length;

    for (int i = 0; i < E; i++)

    {

        cout << " Please enter the start point, end point, and weight of the first " << i + 1 << " edge:" << endl;

        cin >> begin >> end >> length;

        Graph [ begin ][ end ] = length;   // Initialize the adjacency matrix

    }

}

void PrintMyGraph()

{

    cout << " The adjacency matrix of the graph is stored as: " << endl;

    for (int i = 0; i < V; i++)

    {

        for (int j = 0; j < V; j++)

        {

            cout << Graph[i][j] << " ";

        }

        cout << endl;

    }

}

//typedef struct DjNode

//{

//  int _index;

//  int _length;

//  int _prev;

//}Node;

//Node BuyNode(int index, int length)

//{

//  Node* newnode = (Node*)malloc(sizeof(Node));

//  newnode->_index = index;

//  newnode->_length = length;

//  newnode->_prev = 0;

//  return newnode;

//}

//typedef bool (*PCOM)(const Node& left, const Node& right);

//bool Compare(const Node left, const Node right)

//{

//  return left._length > right._length;

//}

class Node

{

public:

    Node( int index , int length , int prev )

        : _index(index)

        , _length(length)

        , _prev( prev )

    {}

    Node(const Node& d)

    {

        _index = d._index;

        _length = d._length;

        _prev = d ._prev;

    }

    Node& operator=(const Node& node)

    {

        if (this != &node)

        {

            _index = node._index;

            _length = node._length;

            _prev = node._prev;

        }

        return *this;

    }

    bool operator>(const Node& d)const

    {

        return _length > d._length;

    }

    bool operator<(const Node& d)const

    {

        return _length < d._length;

    }

    int _index;

    int _length;

    int _prev;

};

class Com

{

public:

    bool operator()(const Node&left, const Node&right)const

    {

        return left._length > right._length;

    }

};

void Print_output(int start, vector<Node> node)

{

    cout << " The distance from " << start << " to the rest of the vertices is " << endl;

    for (int i = 0; i < V; i++)

    {

        if (i == start)

            continue;

        else

            cout << start << "->" << i << ": " << node[i]._length << endl;

    }

}

void Dijkstra_Algorithm()

{

    // 1. Initialize output arrays D and P

    //vector<int> D(V, MAX); // Initialize the shortest length array D

    //vector<int> P(V, 0); // Initialize the predecessor node array P

    vector<Node> node(V, Node(0,0,0));

    for (int i = 0; i < V; i++)

    {

        //node[i] = BuyNode(i, MAX); // node initialization

        node[i]._index = i;

        node[i]._length = MAX;

        node[i]._prev = 0;

    }

    // 2. Initialize the vertex D[S]

    cout << " Please enter the starting point" << endl;

    cin >> S;

    node[S]._length = 0;

    // 3. Create a priority queue, and the starting element enters the queue

    priority_queue<Node, vector<Node>, greater<Node>> q;

    q.push(node[S]);

    while (!q.empty())

    {

        Node cur = q.top();

        q.pop(); // Remove the top element of the heap and save it

        vector<int> pre_next;

        int Index = cur._index;

        for ( int i = 0; i < V; i++) // Save all the subscripts of elements that can reach the current node in one step to pre_next

        {

            if (Graph[Index][i] > 0 && Graph[Index][i] != MAX)

                pre_next.push_back(i);

        }

        while (!pre_next.empty()) // For each node that can reach cur

        {

            int back = pre_next.back();   // access one and take out one

            pre_next.pop_back();

            // The new distance is the distance from the source point to the back plus the distance from back to cur

            int newlength = node[Index]._length + Graph[Index][back];

            // If the new distance is less than the minimum distance before cur, reassign cur and put it into the queue

            if (newlength < node[back]._length)

            {

                node[back]._length = newlength;

                node[back]._prev = Index;

                q.push(node[back]);

            }

        }

    }

    cout << endl;

    Print_output(S, node);

}

void _Dijkstra_Algorithm()

{

    cout << "Dijkstra_Algorithm :" << endl;

    int choice;

    while (1)

    {

        cout << " Please enter:" << "[1] starts" << "[0] ends" << endl;

        cin >> choice;

        switch (choice)

        {

        case 1:

            Dijkstra_Algorithm();

            break;

        case 0:

            exit(0);

            break;

        }

    }

}

int main()

{

    int choice;

    while (1)

    {

        cout << "*******************************************" << endl;

        cout << "************** Please enter the request: *****************" << endl;

        cout << "****************[1] Initialize data *****************" << endl;

        cout << "****************[2] Dijkstra Algorithm************" << endl;

        cout << "***************[0]退出*********************" << endl;

        cout << "*******************************************" << endl;

        cin >> choice;

        switch (choice)

        {

        case 1:

            CreatMyGraph();

            break;

        case 2:

            _Dijkstra_Algorithm();

            break;

        case 0:

            exit(0);

            break;

        default:

            cout << " Input error, please re-enter" << endl;

            break;

        }

    }

    return 0;

}

8. Summary

Through this course design, I have further improved my understanding of data structures, improved my programming ability, and learned about the convenience of Dijkstra's algorithm in using priority queues to solve problems.

 source code:

//(1)设计最短路径,包含以下方面:
//1、用邻接矩阵存储一张带权有向图。
//2、对图进行从某一源点到其他各顶点的最短路径
//了、输出最后结果(路径名称、路径长度)。
//三、信息描述
//邻接矩阵建立包括 : 用二维数组存储信息。没有直达路径的为无
//穷
//用循环来判断最小值
//最终结果用一维数组存储。D[]存放源点到其他顶点的最短路径的
//长度,P[]存放该顶点最短路径的前驱顶点下标
// 0 1 2   0 4 10  1 2 3  1 4 7  2 0 4  2 3 4  3 4 5  4 2 3
#include<functional>
#include<stdlib.h>
#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#define MAX 1000 // 不可到达
int V, E, S; // 顶点数、边数、起点

vector<vector<int>> Graph;

void CreatMyGraph() // 初始化邻接矩阵
{
	cout << "请输入顶点数、边数" << endl;
	cin >> V >> E;
	Graph.resize(V);
	for (int i = 0; i < V; i++)
	{
		Graph[i].resize(V);
		for (int j = 0; j < V; j++)
		{
			if (i == j)
				Graph[i][j] = 0;	// 自己到自己赋值为0
			else
				Graph[i][j] = MAX;	// 默认初始化到其余顶点均为MAX
		}
	}
	/*Graph[0][1] = 2;
	Graph[0][3] = 1;
	Graph[1][3] = 3;
	Graph[1][4] = 7;
	Graph[2][0] = 4;
	Graph[3][2] = 2;
	Graph[3][4] = 2;
	Graph[3][5] = 8;
	Graph[3][6] = 4;
	Graph[4][6] = 1;
	Graph[6][5] = 1;
	Graph[2][5] = 5;*/
	int begin, end;
	int	length;
	for (int i = 0; i < E; i++)
	{
		cout << "请输入第" << i + 1 << "条边的起点、终点、权值:" << endl;
		cin >> begin >> end >> length;
		Graph[begin][end] = length;	// 初始化邻接矩阵
	}
}

void PrintMyGraph()
{
	cout << "图的邻接矩阵存储为:" << endl;
	for (int i = 0; i < V; i++)
	{
		for (int j = 0; j < V; j++)
		{
			cout << Graph[i][j] << " ";
		}
		cout << endl;
	}
}

//typedef struct DjNode
//{
//	int _index;
//	int _length;
//	int _prev;
//}Node;

//Node BuyNode(int index, int length)
//{
//	Node* newnode = (Node*)malloc(sizeof(Node));
//	newnode->_index = index;
//	newnode->_length = length;
//	newnode->_prev = 0;
//	return newnode;
//}

//typedef bool (*PCOM)(const Node& left, const Node& right);
//bool Compare(const Node left, const Node right)
//{
//	return left._length > right._length;
//}

class Node
{
public:
	Node(int index, int length, int prev)
		: _index(index)
		, _length(length)
		, _prev(prev)
	{}
	Node(const Node& d)
	{
		_index = d._index;
		_length = d._length;
		_prev = d._prev;
	}
	Node& operator=(const Node& node)
	{
		if (this != &node)
		{
			_index = node._index;
			_length = node._length;
			_prev = node._prev;
		}
		return *this;
	}
	bool operator>(const Node& d)const
	{
		return _length > d._length;
	}
	bool operator<(const Node& d)const
	{
		return _length < d._length;
	}
	int _index;
	int _length;
	int _prev;
};

class Com
{
public:
	bool operator()(const Node&left, const Node&right)const
	{
		return left._length > right._length;
	}
};

void Print_output(int start, vector<Node> node)
{
	cout << "由" << start << "到其余各顶点距离分别为" << endl;
	for (int i = 0; i < V; i++)
	{
		if (i == start)
			continue;
		else
			cout << start << "->" << i << ": " << node[i]._length << endl;
	}
}

void Dijkstra_Algorithm()
{
	// 1、初始化输出数组D、P
	//vector<int> D(V, MAX);	// 初始化最短长度数组D
	//vector<int> P(V, 0);	// 初始化前驱结点数组P
	vector<Node> node(V, Node(0,0,0));
	for (int i = 0; i < V; i++)
	{
		//node[i] = BuyNode(i, MAX); // 结点初始化
		node[i]._index = i;
		node[i]._length = MAX;
		node[i]._prev = 0;
	}

	// 2、初始化顶点D[S]
	cout << "请输入起点" << endl;
	cin >> S;
	node[S]._length = 0;

	// 3、创建优先队列,起点元素入队列
	priority_queue<Node, vector<Node>, greater<Node>> q; 
	q.push(node[S]);
	while (!q.empty())
	{
		Node cur = q.top();
		q.pop(); // 取出堆顶元素并进行保存
		vector<int> pre_next;
		int Index = cur._index;
		for (int i = 0; i < V; i++) // 将所有可以一步到达当前结点的元素下标全部保存到pre_next中
		{
			if (Graph[Index][i] > 0 && Graph[Index][i] != MAX)
				pre_next.push_back(i);
		}
		while (!pre_next.empty())	// 对于每一个可以到达cur的结点
		{
			int back = pre_next.back();	//访问一个取出一个
			pre_next.pop_back();

			// 新距离就为 从源点到back距离  加上  back到cur的距离
			int newlength = node[Index]._length + Graph[Index][back];

			// 如果新距离小于cur之前的最小距离,就将cur重新赋值,并入队列
			if (newlength < node[back]._length)
			{
				node[back]._length = newlength;
				node[back]._prev = Index;
				q.push(node[back]);
			}
		}
	}
	cout << endl;
	Print_output(S, node);
}

void _Dijkstra_Algorithm()
{
	cout << "Dijkstra_Algorithm :" << endl;
	int choice;
	while (1)
	{
		cout << "请输入:" << "[1]开始" << "[0]结束" << endl;
		cin >> choice;
		switch (choice)
		{
		case 1:
			Dijkstra_Algorithm();
			break;
		case 0:
			exit(0);
			break;
		}
	}
}

int main()
{
	int choice;
	while (1)
	{
		cout << "*******************************************" << endl;
		cout << "***************请输入请求:****************" << endl;
		cout << "***************[1]初始化数据***************" << endl;
		cout << "***************[2]迪杰斯特拉算法***********" << endl;
		cout << "***************[0]退出*********************" << endl;
		cout << "*******************************************" << endl;
		cin >> choice;
		switch (choice)
		{
		case 1:
			CreatMyGraph();
			break;
		case 2:
			_Dijkstra_Algorithm();
			break;
		case 0:
			exit(0);
			break;
		default:
			cout << "输入错误,请重新输入" << endl;
			break;
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_66151870/article/details/128753871