C++二进制最大堆读取访问冲突

C++ binary max heap Read Access Violation

本文关键字:读取 访问冲突 二进制 C++      更新时间:2023-10-16

所以我正在为我的 c++ 类创建一个二进制最大堆,并且不断遇到这个异常,说我在类方法中返回了一个 nullptr。我无法在我的代码中找到它可能在哪里,因此任何帮助将不胜感激。不断抛出的异常如下:

Unhandled exception thrown: read access violation.
**std::_String_alloc<std::_String_base_types<char,std::allocator<char> > ::_Get_data**(...) returned nullptr. occurred

这是我的树头文件: #ifndef HEAP_H #define HEAP_H

    #include <iostream>
    #include "THeapNode.h"
    class TreeHeap {
    private:
        THeapNode *root;  // the top node of the heap
        int next_loc;   // the next valid location to place a node
        void bubble_up(THeapNode *node);    //performs the bubble up operation on the given node
        void bubble_down(THeapNode *node);  //performs the bubble down operation on the given node
        void clear_heap(THeapNode *node); // removes all elements from the heap


    public:
        TreeHeap();    // the constructor
        ~TreeHeap();   // the destructor
        THeapNode* find_node(const int position);   // finds the node in the position given and returns a pointer to it
        void insert(const string &item);    // creates a node with the string given as the value and places it in the next location
        bool Delete();  // removes the root of the heap and returns false if the tree is empty
    };
    #endif

这是我的节点的 .h 文件:

    #ifndef NODE_H
    #define NODE_H
    #include<string>
    using std::string;
    struct THeapNode {
        string data;    // stores a data string
        THeapNode *parent;  // a pointer to the parent node
        THeapNode *rightChild;     // a pointer to the right child node
        THeapNode *leftChild;   // a pointer to the left child node
        THeapNode( const string &str );
    };
    #endif

这是我.cpp文件:

    #include "stdafx.h"
    #include <cmath>
    #include "TreeHeap.h"
    #include "THeapNode.h"

    TreeHeap::TreeHeap() {
        root = NULL;   
        next_loc = 1;
    };
    TreeHeap::~TreeHeap() {
        THeapNode *current = root;
        THeapNode *deleteNode = NULL;
        int d = floor(log2(next_loc - 1));
        int j = next_loc;
        for ( int i = 1; i <= j-1; i++ ) {
            while (1) {
                int d = floor(log2(next_loc - i));
                int power = std::pow(2, d - 1);
                if (next_loc == 1) {
                    deleteNode = current;
                    j -= 1;
                }
                else if (next_loc < (std::pow(2, d - 1) * 3)) {
                    current = current->leftChild;
                }
                else {
                    current = current->rightChild;
                }
                // Update location and depth to reflect traversal
                next_loc = std::pow(2, d - 1) + next_loc % power;
                d = d - 1;
            }
            clear_heap(deleteNode);
        }
    }
    void TreeHeap::clear_heap(THeapNode *node) {
        if (node == NULL) {
            return;
        }
        node->data = "";
        node->leftChild = NULL;
        node->rightChild = NULL;
        node->parent = NULL;
    }
    void TreeHeap::insert( const string &value ) {
        THeapNode newNode = THeapNode(value);
        int loc = next_loc;
        if (loc == 1) {
            *root = newNode;
        }
        THeapNode *current = root;
        while (1) {
            int d = floor(log2(loc));
            int power = std::pow(2, d - 1);
            if (loc < (power * 3)) {
                if (current->leftChild = nullptr) {
                    *current->leftChild = newNode;
                    newNode.parent = current;
                    next_loc += 1;
                    break;
                }
                else {
                    current = current->leftChild;
                }
            }
            else {
                if (current->rightChild = nullptr) {
                    *current->rightChild = newNode;
                    newNode.parent = current;
                    next_loc = +1;
                    break;
                }
                else {
                    current = current->rightChild;
                }
            }
            // Update location and depth to reflect traversal
            loc = std::pow(2, d - 1) + loc % power;
            d = d - 1;
        }
        std::cout << current->data << "n";
        system("PAUSE");
    }
    void TreeHeap::bubble_up( THeapNode *node ) {
        if (node == NULL) {
            return;
        }
        THeapNode *parent = node->parent;
        while ( parent->data < node->data ) {
            parent = node->parent;
            string temp = parent->data;
            parent->data = node->data;
            node->data = temp;
            }
    }
    void TreeHeap::bubble_down( THeapNode *node ) {
        if (node == NULL) {
            return;
        }
        while( node->data < node->rightChild->data || node->data < node->leftChild->data ){
            if (node->rightChild->data > node->leftChild->data) {
                THeapNode *right = node->rightChild;
                string temp = right->data;
                right->data = node->data;
                node->data = temp;
            }
            else if (node->rightChild->data < node->leftChild->data) {
                THeapNode *left = node->leftChild;
                string temp = left->data;
                left->data = node->data;
                node->data = temp;
            }
        }
    }
    THeapNode* TreeHeap::find_node( const int position ){
        int loc = position;
        int d = floor(log2(position));
        int power = std::pow(2, d - 1);
        THeapNode *returnValue = root;
        while (returnValue != NULL && 1 < position && position < (next_loc - 1)) {
            if (loc == 1) {
                return returnValue;
            }
            else if (loc < ( std::pow( 2, d-1 ) * 3)) {
                returnValue = returnValue->leftChild;
            }
            else {
                returnValue = returnValue->rightChild;
            }
            // Update location and depth to reflect traversal
            loc = std::pow(2, d - 1) + loc % power;
            d = d - 1;
        }
        std::cout << returnValue->data<<"n";
        return returnValue;
    }
    bool TreeHeap::Delete() {
        if (next_loc = 1) {
            return false;
        }
        int d = floor(log2(next_loc - 1));
        THeapNode *current = root;
        THeapNode *usedNode = NULL;
        int loc = next_loc - 1;
        while ( 1 ) {
            int d = floor(log2(loc));
            int power = std::pow(2, d - 1);
            if (loc == 1) {
                usedNode = current;
                break;
            }
            else if (loc < (std::pow(2, d - 1) * 3)) {
                current = current->leftChild;
            }
            else {
                current = current->rightChild;
            }
            // Update location and depth to reflect traversal
            loc = std::pow(2, d - 1) + loc % power;
            d = d - 1;
        }

        THeapNode *temp = root;
        clear_heap(root);
        root = usedNode;
        delete temp;
        bubble_down(root);
        return true;
    }

提前感谢您获得的任何帮助。

快速检查可发现bubble_upbubble_down功能中的错误。

bubble_up 中,您有以下内容:

    THeapNode *parent = node->parent;
    while ( parent->data < node->data ) {
        parent = node->parent;
        string temp = parent->data;
        parent->data = node->data;
        node->data = temp;
        }

当一个节点一直冒泡到顶部时,这将失败,因为它不会检查节点是否位于根目录。你需要写:

while (parent != NULL && parent->data < node->data)

bubble_down 中,您有以下代码:

    while( node->data < node->rightChild->data || node->data < node->leftChild->data ){
        if (node->rightChild->data > node->leftChild->data) {

您不检查rightChildleftChild是否为 NULL。

更重要的是,这对我来说看起来像一个无限循环,因为你永远不会改变node的值。

这些只是我在快速阅读您的代码时看到的错误。可能还有更多。