带链表的分段错误(c ++)

时间:2014-11-24 21:25:07

标签: c++

当以下程序运行时,我遇到分段错误。问题究竟在哪里?

标题文件:

#ifndef MAIN_SAVITCH_NODE1_H  
#define MAIN_SAVITCH_NODE1_H
#include <cstdlib> // Provides size_t and NULL

namespace main_savitch_5
{
    class node
    {
    public:
        // TYPEDEF
        typedef double value_type;

        // CONSTRUCTOR
        node(
            const value_type& init_data = value_type(),
            node* init_link = NULL
            )
        {
            data_field = init_data; link_field = init_link;
        }

        // Member functions to set the data and link fields:
        void set_data(const value_type& new_data) { data_field = new_data; }
        void set_link(node* new_link)             { link_field = new_link; }

        // Constant member function to retrieve the data:
        value_type data() const { return data_field; }

        // Constant member functions to retrieve the link:
        node* link() const          { return link_field; }

    private:
        value_type data_field;
        node* link_field;
    };

    // FUNCTIONS for the linked list toolkit
    std::size_t list_length(const node* head_ptr);
    void list_head_insert(node*& head_ptr, const node::value_type& entry);
    void list_insert(node* previous_ptr, const node::value_type& entry);
    node* list_search(node* head_ptr, const node::value_type& target);
    node* previous_to_min(node* marker_ptr);
    node* list_locate(node* head_ptr, std::size_t position);
    void list_head_remove(node*& head_ptr);
    void list_remove(node* previous_ptr);
    void list_clear(node*& head_ptr);
    void list_copy(const node* source_ptr, node*& head_ptr, node*& tail_ptr);
    void print_list(const node* head_ptr);

}

#endif

实施文件(这些都不是我的)

#include "node1.h"
#include <cassert>    // Provides assert
#include <iostream>  
#include <cstdlib>    // Provides NULL and size_t
using namespace std;

namespace main_savitch_5
{
    size_t list_length(const node* head_ptr)
        // Library facilities used: cstdlib
    {
        const node *cursor;
        size_t answer;

        answer = 0;
        for (cursor = head_ptr; cursor != NULL; cursor = cursor->link())
            ++answer;

        return answer;
    }

    void print_list(const node* head_ptr)
    {
        const node *cursor;
        cout << endl;
        for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) cout << cursor->data() << " ";
        cout << endl;
    }

    void list_head_insert(node*& head_ptr, const node::value_type& entry)
    {
        head_ptr = new node(entry, head_ptr);
    }

    void list_insert(node* previous_ptr, const node::value_type& entry)
    {
        node *insert_ptr;

        insert_ptr = new node(entry, previous_ptr->link());
        previous_ptr->set_link(insert_ptr);
    }

    node* list_search(node* head_ptr, const node::value_type& target)
        // Library facilities used: cstdlib
    {
        node *cursor;

        for (cursor = head_ptr; cursor != NULL; cursor = cursor->link())
            if (target == cursor->data())
                return cursor;
        return NULL;
    }

    node* previous_to_min(node* marker_ptr)
    {
        node * cursor;
        node * pre_cursor;
        node * current_min_prev_cursor;
        int current_min;

        pre_cursor = marker_ptr;
        cursor = marker_ptr->link();
        current_min = cursor->data();
        current_min_prev_cursor = pre_cursor;

        while (cursor != NULL)
        {
            if (cursor->data() < current_min)
            {
                current_min = cursor->data();
                current_min_prev_cursor = pre_cursor;
            }

            pre_cursor = cursor;
            cursor = cursor->link();
        }
        return current_min_prev_cursor;
    }










    node* list_locate(node* head_ptr, size_t position)
        // Library facilities used: cassert, cstdlib
    {
        node *cursor;
        size_t i;

        assert(0 < position);
        cursor = head_ptr;
        for (i = 1; (i < position) && (cursor != NULL); i++)
            cursor = cursor->link();
        return cursor;
    }


    void list_head_remove(node*& head_ptr)
    {
        node *remove_ptr;

        remove_ptr = head_ptr;
        head_ptr = head_ptr->link();
        delete remove_ptr;
    }

    void list_remove(node* previous_ptr)
    {
        node *remove_ptr;

        remove_ptr = previous_ptr->link();
        previous_ptr->set_link(remove_ptr->link());
        delete remove_ptr;
    }

    void list_clear(node*& head_ptr)
        // Library facilities used: cstdlib
    {
        while (head_ptr != NULL)
            list_head_remove(head_ptr);
    }

    void list_copy(const node* source_ptr, node*& head_ptr, node*& tail_ptr)
        // Library facilities used: cstdlib
    {
        head_ptr = NULL;
        tail_ptr = NULL;

        // Handle the case of the empty list.
        if (source_ptr == NULL)
            return;

        // Make the head node for the newly created list, and put data in it.
        list_head_insert(head_ptr, source_ptr->data());
        tail_ptr = head_ptr;

        // Copy the rest of the nodes one at a time, adding at the tail of new list.
        source_ptr = source_ptr->link();
        while (source_ptr != NULL)
        {
            list_insert(tail_ptr, source_ptr->data());
            tail_ptr = tail_ptr->link();
            source_ptr = source_ptr->link();
        }
    }

}

