【问题标题】:How to return structure array in C++如何在 C++ 中返回结构数组
【发布时间】:2021-04-10 14:04:46
【问题描述】:

所以我一直在尝试实现 Kruskal 的算法,首先我想明确这个问题与算法的实现无关。我创建了一个graph.hpp 文件,一个kruskalsAlgo.hppmain.cpp 分别如下:

#pragma once

struct Edge
{
    int source;
    int destination;
    int weight;
};

struct Graph
{
    int V;
    int E;

    Edge* edge;
};

Graph* create_graph(int V, int E)
{
    Graph* graph = new Graph;
    graph -> V = V;
    graph -> E = E;

    graph -> edge = new Edge[E];

    return graph;
}
#include <stdlib.h>
#include <tuple>

#include "../Graph/Graph.hpp"

class Kruskals_Algo
{
    private:
        struct subset
        {
            int parent;
            int rank;
        };

        void make_set(subset*, int);
        int find_set(subset*, int);
        void _union(subset*, int, int);
    
    public:
        Edge* kruskal(Graph*);
        void print_kruskals_MST(Edge*, int);
};

void Kruskals_Algo::make_set(subset* subsets, int V)
{
    subsets[V].parent = V;
    subsets[V].rank = 0;
}

int Kruskals_Algo::find_set(subset* subsets, int V)
{
    if(subsets[V].parent != V)
        subsets[V].parent = find_set(subsets, subsets[V].parent);
    
    return subsets[V].parent;
}

void Kruskals_Algo::_union(subset* subsets, int x, int y)
{
    int xroot = find_set(subsets, x);
    int yroot = find_set(subsets, y);

    if(subsets[xroot].rank < subsets[yroot].rank)
        subsets[xroot].parent = yroot;
    
    else if(subsets[xroot].rank > subsets[yroot].rank)
        subsets[yroot].parent = xroot;

    else
    {
        subsets[yroot].parent = xroot;
        subsets[xroot].rank++;
    }
}

inline int myComp(const void* a, const void* b)
{
    Edge* a1 = (Edge*)a;
    Edge* b1 = (Edge*)b;
    return a1 -> weight > b1 -> weight;
}

Edge* Kruskals_Algo::kruskal(Graph* graph)
{
    int V = graph -> V;
    Edge result[V];
    Edge* result_ptr = result;
    int e = 0;
    int i = 0;

    qsort(graph -> edge, graph -> E, sizeof(graph -> edge[0]), myComp);

    subset* subsets = new subset[(V * sizeof(subset))];

    for (int v = 0; v < V; ++v)
        make_set(subsets, v);

    while(e < V - 1 && i < graph -> E)
    {
        Edge next_edge = graph -> edge[i++];

        int x = find_set(subsets, next_edge.source);
        int y = find_set(subsets, next_edge.destination);

        if (x != y)
        {
            result[e++] = next_edge;
            _union(subsets, x, y);
        }
    }
    //return std::make_tuple(res, e);
    return result_ptr;
}

void Kruskals_Algo::print_kruskals_MST(Edge* r, int e)
{
    int minimumCost = 0;
    for(int i=0; i<e; ++i)
    {
        std::cout << r[i].source << " -- "
                  << r[i].destination << " == "
                  << r[i].weight << std::endl;
        minimumCost = minimumCost + r[i].weight;
    }
    
    std::cout << "Minimum Cost Spanning Tree: " << minimumCost << std::endl;
}
#include <iostream>

#include "Graph/Graph.hpp"

#include "Kruskals_Algo/kruskalsAlgo.hpp"
//#include "Prims_Algo/primsAlgo.hpp"

using namespace std;

class GreedyAlgos
{        
    public:
        void kruskals_mst();
        //void prims_mst();
};

void GreedyAlgos::kruskals_mst()
{
    Kruskals_Algo kr;
    int V;
    int E;
    int source, destination, weight;
    
    cout << "\nEnter the number of vertices: ";
    cin >> V;
    cout << "\nEnter the number of edges: ";
    cin >> E;
    
    Edge* res;

    Graph* graph = create_graph(V, E);

    for(int i=0; i<E; i++)
    {
        cout << "\nEnter source, destinstion and weight: ";
        cin >> source >> destination >> weight;
        graph -> edge[i].source = source;
        graph -> edge[i].destination = destination;
        graph -> edge[i].weight = weight;
    }

    //std::tie(result, E) = kr.kruskal(graph);
    res = kr.kruskal(graph);
    kr.print_kruskals_MST(res, E);
}

int main()
{
    int choice;
    GreedyAlgos greedy;
    greedy.kruskals_mst();
    
    return 0;
}

所以我的问题是,当我调试程序时,Edge result[V] 中的值是一个结构数组,在位置[0] [1] [2] 处被正确计算,如下图所示:

但是当函数 print_kruskals_MST(res, E) 从 main 调用时,打印的值是不同的:

我做错了什么指针的事情吗? 提前致谢! 附言忽略cmets!

【问题讨论】:

  • 不要使用数组,使用std::vector
  • 边缘相关:new subset[(V * sizeof(subset))] 相当可疑。 sizeof 是干什么用的? new 不是 mallocnew subset[V] 已经为 V 类型为 subset 的条目分配了正确的数量。
  • 当您使用调试器运行程序时,一次一行地检查所有对象、变量和指针的值,您看到了什么?

标签: c++ pointers structure


【解决方案1】:

此答案可能无法直接回答您的问题,但它应该可以阐明问题。

首先,是的,你有很多指针问题......

其次,将new 运算符的任何使用与delete 运算符配对。就目前而言,你有一堆内存泄漏。

另外,为什么要create_graph?而是为Graph 创建一个构造函数(以及一个析构函数,因为该类有一个需要处理的Edge* edge)。

struct Graph
{
    int V;
    int E;

    Edge* edge;

    // constructor
    Graph(int V, int E)
    {
        this->V = V;
        this->E = E;
        this->edge = new Edge[E];
    }

    // destructor
    ~Graph()
    {
        // nullify the member variable before deleting its memory is just a safety measure pertaining to multithreading.
        Edge* _edge = this->edge;
        this->edge = nullptr;
        delete _edge;
    }
};

然后将Graph* graph = create_graph(V, E); 更改为Graph* graph = new Graph(V, E); 并在使用完毕后执行delete graph

确保删除所有内存泄漏,我们可以继续讨论引用正确的数据(例如,我更改了我的答案)。

【讨论】:

    猜你喜欢
    • 2020-03-23
    • 2014-06-02
    • 2022-10-20
    • 2020-05-31
    • 2023-03-09
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多