C ++指针返回意外值

时间:2019-03-19 19:35:40

标签: c++ pointers linked-list

我正在用C ++构建一个跳转列表的实现,该列表具有到周围节点的四重链接。

这是跳过列表节点类:

class SkipList_Node {
public:
    int key;
    string data;

//special values for infinity keys
int pos_infinity_key = 1000;
int neg_infinity_key = -1000;

//pointers to surrounding nodes
SkipList_Node *up;
SkipList_Node *down;
SkipList_Node *left;
SkipList_Node *right;

//Constructors
SkipList_Node() {};

SkipList_Node(int k, string d) {
    this->key = k;
    this->data = d;

    up =  NULL;
    down = NULL;
    left = NULL;
    right = NULL;

}
};

这是“跳过”列表类。

class Skip_List {
public:
    //first and last nodes in the list
    SkipList_Node first;
    SkipList_Node last;

//Number of rows in the list
int height;

//Constructor for an empty skiplist
Skip_List() {
    //initialize infinity keys
    SkipList_Node node1(SkipList_Node().neg_infinity_key, ""); 
    SkipList_Node node2(SkipList_Node().pos_infinity_key, "");

    //link new nodes
    node1.right = &node2;
    node2.left = &node1;
    //update first and last key values
    first = node1;
    last = node2;

    height = 0;
}

//Randomly determine the height of a node   
int getLevel() {
    //set the seed for random function
    srand(time(NULL));

    //Simulate coin flips and store heads into array
    //Max height is 4
    int flips[5];
    for (int i = 0; i < 5; i++) {
        flips[i] = 1 + rand() % 2;
    }

    //Determine height based on heads
    //As soon as tails is fliped stop counting height
    int height_counter = 0;
    for (int n = 0; n < 5; n++) {
        if (flips[n] == 2) {
            height_counter += 1;
        }
        else {
            break;
        }
    }

    return height_counter;

}

//return height of the skip list
int getHeight() {
    return height;
}

//find the largest key which is <= value of key passed
SkipList_Node searchSkipList(int k) {
    //pointer to the node
    SkipList_Node* ptr;
    //point to the first node of the list
    ptr = &first;
    //move right until a key <= value of key passed is found
    while (1) {
        while (ptr->right->key != SkipList_Node().neg_infinity_key &&
            ((ptr->right->key) - k) <= 0) {

            ptr = ptr->right;
        }

        //drop down level
        if (ptr->down != NULL) {
            ptr = ptr->down;
        }
        else {
            //Lowest level of skip list reached
            break;
        }
    }

    return *ptr;
}

//Return the value of a node given the key
string getValue(int k){
    SkipList_Node* ptr;
    //search for the node
    ptr = &searchSkipList(k);

    //If key is found return its value else return null
    if (k == (ptr->key)) {
        return ptr->data;
    }
    else {
        cout << "No Nodes found with that key value";
        return NULL;
    }
}

//Insert a new node into skip list
void insertIntoSkiplist(int k, string d) {
    SkipList_Node* p;
    int level;

    p = &searchSkipList(k);

    //if key already exists update the value
    if (k == (p->key)) {
        p->data = d;
        return;
    }

    // Create and insert a new node
    SkipList_Node* q = new SkipList_Node(k, d);
    q->left = p;
    q->right = p->right;
    p->right->left = q;
    p->right = q;

    //Calculate the level
    level = getLevel();

    //insert node in each level
    for (int i = 0; i <= level; i++) {
        //Create new empty row if level is hiegher than the current height of the list
        if (level >= height) {
            SkipList_Node* node1 = new SkipList_Node(SkipList_Node().neg_infinity_key, "");
            SkipList_Node* node2 = new SkipList_Node(SkipList_Node().pos_infinity_key, "");

            //link inifnity nodes
            node1->right = node2;
            node1->down = &first;
            node2->left = node1;
            node2->down = &last;
            first.up = node1;
            last.up = node2;
            first = *node1;
            last = *node2;
        }

        while (p->up == NULL) {
                p = p->left;
        }

        p = p->up;

        SkipList_Node* z = new SkipList_Node(k, NULL);

        z->left = p;
        z->right = p->right;
        z->down = q;

        p -> right -> left = z;
        p->right = z;
        q->up = z;

        q = z;

        level += 1;

    }
}
};

主要,我创建一个新的跳过列表对象。查看调试器,构造函数成功创建了node1和node2,并使用它们首先更新了节点,最后更新了节点。此时,节点first和last具有正确的链接值,First.right的键为1000,last.left的键为-1000。

然后我调用insertIntoSkipList()方法,该方法又调用searchSkipList()方法。在我将first的内存地址分配给指针ptr的那一点上看调试器,first.right的值现在为key = -858993和data =“错误读取字符串字符”。我不确定为什么first的内存地址将这些值保存为指向正确节点的指针。在这一点上,我希望first.right仍然保持key = 1000和data =“”的值,然后由ptr-> right指向。

我对C ++和指针没有太多经验。

1 个答案:

答案 0 :(得分:0)

您正在将左右指针分配给临时对象的地址。 SkipList构造函数运行后,它们就会超出范围,现在您有了悬空的指针。

如果需要永久引用,则需要分配内存。在cplusplus.com上查看指针和内存:

http://www.cplusplus.com/doc/tutorial/pointers/ http://www.cplusplus.com/doc/tutorial/dynamic/