一笔画路径生成(c/c++)

2023-10-07 17:50
文章标签 c++ 路径 生成 笔画

本文主要是介绍一笔画路径生成(c/c++),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一笔画 路径生成(c++)

练习图的遍历、回溯

新建一个OnePen类;
使用setNodeNum()方法设置节点数量;
使用setNodeJoin()设置节点连线;
执行drawLine()方法即可得出该图的一笔画路线;

  • main.cpp
#include <iostream>
#include "OnePen.h"void test01()
{OnePen op;op.setNodeNum(4);op.setNodeJoin(1, 2);op.setNodeJoin(1, 3);op.setNodeJoin(2, 3);op.setNodeJoin(2, 4);op.printTable();op.drawLine();
}void test02()
{OnePen op;op.setNodeNum(5);op.setNodeJoin(1, 4);op.setNodeJoin(1, 5);op.setNodeJoin(2, 4);op.setNodeJoin(2, 5);op.setNodeJoin(3, 4);op.setNodeJoin(3, 5);op.setNodeJoin(4, 5);op.printTable();op.drawLine();
}int main()
{test02();system("pause");return 0;
}
  • OnePen.h
#pragma once
#include <iostream>
#include <vector>class OnePen
{
private:struct node				// 节点{int data;			// 数据域bool flag;			// 标记(1已使用0未使用)node* next;			// 下一个};node* nodeArray;		// 节点数组int nodeNum;			// 节点数量std::vector<int> path;	// 路径bool checkAlone();bool sign(int p1, int p2, int flag);bool endCheck();int draw(int p);
public:OnePen();void setNodeNum(int num);void setNodeJoin(int begin, int end);void printTable();void drawLine();
};
  • OnePen.cpp
