简体   繁体   English

编写C程序创建链表的副本

[英]Write a C program to create a copy of a linked list

I want to write a copy_list function that creates a linked list(the function result) with new nodes that contain the same data as the linked list referenced by the single argument of copy_list.But my copy_list function doesn't work.It goes into infinite loop,While loop doesn't quit. I want to write a copy_list function that creates a linked list(the function result) with new nodes that contain the same data as the linked list referenced by the single argument of copy_list.But my copy_list function doesn't work.It goes into infinite循环,而循环不退出。 My structures我的结构

typedef struct name_node_s {
  char name[11];
  struct name_node_s *restp;
}name_node_t;
typedef struct {
  name_node_t *headp;
  int size;
}name_list_t;

My copy_list function:我的copy_list function:

name_node_t *copy_list(name_node_t *head){
    name_node_t *current = head;
    name_node_t *newList = NULL;
    name_node_t *tail = NULL;

    while (current != NULL){
        if (newList == NULL) {
            newList = malloc(sizeof(name_node_t));
            strcpy(newList->name, current->name);
            newList->restp = NULL;
            tail = newList;
        }
        else {
            tail->restp = malloc(sizeof(name_node_t));
            tail = tail->restp;
            strcpy(tail->name, current->name);
            tail->restp = NULL;
        }
        current = current->restp;
    }
    return(newList);
}

Rest of code: Rest 代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct name_node_s {
  char name[11];
  struct name_node_s *restp;
}name_node_t;
typedef struct {
  name_node_t *headp;
  int size;
}name_list_t;
name_node_t* presidents(void);
void insertAfter(name_node_t* mynode,name_node_t* newNode);
//void delete_last(name_node_t** headRef);
//void ListDelete(name_list_t* listP, char pname[]);
void lastDelete(name_list_t* listP);
void place_first(name_node_t **headRef, char pname[]);
name_node_t *copy_list(name_node_t *head);
int main(void)
{
  name_list_t list;
  name_list_t list_two;
  //name_node_t *np, *qp;
  list.headp = presidents();
  name_node_t *new_node;
  new_node = malloc(sizeof(name_node_t));
  strcpy(new_node->name, "Eisenhower");
  insertAfter(list.headp->restp, new_node);
  lastDelete(&list);
  place_first(&list.headp, "Mustafa");
  printf("%s %s %s %s", list.headp->name, list.headp->restp->name, list.headp->restp->restp->name, list.headp->restp->restp->restp->name);
  list_two.headp = copy_list(list.headp);
  printf("%s %s %s %s", list_two.headp->name, list.headp->restp->name, list.headp->restp->restp->name, list.headp->restp->restp->restp->name);

  return(0);
}
name_node_t* presidents(void)
{
  name_node_t* head = NULL;
  name_node_t* second = NULL;
  name_node_t* third = NULL;

  head = malloc(sizeof(name_node_t));
  second = malloc(sizeof(name_node_t));
  third = malloc (sizeof(name_node_t));

  strcpy(head->name, "Washington");
  head->restp = second;

  strcpy(second->name, "Roosevelt");
  second->restp = third;

  strcpy(third->name, "Kennedy");
  third->restp = NULL;

  return(head);
}
void insertAfter(name_node_t* mynode,name_node_t* newNode)
{
    newNode->restp = mynode->restp;
    mynode->restp = newNode;
}

void ListDelete(name_list_t* listP, char pname[]){
    name_node_t *to_freep, *cur_nodep;
    if(strcmp(listP->headp->name, pname)){
        to_freep = listP->headp;
        listP->headp = to_freep->restp;
        --(listP->size);
    }
    else {
        for (cur_nodep = listP->headp;
            cur_nodep->restp != NULL && !strcmp(cur_nodep->restp->name, pname);
            cur_nodep = cur_nodep->restp) {
                if( cur_nodep->restp != NULL && strcmp(cur_nodep->restp->name, pname)) {
                    to_freep = cur_nodep->restp;
                    cur_nodep->restp = to_freep->restp;
                    free(to_freep);
                    --(listP->size);
                }
            }
        }
    }
