数据结构之旅行商问题(深度优先搜索)

简介: 旅行商问题(TSP)是寻找访问多个城市并返回起点的最短路径的经典问题。本文介绍了TSP的背景、应用、复杂性和解决方法,重点讲解了使用深度优先搜索(DFS)算法求解TSP的过程。通过邻接矩阵表示城市间的距离,利用访问数组和栈结构辅助DFS遍历,最终找到最优路径。此方法虽然能保证找到最优解,但时间复杂度高,适用于城市数量较少的情况。示例代码展示了算法的具体实现及结果分析。


1 旅行商问题(深度优先搜索)

旅行商问题(Traveling Salesman Problem,TSP)是运筹学和计算机科学领域中一个经典的组合优化问题。这个问题最早可以追溯到19世纪,当时它被描述为一个旅行推销员需要访问多个城市,寻找最短路径以完成任务。假设有一个推销员需要拜访多个城市,其目标是找到一条最短路径,使得他只需一次访问每个城市,最终回到出发地点。问题的关键是在城市之间存在不同的距离或成本,推销员需要找到最经济的路线,以最小化总行程或成本。

实际应用:

    物流和配送: TSP在物流和配送领域有广泛的应用。例如,货车司机、快递员或邮递员需要规划最优路径,以便在最短时间内完成所有配送任务。

    电路设计: 在电子设计自动化中,TSP可以用于优化电路中不同元件之间的连接,以最小化连接成本或最大化性能。

    通信网络规划: 在通信网络规划中,TSP可以用于确定数据包从一个节点到另一个节点的最短路径,以最大程度地减少传输延迟或成本。

问题复杂性:

    尽管TSP问题的形式相对简单,但它的复杂性却很高。具体而言,TSP是一个NP-困难问题,意味着没有已知的多项式时间算法可以在所有情况下找到最优解。这使得在大规模问题上找到最优解成为一个计算上的挑战。

解决方法:

    为了解决TSP,研究人员提出了各种各样的算法,包括穷举法、动态规划、分支限界法、近似算法等。每种方法都在特定情境下表现得更好,取决于问题的规模和特征。总的来说,旅行商问题作为一个经典而具有挑战性的组合优化问题,激发了许多研究人员探索解决方案,并在实际应用中产生了广泛而深远的影响。

2 数据结构和思维导图

邻接矩阵:

该图使用邻接矩阵 () 表示。graph[MAX][MAX]

    它有效地捕获了每对城市之间的距离。

    矩阵是对称的,因为从城市 i 到城市 j 的距离与从城市 j 到城市 i 的距离相同。

访问阵列:

```js

该数组是一个布尔数组,用于在 DFS 遍历期间跟踪访问的城市。visited

它可以防止在同一条路径上重访同一城市,以避免循环。

栈:

实现自定义堆栈(结构)来存储 DFS 期间正在探索的当前路径。Stack

它用于跟踪迄今为止访问的城市的顺序。

堆栈操作有助于 DFS 遍历。
最短路径阵列:

   ```js
该数组用于存储 DFS 遍历期间找到的当前最短路径。shortestPath

    每当发现较短的路径时,它都会更新。

常量和变量:

    常量表示最大城市数。MAX

    numCities表示图中的城市总数。

    shortestPathLength保存当前最短路径的长度。

DFS功能:

```js

深度优先搜索函数 () 是递归实现的。dfs

它探索所有可能的路径,在找到完整路径时更新最短路径。









3 代码结果分析
```js
程序正常运行并找到了正确的最短路径和路径长度。在这个例子中,最短路径是从城市1出发,依次经过城市2、城市4、城市3,最后回到城市1,路径长度为80。

这意味着,根据给定的图形和实现的算法,访问每个城市一次并返回起始城市的最有效路线是通过上述城市序列,并且该路径的总长度为 80 个单位。

4 算法优缺点

优势:

正确性:该算法保证找到最佳解决方案,因为它详尽地探索所有可能的路径,并在找到较短路径时更新最短路径。

    完整性:该算法是完整的,这意味着如果存在解决方案,它总能找到解决方案。它系统地探索了所有的可能性。

    单纯:该算法实现起来相对简单,易于理解和调试。

弊端:

指数时间复杂度:该算法的时间复杂度是阶乘的,即 O(n!),其中 n 是城市的数量。这使得它对许多城市来说效率非常低下。随着城市数量的增加,运行时间迅速增长。

    冗余计算:该算法探索了许多冗余路径,因为它没有采用任何修剪或记忆技术。这会导致大量重复计算,并使算法效率降低。

    不可扩展:由于其较高的时间复杂度,该算法对于具有大量城市的实际实例变得不切实际。它不适合解决例如数百或数千个城市的 TSP 实例。

    缺乏启发式方法:该算法不使用任何启发式方法来指导搜索或对解决方案进行有根据的猜测。因此,可能需要很长时间才能找到最佳解决方案。

6 附件之源代码

#include <iostream>

#include <climits>



const int MAX = 4;  // 假设有4个城市



// 邻接矩阵表示图

int graph[MAX][MAX] = {
   

    {
   0, 10, 15, 20},

    {
   10, 0, 35, 25},

    {
   15, 35, 0, 30},

    {
   20, 25, 30, 0}

};



// 城市数

int numCities = 4;



// 记录访问过的城市

