拆分链接列表

时间:2015-02-21 02:06:10

标签: c++ list hyperlink

我正在尝试将某个值的链接列表拆分为大于和小于其自己列表中的值。我的代码当前尝试ptr2-> data = original->数据时会出现错误;

这是我的代码:

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

struct node{
 int data;
 node * link;
};



void build_list(node* & head);  
void show_list(const node* head);
int size(const node* head);


 void remove_repeats(node*& head);
 void split_list(const node* original, node*& lesser, 
    node*& greater,int split_value);


int main(){
int start, stop;
int split;
node* head = NULL;
node *lesser;
node * greater;

start = time(NULL);
build_list(head);
stop = time(NULL);
cout<<"Time to build list = "<<stop - start <<"seconds.\n";
start = time(NULL);
show_list(head);
stop = time(NULL);
cout<<"Time to print list = "<<stop - start<<"seconds.\n";
cout<<"Size of the list = "<<size(head)<<endl;
cout<<"Removing repeats" << endl;
remove_repeats(head);
show_list(head);
cout<<"The size of the list is now " << size(head) << endl;
cout<<"Enter value to split list at" << endl;
cin >> split;
split_list(head, lesser, greater, split);
cout<<"The number less than split value" << endl;
show_list(lesser);
cout<<"The numbers greater than splt value" << endl;
show_list(greater);

return 0;
}

// builds a linked list of 2000 random integers, all in the 1 to 500 range
void build_list(node*& head){
 node* cursor;
 head = new node;
 head->data = rand()%500 + 1;
 cursor = head;
 for(int i = 0; i < 2000; ++i){
cursor->link = new node;
    cursor = cursor->link;
    cursor->data = rand()%500 + 1;
 }
 cursor->link = NULL;
}

// outputs the contents of a linked list to the screen
void show_list(const node* head){
  const node * cursor = head;
  while(cursor !=  NULL){
cout<<cursor->data<<"  ";
cursor = cursor->link;
  }
 cout<<endl;
}

// returns the number of nodes in a linked list
int size(const node* head){
const node* cursor = head;
int count = 0;
while(cursor != NULL){
    count++;
    cursor = cursor->link;
}
return count;
}

void remove_repeats(node*& head)
{
node *cur, *next, *prev;

cur = head;

while(cur != NULL){
       next = cur->link;
       prev = cur;
            while(next != NULL){
               if(next->data == cur->data){
                  prev->link = next->link;
                  delete next;
                  next = prev->link;
               }
               else{
                  prev = next;
                  next = next->link;
               }
            }
       cur = cur->link;
    }
}

void split_list(const node* original, node*& lesser, node*& greater, int split_value){

    node* ptr1;
    node* ptr2;
    ptr1 = lesser;
    ptr2 = greater;

        for(original; original != NULL; original = original->link){

                if(original->data < split_value){
           ptr1->data = original->data;
           ptr1->link = new node;
           ptr1 = ptr1->link;
                }
        else if(original->data > split_value){
               ptr2->data = original->data;
                   ptr2->link = new node;
                   ptr2 = ptr2->link;

                }
    }
}

1 个答案:

答案 0 :(得分:1)

您的函数出错是因为您取消引用NULL或不确定指针,并且很容易看到:

鉴于您已经通过两个指针引用了较低和较高的列表以最终填充,这个:

void split_list(const node* original, node*& lesser, node*& greater, int split_value){

    node* ptr1;
    node* ptr2;
    ptr1 = lesser;  // lesser is NULL or indeterminate, so is ptr1
    ptr2 = greater; // greater is NULL or indeterminate, so is ptr2

    for(original; original != NULL; original = original->link){

        if(original->data < split_value){
            ptr1->data = original->data; // ptr1 still bad. boom
            ptr1->link = new node;
            ptr1 = ptr1->link;
        }
        else if(original->data > split_value){
            ptr2->data = original->data; // ptr2 still bad, boom
            ptr2->link = new node;
            ptr2 = ptr2->link;
        }
    }
}

通过查看调用者来支持这个结论,其中传入的两个指针是:

node *lesser;
node * greater;

即。不定。并且在调用split函数之前从未改变过。

我认为你在这项任务中读得太多了。正如您所说,没有必要对原始列表进行复制。只需在引用中传递头指针,然后从该列表中拉出节点,分别填充下部和上部列表。下面的代码是这样做的一种方法,使用一种称为正向链接的技术,该技术利用指向指针的指针始终包含存储列表的下一个节点指针的地址:

void split_list(node *& head, node *& lhs, node *& rhs, int value)
{
    node **pplhs = &lhs;
    node **pprhs = &rhs;

    for (;head; head = head->link)
    {
        node **& pp = (head->data < value) ? pplhs : pprhs;
        *pp = head;
        pp = &(*pp)->link;
    }
    *pplhs = *pprhs = nullptr;
}

完成后,原始列表为空(head将为NULL),并且已根据拆分值测试设置了另外两个列表。没有创建新节点; 原始列表中取出节点,将其留空。

祝你好运