链式前向星(非递归深度优先遍历算法等)

目录

链式前向星类(包括非递归深度优先遍历、非递归广度优先遍历、求一条包含所有结点的道路、是否有环、两点之间基本路径):

测试程序:


链式前向星类(包括非递归深度优先遍历、非递归广度优先遍历、求一条包含所有结点的道路、是否有环、两点之间基本路径):

(PS:有向图和无向图的区分靠main程序中用户输入来解决,如果是有向图输入中只有边1 4,如果是无向图输入边1 4以及边4 1)

#pragma once

#include <iostream>
#include <queue>
#include <vector>
#include <string>

using namespace std;

//链式前向星
class chain_forward_star
{
private:
    //结点数、边数、边序号(从1开始)
    int _node_number, _edge_number, _sequence_number;  
    //前结点最后出现的边序号
    int *_end_edge = new int[_node_number+1] ;         
    //边类
    struct Edge
    {
        //后结点、前结点上一次出现的边序号
        int _end_node, _last_edge;                      
    };
    //边数组
    Edge* _edge = new Edge[_node_number+1];            
public:
    //构造函数
    chain_forward_star(int node_number, int edge_number):
        _node_number(node_number),_edge_number(edge_number)
    {
        for (int x = 0; x < _node_number + 1; x++)
        {
            _end_edge[x] = -1;
        }
        _sequence_number = 1;
    }
    //默认析构函数
    ~chain_forward_star()
    {
        delete[] _end_edge;
        delete[] _edge;
    }

    //加边函数(起点,终点)
    void add_edge(int start_node, int end_node)                     
    {
        _edge[_sequence_number]._end_node = end_node;               
        _edge[_sequence_number]._last_edge = _end_edge[start_node];    
        _end_edge[start_node] = _sequence_number;                    
        _sequence_number++;                                         
    }

    //非递归深度优先遍历(遍历起点)
    void non_recursive_depth_first_traversal(int start_node) const
    {
        //初始化
        //建一个end_edge的副本进行使用
        int* temp_end_edge = new int[_node_number + 1];  
        //flag用于避免回路
        bool* flag = new bool[_node_number + 1];
        for (int x = 0; x < _node_number + 1; x++)
        {
            flag[x] = false;
            temp_end_edge[x] = _end_edge[x];
        }
        //vector用于回访前面的结点
        vector<int> node_vector;
        //算法
        flag[start_node] = true;
        node_vector.push_back(start_node);
        cout << start_node << " ";
        for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
        {
            if (temp_edge == -1)
            {
                node_vector.pop_back();
                if (node_vector.empty())
                {
                    break;
                }
                temp_node = node_vector.back();
                temp_edge = temp_end_edge[temp_node];
                continue;
            }
            temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
            temp_node = _edge[temp_edge]._end_node;
            if (flag[temp_node] == true)
            {
                temp_node = node_vector.back();
                temp_edge = temp_end_edge[temp_node];
                continue;
            }
            flag[temp_node] = true;
            node_vector.push_back(temp_node);
            cout << temp_node << " ";
            temp_edge = temp_end_edge[temp_node];
        }
        //回收内存
        delete [] temp_end_edge;
        delete [] flag;
    }

    //非递归广度优先遍历
    void non_recursive_breadth_first_traversal(int start_node) const
    {
        //初始化
        queue<int> node_queue;
        bool* flag = new bool[_node_number + 1];
        for (int x = 0; x < _node_number + 1; x++)
        {
            flag[x] = false;
        }
        //算法 
        flag[start_node] = true;
        node_queue.push(start_node);
        while (!node_queue.empty()) 
        {
            int temp_node = node_queue.front();
            node_queue.pop();
            cout << temp_node << " ";

            for (int temp_edge = _end_edge[temp_node]; temp_edge!=-1; 
                temp_edge = _edge[temp_edge]._last_edge) 
            {
                int temp_end_node = _edge[temp_edge]._end_node;
                if (flag[temp_end_node] == false)
                {
                    node_queue.push(temp_end_node);
                    flag[temp_end_node] = true;
                }
            }
        }
        //回收
        delete [] flag;
    }