bool visited[MAX];



// 当前最短路径长度

int shortestPathLength = INT_MAX;



// 当前最短路径

int shortestPath[MAX];



// 简单栈的实现

struct Stack {
   

    int arr[MAX];

    int top;



    Stack() {
   

        top = -1;

    }



    void push(int value) {
   

        arr[++top] = value;

    }



    int pop() {
   

        return arr[top--];

    }



    int peek() {
   

        return arr[top];

    }



    bool isEmpty() {
   

        return top == -1;

    }

};



// 深度优先搜索函数

void dfs(int currentCity, int pathLength, Stack& currentPath) {
   

    if (currentPath.top == numCities - 1) {
   

        // 如果已经访问了所有城市

        if (graph[currentPath.peek()][currentPath.arr[0]] != 0) {
   

            // 更新最短路径

            if (pathLength + graph[currentCity][currentPath.arr[0]] < shortestPathLength) {
   

                shortestPathLength = pathLength + graph[currentCity][currentPath.arr[0]];

                for (int i = 0; i < numCities; ++i) {
   

                    shortestPath[i] = currentPath.arr[i];

                }

            }

        }

        return;

    }



    for (int i = 0; i < numCities; ++i) {
   

        if (!visited[i] && graph[currentCity][i] != 0) {
   

            visited[i] = true;

            currentPath.push(i);

            dfs(i, pathLength + graph[currentCity][i], currentPath);

            visited[i] = false;

            currentPath.pop();

        }

    }

}



int main() {
   

    // 初始化访问数组和堆栈

    for (int i = 0; i < MAX; ++i) {
   

        visited[i] = false;

    }



    Stack currentPath;



    // 从第一个城市开始深度优先搜索

    visited[0] = true;

    currentPath.push(0);

    dfs(0, 0, currentPath);



    // 输出最短路径和长度

    std::cout << "最短路径为:";

    for (int i = 0; i < numCities; ++i) {
   

        std::cout << "城市" << shortestPath[i] + 1 << " ";

    }

    std::cout << "城市" << shortestPath[0] + 1 << "\n";

    std::cout << "最短路径长度为:" << shortestPathLength << "\n";



    return 0;

}
目录
相关文章
|
算法 测试技术 定位技术
数据结构与算法——DFS(深度优先搜索)
数据结构与算法——DFS(深度优先搜索)
|
算法 安全 网络安全
数据结构之网络攻击路径(深度优先搜索)
本文介绍了如何使用深度优先搜索(DFS)算法分析网络攻击路径。在网络安全领域,DFS用于检测网络中潜在的攻击路径,帮助安全人员及时发现并阻止威胁。文中详细描述了网络图的构建、节点间的连接关系以及DFS的实现过程。通过一个具体的例子,展示了如何检测从一个普通节点到关键节点的攻击路径,并讨论了DFS算法的优缺点。提供的C++代码实现了网络图的构建和攻击路径的检测功能。
353 24
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
437 0
|
算法
数据结构之路由表查找算法(深度优先搜索和宽度优先搜索)
在网络通信中,路由表用于指导数据包的传输路径。本文介绍了两种常用的路由表查找算法——深度优先算法(DFS)和宽度优先算法(BFS)。DFS使用栈实现,适合路径问题;BFS使用队列,保证找到最短路径。两者均能有效查找路由信息,但适用场景不同,需根据具体需求选择。文中还提供了这两种算法的核心代码及测试结果,验证了算法的有效性。
705 23
|
传感器 算法
数据结构之环境监测系统(深度优先搜索)
环境监测系统采用深度优先搜索(DFS)算法,实现实时监测和分析环境参数,如温度、湿度等。系统通过构建传感器网络图结构,利用DFS遍历网络,检测异常数据。当温度超过预设阈值时,系统将发出警告。此系统适用于工业生产、室内空调控制、农业温室管理等多种场景,提供高效的环境监测解决方案。
297 12
|
算法
数据结构之农业作物管理(深度优先搜索)
本文探讨了农业作物管理系统的背景、发展动因及其在现代农业中的重要性,特别是在应对气候变化、资源减少等挑战时的作用。文中介绍了作物关系建模与深度优先搜索(DFS)的应用,展示了如何通过邻接矩阵和DFS算法实现作物的智能管理和优化。通过具体的数据结构设计和核心代码实现,说明了DFS在农业作物管理中的应用效果及优缺点。
152 1
|
算法 Java
Java数据结构与算法:图算法之深度优先搜索(DFS)
Java数据结构与算法:图算法之深度优先搜索(DFS)
|
存储 C语言
数据结构学习记录——图的遍历(深度优先搜索、广度优先搜索、为什么需要两种遍历、图不连通怎么办)
数据结构学习记录——图的遍历(深度优先搜索、广度优先搜索、为什么需要两种遍历、图不连通怎么办)
758 0
|
算法 Python
Python 数据结构和算法:解释深度优先搜索(DFS)和广度优先搜索(BFS)。
Python 数据结构和算法:解释深度优先搜索(DFS)和广度优先搜索(BFS)。
644 0
408数据结构学习笔记——图的广度优先搜索、深度优先搜索
408数据结构学习笔记——图的广度优先搜索、深度优先搜索
460 1
408数据结构学习笔记——图的广度优先搜索、深度优先搜索

热门文章

最新文章