#include "OnePen.h"// 构造函数,初始化成员变量
OnePen::OnePen()
{this->nodeNum = 0;this->nodeArray = NULL;
}// 设置节点数量,并生成初始数组
void OnePen::setNodeNum(int num)
{if (num <= 1){std::cout << "节点数必须大于 1。" << std::endl;}else{this->nodeNum = num;this->nodeArray = new node[num];for (int i = 0; i < num; i++){this->nodeArray[i].data = i;this->nodeArray[i].flag = false;this->nodeArray[i].next = NULL;}}
}// 连接节点
void OnePen::setNodeJoin(int begin, int end)
{// 首尾不能相同if (begin == end){std::cout << "首尾节点不能相同,请重新确认!";std::cout <<"(Error: .setNodeJoin(" << begin << "," << end << ");)" << std::endl;return;}// 其中一节点不存在bool beginExist = false, endExist = false;for (int i = 0; i < this->nodeNum; i++){// 数据存储节点是从0开始,但是从用户角度节点是从1开始,所以需要-1if (this->nodeArray[i].data == begin - 1)beginExist = true;if (this->nodeArray[i].data == end - 1)endExist = true;}if (!beginExist || !endExist){std::cout << "节点不存在,请重新确认!";std::cout << "(Error: .setNodeJoin(" << begin << "," << end << ");)" << std::endl;return;}// 找到 begin 节点的最后一个邻接节点,然后插入新的邻接节点node* beginNode = &this->nodeArray[begin - 1];	// begin节点while (NULL != beginNode->next){if (beginNode->next->data == end - 1){// 已存在从 begin -> end 的路线break;}beginNode = beginNode->next;}if (beginNode->next == NULL){node* temp = new node;temp->data = end - 1;temp->flag = 0;temp->next = NULL;beginNode->next = temp;}// 找到 end 节点的最后一个邻接节点,然后插入新的邻接节点node* endNode = &this->nodeArray[end - 1];		// end节点while (NULL != endNode->next){if (endNode->next->data == begin - 1){// 已存在从 end -> begin 的路线break;}endNode = endNode->next;}if (endNode->next == NULL){node* temp = new node;temp->data = begin - 1;temp->flag = 0;temp->next = NULL;endNode->next = temp;}
}// 输出邻接表
void OnePen::printTable()
{std::cout << "当前邻接表为:" << std::endl;std::cout << "-----------------------------" << std::endl;for (int i = 0; i < this->nodeNum; i++){std::cout << this->nodeArray[i].data + 1 << " | ";node* temp = this->nodeArray[i].next;while (temp != NULL){std::cout << " ->" << temp->data + 1;temp = temp->next;}std::cout << std::endl;}std::cout << "-----------------------------\n" << std::endl;
}// 检查是否存在独立的点(即出度和入度皆为0)
bool OnePen::checkAlone()
{for (int i = 0; i < this->nodeNum; i++){if (this->nodeArray[i].next == NULL){return true;}}return false;
}// 设置标记(p1->p2 的 flag 设置为 flag)
bool OnePen::sign(int p1, int p2, int flag)
{node* it = this->nodeArray[p1].next;while (it != NULL){if (it->data == p2){it->flag = flag;return true;}it = it->next;}return false;
}// 最终检查(邻接表的全部flag都为1即返回true)
bool OnePen::endCheck()
{node* temp;for (int i = 0; i < this->nodeNum; i++){temp = this->nodeArray[i].next;while (NULL != temp){if (temp->flag == 0){return false;}temp = temp->next;}}return true;
}// 开始画线
void OnePen::drawLine()
{// 检查是否存在独立的点if (this->checkAlone()){std::cout << "- 单独的节点:\n\n>>> ";for (int i = 0; i < this->nodeNum; i++){if (this->nodeArray[i].next == NULL){std::cout << this->nodeArray[i].data << "\t";}}std::cout << "\n\n- 请将全部节点连接!\n" << std::endl;return;}// 统计有多少种方法int count = 1;// 从每个节点为初始节点依次走一次for (int i = 0; i < this->nodeNum; i++){// 将全部标签置0for (int j = 0; j < this->nodeNum; j++){node* t = this->nodeArray[j].next;while (t != NULL){t->flag = 0;t = t->next;}}// 将路径清空this->path.clear();// 开始画线draw(i),其中i为初始节点,返回结果为是否走得通if (this->draw(i)){std::cout << "-----------------------------" << std::endl;std::cout << ">>> 第 " << count << " 种解法:\n>>> ";count++;for (int i = 0; i < this->path.size(); i++){if (i == 0)std::cout << this->path[i];elsestd::cout << " ->" << this->path[i];}std::cout << "\n" << std::endl;}}
}// 以point节点为开始节点走下一步
int OnePen::draw(int point)
{// 当前节点添加到路径(由于存储和显示不同,所以+1)this->path.push_back(point + 1);// 完成(到该点已经全部路线都走完了就逐层返回1)if (this->endCheck()){return 1;}node* past = new node;					// 走过节点列表(已经走过并且走不通)node* last = past;						// 走过节点列表 的最后一个节点(方便添加新的节点)int peerNode = -1;						// 目标节点(将要走的节点,初始化为不可能的-1)node* it = this->nodeArray[point].next;	// 当前节点的第一个邻接点// 找到下一个要走的节点,并且标记while (it != NULL){if (it->flag == 0)			// 尚未走过的目标节点{peerNode = it->data;	// 记录目标节点it->flag = 1;			// 标记目标节点past->data = peerNode;	// 目标节点加入past列表past->next = NULL;break;}it = it->next;}// 此路不通(遍历完当前节点的所有邻接点都没找到flag=0的节点即无路可走了)if (it == NULL){return 0;}// 将目标节点到当前节点的线标记this->sign(peerNode, point, 1);// 开始递归,如果递归结果返回0(即此路不通)开始进入循环找新的目标节点while (!this->draw(peerNode)){// 进入循环证明当前past列表的最新元素走不通,移除this->path.pop_back();// 1. 将刚刚走过的标记取消(让其他节点可以走)this->sign(point, peerNode, 0);this->sign(peerNode, point, 0);// 2. 找到一个节点需要即不在past列表里,并且flag为0it = this->nodeArray[point].next;while (it != NULL){if (it->flag == 0){bool b = true; // 检查这个节点是否存在past列表(1这个节点能走,0这个节点不能走)// 遍历走过列表node* ps = past;while (ps != NULL){// 如果当前节点存在走过列表里面,这个节点不能走if (it->data == ps->data){b = false;break;}ps = ps->next;}// 找到目标节点if (b){peerNode = it->data;// 添加到走过列表node* past2 = new node;past2->data = peerNode;past2->next = NULL;last->next = past2;		// 添加到past列表的最后last = past2;			// last指向past列表的最后元素// 标记(当前节点到目标节点的路线已使用)this->sign(point, peerNode, 1);this->sign(peerNode, point, 1);// 退出循环break;}}it = it->next;}// 3. 遍历完邻接点也没找到可用的节点,没有可以走的路线了,此路不通if (it == NULL){return 0;}}
}
  • 测试(上面的main.cpp的test02函数)
    在这里插入图片描述

  • 执行结果
    在这里插入图片描述

这篇关于一笔画路径生成(c/c++)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/159426

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot路径映射配置的实现步骤

《SpringBoot路径映射配置的实现步骤》本文介绍了如何在SpringBoot项目中配置路径映射,使得除static目录外的资源可被访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一... 目录SpringBoot路径映射补:springboot 配置虚拟路径映射 @RequestMapp

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Python使用python-pptx自动化操作和生成PPT

《Python使用python-pptx自动化操作和生成PPT》这篇文章主要为大家详细介绍了如何使用python-pptx库实现PPT自动化,并提供实用的代码示例和应用场景,感兴趣的小伙伴可以跟随小编... 目录使用python-pptx操作PPT文档安装python-pptx基础概念创建新的PPT文档查看