    //求一条包含所有结点的回路
    //采用类似之前的深度优先遍历算法,每个结点作为开始结点,一直走,找到所求即退出
    void all_node_road_search(void)
    {
        //初始化
        int* temp_end_edge = new int[_node_number + 1];
        bool* flag = new bool[_node_number + 1];
        //算法
        for (int start_node = 1; start_node <= _node_number; start_node++)
        {
            for (int x = 0; x < _node_number + 1; x++)
            {
                flag[x] = false;
                temp_end_edge[x] = _end_edge[x];
            }
            vector<int> node_vector;
            flag[start_node] = true;
            node_vector.push_back(start_node);
            for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
            {
                if (temp_edge == -1)
                {
                    node_vector.pop_back();
                    if (node_vector.empty())
                    {
                        break;
                    }
                    temp_node = node_vector.back();
                    temp_edge = temp_end_edge[temp_node];
                    continue;
                }
                temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
                temp_node = _edge[temp_edge]._end_node;
                if (flag[temp_node] == true)
                {
                    break;
                }
                flag[temp_node] = true;
                node_vector.push_back(temp_node);
                temp_edge = temp_end_edge[temp_node];
            }
            //这里不一样
            if (node_vector.size() == _node_number)
            {
                cout << "一条包含所有结点的回路如下:";
                for (int x = 0; x < _node_number; x++)
                {
                    cout << node_vector[x] << " ";
                }
                //回收
                delete [] temp_end_edge;
                delete [] flag;
                return;
            }
        }
        cout << "没有找到一条包含所有结点的回路!";
        //回收
        delete [] temp_end_edge;
        delete [] flag;
        return;
    }

    //是否有环
    //采用类似之前的深度优先遍历算法,每个结点作为开始结点,遇到重复的即有环,退出函数
    void is_ring(void) const
    {
        //初始化
        int* temp_end_edge = new int[_node_number + 1];
        bool* flag = new bool[_node_number + 1];
        //算法
        for (int start_node = 1; start_node <= _node_number; start_node++)
        {
            for (int x = 0; x < _node_number + 1; x++)
            {
                flag[x] = false;
                temp_end_edge[x] = _end_edge[x];
            }
            vector<int> node_vector;
            flag[start_node] = true;
            node_vector.push_back(start_node);
            for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
            {
                if (temp_edge == -1)
                {
                    node_vector.pop_back();
                    if (node_vector.empty())
                    {
                        break;
                    }
                    temp_node = node_vector.back();
                    temp_edge = temp_end_edge[temp_node];
                    continue;
                }
                temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
                temp_node = _edge[temp_edge]._end_node;
                if (flag[temp_node] == true)
                {
                    cout<< "有环!" ;
                    //回收
                    delete [] temp_end_edge;
                    delete [] flag;
                    return;
                }
                flag[temp_node] = true;
                node_vector.push_back(temp_node);
                temp_edge = temp_end_edge[temp_node];
            }
        }
        cout << "无环!";
        //回收
        delete [] temp_end_edge;
        delete [] flag;
        return;
    }