我的主文件

    #include <cstdlib>
#include <ctime>
#include <iostream>
#include <cassert>
#include "node1.h"

using namespace main_savitch_5;

void list_sort(node* &head_ptr);

int main()
{
    unsigned seed = time(0);
    size_t n;
    node *head;
    node *current;

    srand(seed);

    std::cout << "How many items would you like to sort?\n";
    std::cin >> n;
    assert(n > 0); // Ensure the list is not empty

    list_head_insert(head, 1 + rand() % 1000);
    current = head;

    for (size_t i = 1; i < n; i++)
    {
        list_insert(current, (1 + rand() % 1000));
        current = current->link();
    }

    std::cout << "Unsorted list:\n";
    print_list(head);

    list_sort(head);

    std::cout << "Sorted list:\n";
    print_list(head);

    list_clear(head);

    return 0;
}

    void list_sort(node* &head_ptr)
    {
        node* marker;
        node* min_node;
        node* temp;
        node* cursor;

        min_node = previous_to_min(head_ptr);
        // Set a pointer to the minimum data value in the list
        if (head_ptr->data() < min_node->data())
            marker = head_ptr;
        else
        {
            // If the head pointer does not hold the smallest value,
            // swap it with the node containing the min value
            temp = min_node->link();
            min_node->set_link(temp->link());
            temp->set_link(head_ptr);
            head_ptr = temp;
            marker = head_ptr;
        }

        while (marker->link()->link() != NULL)
        {
            cursor = previous_to_min(marker);
            // Find the smallest value of our new sublist

            if (cursor == marker)
                marker = marker->link();
            else
            {
                // Swap the head of the sublist with the new min value
                temp = cursor->link();
                cursor->set_link(temp->link());
                temp->set_link(marker->link());
                marker->set_link(temp);
                marker = marker->link();
            }
        }
    }

第一次调用print_list()后立即发生分段错误。

1 个答案:

答案 0 :(得分:0)

问题是您从列表中开始使用未设置为NULL的链接节点:

main函数中,您有:

node *head;
      //...
    list_head_insert(head, 1 + rand() % 1000);

但是,list_head_insert函数使用第一个参数的值来设置下一个链接。

void list_head_insert(node*& head_ptr, const node::value_type& entry)
{
    head_ptr = new node(entry, head_ptr);
}

由于指针未初始化,因此在创建新list_head_insert时,在head_ptr调用之前设置的任何垃圾都被用作node,如下所示:

node(const value_type& init_data = value_type(),
    node* init_link = NULL)
{
   data_field = init_data; 
   link_field = init_link;  // oh no.
}

发生的事情是,添加到链接列表的每个新节点都依赖于前一个节点的链接值。因此,当您构建链接列表时,这个错误的链接值将从节点传递到节点,并最终被用作列表的标记节点。

由于sentinel节点具有垃圾值,因此当节点为NULL时停止的循环都是错误的(因为没有NULL)。

所以解决方法是在head的开头将main节点设置为NULL:

node *head = NULL;

现在将链接设置为NULL,然后将该值用作sentinel节点。