按升序插入C中的链表而不显示

时间:2017-09-29 15:36:48

标签: c list struct

我正在编写一个函数来插入C中的链表,基于以下结构:

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


/* self-referential structure */
struct Node {
    int item;
    int id;
    struct Node *next;
};

struct List {
    struct Node *head;
    struct Node *tail;
};


struct List SLL_new(){
    /* construct an empty list */
    struct List list;
    list.head = NULL;
    list.tail = NULL;
    return list;
}

int SSL_length(struct List *list) {
    /* return the number of items in the list */
    struct Node *p;

    int n = 0;
    for (p = list->head; p != NULL; p = p->next) {
        ++n;
    }
    return n;
}

int SLL_empty(struct List *list) {
    /* return true if the list contains no items */
    return list->head == NULL;
}

int SLL_pop(struct List *list) {
    /* remove and return the first item of the list */
    struct Node *node = list->head;
    int item = node->item;
    list->head = node->next;
    if (SLL_empty(list)) {
        list->tail = NULL;
    }
    free(node);
    return item;
}

void SLL_clear(struct List *list) {
    /* remove all the items from the list */
    while (!SLL_empty(list)) {
        SLL_pop(list);
    }
}

void SLL_push(struct List *list, int item) {
    /*  insert the item at the front of the list */
    struct Node *node = malloc(sizeof(struct Node));
    node->item = item;
    node->next = list->head;
    if (SLL_empty(list)) {
        list->tail = node;
    }
    list->head = node;
}

void SLL_append(struct List *list, int item) {
    /* append the item to the end of the list */
    if (SLL_empty(list)) {
        SLL_push(list, item);
    }
    else {
        struct Node *node = malloc(sizeof(struct Node));
        node->item = item;
        node->next = NULL;
        list->tail->next = node;
        list->tail = node;
    }
}

void SLL_insert(struct List *list, int id, int item) {
    /*append item according to node data */
    struct Node *node = malloc(sizeof(struct Node));
    node->id = id;
    node->item = item;
    if(list->head == NULL){
        list->head = node;
        list->tail = node;
    }
    else if(list->head->id >= node->id){
        node->next = list->head;
        list->head = node;
    }
    else{
        struct Node *temp;
        struct Node *prev;
        temp = list->head->next;
        prev = list->head;
        while(temp != NULL && temp->id <= id) {
            prev = temp;
            temp = temp->next;
        }
        node->next = temp;
        prev->next = node;
    }
}

int main(int argc, char **argv) {
    int i;
    printf("hello world");
    struct List list = SLL_new();
    for (i = 0; i < 5; ++i) {
        SLL_insert(&list, i, i);
    }

}

到目前为止,这是我的功能:

void SLL_insert(struct List *list, int id, int item) {
    /*append item according to node data */
    struct Node *node = malloc(sizeof(struct Node));
    node->id = id;
    node->item = item;
    if(list->head == NULL){
        list->head = node;
        list->tail = node;
    }
    else if(list->head->id >= node->id){
        node->next = list->head;
        list->head = node;
    }
    else{
        struct Node *temp;
        struct Node *prev;
        temp = list->head->next;
        prev = list->head;
        while(temp != NULL && temp->id <= id) {
            prev = temp;
            temp = temp->next;
        }
        node->next = temp;
        prev->next = node;
    }
}

然而,当我运行它时,只是尝试使用pastebin底部主要的循环插入它,我的cmd似乎只是在无限循环中运行。我的问题是为什么会这样,我似乎处理每一个案例,并且在我的while循环中有一个明确的停止值。我的后续问题,出于好奇心的杂项问题在理论上是如何在我不进行迭代的情况下插入链表而不跟踪前一个节点。

3 个答案:

答案 0 :(得分:4)

SLL_insert

中分配新节点后
struct Node *node = malloc(sizeof(struct Node));

您忘记将next指针初始化为NULL

如果在列表的末尾插入了元素,那么在SLL_Insert中你也不会更新tail指针。

答案 1 :(得分:1)

创建节点时,请将其设置为NULL

struct Node *node = malloc(sizeof(struct Node));
node->id = id;
node->item = item;
node->next = NULL;

通过这种方式,您可以确定tail的{​​{1}}是next,并且您不会得到未定义的行为。此外,值得考虑创建一个单独的函数,它将找到小于或等于输入的最后一个元素,如果没有找到则返回NULL。它将极大地简化您的生活,以使用这些辅助函数。

答案 2 :(得分:1)

我要重复其他问题的建议。

  1. 插入第一个项目时未能设置node->next=NULL
  2. 第一次插入后,您也无法更新list->tail
  3. 其他建议:

    考虑添加一个&#39;构造函数&#39;名为SSL_new_node()的Node的函数,它返回一个初始化的节点对象。它位于Object Orientation的山脚下,但是如果你有一个函数将节点初始化为一个有效状态,并且只使用它创建它们,那么你的代码将更可靠和可维护。

    添加一个名为SLL_destroy(struct List*list)的函数,该函数在结尾处释放列表以避免内存泄漏。

    在不跟踪上一个节点的情况下回答有关单链表的问题: 您可以有效地实现此模型,而无需在列表中使用tail。 你必须做的(并且已经完成的)是跟踪之前的那个人。因此,当您意识到您的循环刚刚超过插入点时,您可以选择上一个节点并挂钩插入。没有实际的方法可以避免这种情况。

    无论如何,您似乎并没有充分利用tail。事实上,您的函数append只是将项目放在列表的末尾。这似乎与SLL_insert不一致,因为它似乎试图按顺序维护列表。

    您可能应该决定您的列表是否已订购,以及是否确保所有功能都保持不变。 如果这样做,则允许所有函数假定列表是作为前置条件订购的,并且必须确保它作为后置条件保持订购。