堆实现中的奇异分段错​​误

时间:2013-08-25 21:07:11

标签: c++ segmentation-fault heap priority-queue

下面给出的是我用自己的堆实现编写的驱动程序。

#include<iostream>
#include"Heap.h"

int main(){
        Heap h(30);
        h.insert(1);
        h.insert(3);
        h.insert(5);
        h.insert(6);
        h.insert(5);
        h.insert(8);

        h.display();
        std::cout<<h.extractMin();    // Statement 1
        h.display();
        }

这给出了所需的结果:

========= Heap Contents =========
1   3   5   6   5   8   
1
========= Heap Contents =========
3   6   5   8   5

但是,如果我将statement 1更改为:

   std::cout<<"Min: "<<h.extractMin();

代码开始给出分段错误。同样,如果我将statement 1更改为

int z = h.extractMin();

代码仍然给出了分段错误。这诱惑我看看我在extractMin()做错了什么。以下是我对extractMin()的定义:

int Heap::extractMin()
{
    int min = this -> arr[0];
    this -> arr[0] = this -> arr[heapSize];

    heapSize -= 1;
    heapify(0);

    return min;
}

为了完整起见,下面是我对heapify()的定义:

void Heap::heapify(int index){
        if(index > this -> heapSize)
                return;

        int smallest = index;
        int l = leftChild(index);
        int r = rightChild(index);

        if(l <= heapSize && arr[l] < arr[index])
                smallest = l;
        if(r <= heapSize && arr[r] < smallest)
                smallest = r;

        if(smallest != index){
                arr[smallest] = arr[smallest] ^ arr[index];
                arr[index] = arr[smallest] ^ arr[index];
                arr[smallest] = arr[smallest] ^ arr[index];
                heapify(smallest);
                }
        }

知道发生了什么事吗?我无法理解分段错误背后的原因。我有什么明显的遗失吗?

谢谢!

增加1:

h.getHeapSize()h.getArrSize()也会发生这种情况,这让我觉得问题在于其他问题,而不在函数中。

增加2:

整个代码如下:

#include<iostream>
#include<cmath>

class Heap{
    private:
        int* arr;
        int size;
        int heapSize;
    public:
        Heap(int = 8); 
        Heap(int*, int size);
        int* initArr(int size);
        void setSize(int);
        int getSize();
        int getHeapSize();
        void setHeapSize(int);
        int leftChild(int);
        int rightChild(int);
        int parent(int);
        void heapify(int);
        void buildHeap();
        void insert(int);
        int extractMin();
        void display() const;
    };

Heap::Heap(int size){
    initArr(size);
    this -> size = size;
    this -> heapSize = -1;
    }

Heap::Heap(int* arr, int size){
    this -> arr = arr;
    this -> size = size;
    this -> heapSize = size - 1;
    buildHeap();
    }

int* Heap::initArr(int size){
    int* arr = new int[size];
    return arr;
    }

void Heap::setSize(int size){
    if(size > this -> heapSize)
        this -> size = size;
    }

int Heap::getSize(){
    return this -> size;
    }

void Heap::setHeapSize(int heapSize){
    this -> heapSize = heapSize;
    }

int Heap::getHeapSize(){
    return this -> heapSize;
    }

int Heap::leftChild(int index){
    return 2*index + 1;
    }

int Heap::rightChild(int index){
    return 2*index + 2;
    }

int Heap::parent(int index){
    return ceil(index >> 1) - 1;
    }

void Heap::heapify(int index){
    if(index > this -> heapSize)
        return;

    int smallest = index;
    int l = leftChild(index);
    int r = rightChild(index);

    if(l <= heapSize && arr[l] < arr[index])
        smallest = l;
    if(r <= heapSize && arr[r] < smallest)
        smallest = r;

    if(smallest != index){
        arr[smallest] = arr[smallest] ^ arr[index];
        arr[index] = arr[smallest] ^ arr[index];
        arr[smallest] = arr[smallest] ^ arr[index];
        heapify(smallest);
        }
    }

void Heap::buildHeap(){
    for(int i = heapSize/2 - 1; i >= 0; i-- )
        heapify(i);
    }

void Heap::insert(int val){
    heapSize += 1;
    int loc = heapSize;

    arr[heapSize] = val;
    int p;

    while((p = arr[parent(heapSize)]) > val){   
        arr[loc] = arr[p] ^ arr[loc];
        arr[p] = arr[p] ^ arr[loc];
        arr[loc] = arr[p] ^ arr[loc];
        }
    }

int Heap::extractMin(){
    //int temp = arr[0];
    //arr[0] = arr[heapSize];
    //arr[heapSize] = temp;

    int min = arr[0];
    arr[0] = arr[heapSize];

    heapSize -= 1;
    heapify(0);

    //return arr[heapSize + 1];
    return min;
    }

void Heap::display() const{
    std::cout<<"\n========= Heap Contents =========\n";
    for(int i = 0; i <= heapSize; i++)
        std::cout<<arr[i]<<'\t';
    std::cout<<'\n';
    }

2 个答案:

答案 0 :(得分:0)

从你在这里发布的内容来看,堆大小的不当处理是罪魁祸首。涉及heapSize的所有测试似乎都没有考虑到基于零的访问。你应该真的改变它,因为它会导致许多非逻辑后果:heapSize是否被初始化为-1

至于调试:

  • 悠闲地添加更多空值和边界检查(不仅是heapSize,还包括0)
  • 尝试减少测试集(它是否与一个项目崩溃?)并尝试手动或使用gdb跟踪控制流程

修改

该错误发生在parent()。尝试调试技巧。

答案 1 :(得分:0)

有很多问题。

首先,采用int参数的构造函数不会初始化arr成员,它会分配内存并将其分配给本地指针变量,它返回但只是忽略返回值。
你必须将它存储在成员变量中(将局部变量命名为与成员相同通常是一个非常糟糕的主意。)

修复后:在第一次插入期间,h.insert(1);parent(heapSize)为-1 由于您使用它在数组中进行索引,因此程序具有未定义的行为并且所有注意都已关闭;该程序不是一个有效的C ++程序。

也可能存在其他问题,但这些问题最为明显。