    //找两个点之间的基本路径(点不重复的路径,同时边一定也不重复)
    void basic_path_between_two_points(int start_node, int end_node)
    {
        //初始化
        int* temp_end_edge = new int[_node_number + 1];
        bool* flag = new bool[_node_number + 1];
        for (int x = 0; x < _node_number + 1; x++)
        {
            flag[x] = false;
            temp_end_edge[x] = _end_edge[x];
        }
        vector<int> node_vector;
        //算法
        flag[start_node] = true;
        node_vector.push_back(start_node);
        for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
        {
            if (temp_node == end_node)
            {
                cout << start_node << "、" << end_node <<"两点间基本路径如下:";
                for (auto x : node_vector)
                {
                    cout << x << " ";
                }
                //回收
                delete [] temp_end_edge;
                delete [] flag;
                return;
            }
            if (temp_edge == -1)
            {
                node_vector.pop_back();
                if (node_vector.empty())
                {
                    break;
                }
                temp_node = node_vector.back();
                temp_edge = temp_end_edge[temp_node];
                continue;
            }
            temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
            temp_node = _edge[temp_edge]._end_node;
            if (flag[temp_node] == true)
            {
                temp_node = node_vector.back();
                temp_edge = temp_end_edge[temp_node];
                continue;
            }
            flag[temp_node] = true;
            node_vector.push_back(temp_node);
            temp_edge = temp_end_edge[temp_node];
        }
        cout << start_node << "、" << end_node << "两点间没有基本路径!";
        //回收
        delete [] temp_end_edge;
        delete [] flag;
        return;
    }
};

测试程序:

#include <iostream>

#include "chain_forward_star.h"
using namespace std;

//判断边处理函数
bool process_repeat_edge(int* temp_node_list_1, int* temp_node_list_2, 
                    int start_node, int end_node, int length)
{
    for (int x = 1; x <= length; x++)
    {
        if (temp_node_list_1[x] == start_node && temp_node_list_2[x] == end_node)
        {
            return false;
        }
    }
    return true;
}

int main()
{
    cout << "请输入结点数和边数:";
    int node_number = 0 , edge_number = 0;
    cin >> node_number >> edge_number;
    //输入结点数为0时退出
    if(node_number == 0)
    {
        cout << "错误,结点数为0!" << endl;
        return 0;
    }
    if(edge_number == 0)
    {
        cout << "错误,边数为0!" << endl;
        return 0;
    }
    if(edge_number > node_number * (node_number - 1))
    {
        cout << "错误,边数大于通过结点推断数目!" << endl;
        return 0;
    }
    //类实例化
    chain_forward_star star(node_number, edge_number);
    cout << "每排输入一条边的前结点和后结点,结点只能输入数字,从1到结点数:" << endl;
    int start_node = -1;
    int end_node = -1;
    //用于处理重复边
    int* temp_node_list_1 = new int[edge_number+1];
    int* temp_node_list_2 = new int[edge_number+1];
    //加边
    for (int x = 1; x <= edge_number; x++)
    {
        cin >> start_node >> end_node;
        //处理输入不正确的边
        if(start_node == -1 || end_node == -1 || start_node > node_number || end_node > node_number)
        {
            cout << "请输入正确格式的边!" << endl;
            return 0;
        }
        //处理重复边
        temp_node_list_1[x] = start_node;
        temp_node_list_2[x] = end_node;
        if(!process_repeat_edge(temp_node_list_1, temp_node_list_2, start_node, end_node, x-1))
        {
            cout << "错误,出现重复边!" << endl;
            return 0;
        }
        star.add_edge(start_node, end_node);
    }
    //回收
    delete [] temp_node_list_1;
    delete [] temp_node_list_2;
    cout << endl;

    cout << "非递归深度优先遍历:";
    star.non_recursive_depth_first_traversal(1);
    cout << endl;

    cout << "非递归广度优先遍历:";
    star.non_recursive_breadth_first_traversal(1);
    cout << endl;

    star.all_node_road_search();
    cout << endl;

    star.is_ring();
    cout << endl;
   
    cout<<"请输入想要查找基本路径两个结点:";
    int node_1 = -1, node_2 = -1;
    cin >> node_1 >> node_2;
    if(node_1 == -1 || node_2 == -1 || node_1 > node_number || node_2 > node_number)
    {
        cout << "请输入正确格式的边!" << endl;
        return 0;
    }
    star.basic_path_between_two_points(node_1, node_2);
    cout << endl;

    return 0;
}

/*
输入示例,第一排是7个点 8条边
7 8 
1 2
1 3
1 4
3 7
4 5
4 6
5 6
2 7
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值