void lastDelete(name_list_t* listP){
    name_node_t *to_freep, *cur_nodep;
    for (cur_nodep = listP->headp;
            cur_nodep->restp != NULL;
            cur_nodep = cur_nodep->restp) {}
    to_freep = cur_nodep;
    cur_nodep->restp = to_freep->restp;
    free(to_freep);
    --(listP->size);
}
void place_first(name_node_t **headRef, char pname[]) {
    name_node_t *newNode = malloc(sizeof(name_node_t));
    strcpy(newNode->name, pname);
    newNode->restp = *headRef;
    *headRef = newNode;
}
/*name_node_t *copy_list(name_node_t *head) {
    name_node_t *current = head;
    name_node_t *newList = NULL;
    name_node_t **lastPtr;

    lastPtr = &newList;

    while (current != NULL) {
        printf("**");
        place_first(lastPtr, current->name);
        lastPtr = &((*lastPtr)->restp);
        current = current->restp;
    }
    return(newList);
}*/
/*name_node_t *copy_list(name_node_t *head) {
    if (head == NULL)
        return NULL;
    else {
        name_node_t *newList = malloc(sizeof(name_list_t));
        strcpy(newList->name, head->name);
        newList->restp = copy_list(head->restp);

        return(newList);
    }
}*/
/name_node_t *copy_list(name_node_t *head){
    name_node_t *current = head;
    name_node_t *newList = NULL;
    name_node_t *tail = NULL;

    while (current != NULL){
        if (newList == NULL) {
            newList = malloc(sizeof(name_node_t));
            strcpy(newList->name, current->name);
            newList->restp = NULL;
            tail = newList;
        }
        else {
            tail->restp = malloc(sizeof(name_node_t));
            tail = tail->restp;
            strcpy(tail->name, current->name);
            tail->restp = NULL;
        }
        current = current->restp;
    }
    return(newList);
}

This may be easier to do recursively, since singly-linked lists are recursive structures:这可能更容易递归执行,因为单链表是递归结构:

  • A copy of NULL is just NULL. NULL 的副本只是 NULL。
  • A copy of a name_node_t is a freshly malloc 'd name_node_t with the same name as the original and a copy of the original's restp as its restp . name_node_t的副本是新的malloc 'd name_node_t与原始name相同,原始的restp副本作为它的restp

In lastDelete() , this loop:lastDelete()中,这个循环:

for (cur_nodep = listP->headp;
            cur_nodep->restp != NULL;
            cur_nodep = cur_nodep->restp) {}

... stops at the last node in the list. ...停在列表中的最后一个节点。 Afterwards you never set restp to NULL in the second-to-last element.之后,您永远不会在倒数第二个元素restp设置为NULL You only work on the last one as to_freep and cur_nodep point to the same element.您只处理最后一个,因为to_freepcur_nodep指向同一个元素。

It's been a long time since I wrote C++.很久没有写C++了。 Still:仍然:

Doesn't look like there's anything in copy_list that should make it go into an infinite loop.看起来 copy_list 中没有任何内容应该使其 go 进入无限循环。

The logic has: while (current;=null) current = current->next;逻辑有: while (current;=null) current = current->next;

Perhaps copy_list is being passed in a bad list?也许 copy_list 被传递到一个错误的列表中? (ie A list where the last element does not have restp == null ). (即最后一个元素没有restp == null的列表)。

In main you are calling:主要是你打电话:
insertAfter(....);插入后(....);
lastDelete(....);最后删除(....);
... copy_list(....); ... 复制列表(....);

So the problem could be in insertAfter or lastDelete... or...所以问题可能出在 insertAfter 或 lastDelete... 或...

Check lastDelete:检查最后删除:

 name_node_t *to_freep, *cur_nodep;
 for (cur_nodep = listP->headp;
        cur_nodep->restp != NULL;
        cur_nodep = cur_nodep->restp) {}
 to_freep = cur_nodep;
 cur_nodep->restp = to_freep->restp;
 free(to_freep);   //what if listP->headp was null? i.e. list had size 0?
--(listP->size);

Plenty of issues很多问题

  1. What if you're passed a list with 0 elements?如果您传递了一个包含 0 个元素的列表怎么办?
  2. What if you're passed a list with 1 element?如果您传递了一个包含 1 个元素的列表怎么办?
  3. In any case after you free "to_freep", the node prior to "to_freep" does not have it's restp set to null.在你释放“to_freep”之后的任何情况下,“to_freep”之前的节点都没有将它的restp设置为null。 So the second last node, now points to a deleted node.所以倒数第二个节点,现在指向一个已删除的节点。 This means the list never terminates.这意味着列表永远不会终止。

A better lastDelete: (just an algo, can't remember the syntax anymore...)更好的lastDelete:(只是一个算法,不记得语法了......)

if (head == null) return; //do nothing
if (head->next == null) 
{
  listP->head = null;
  listP->size = 0;
  return;
}
node* prev = head;
head = head->next;
while (head->next != null)
{
   prev = head;
   head = head->next;
}
//now prev points to a 2nd last node
//head points to last node
free(head);
prev->restp = null;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM