简体   繁体   English

将值按升序插入排序的链表中

[英]Insert value into sorted linked list in ascending order

This function will asks the user to input an integer, then inserts it to the linked list in ascending order. 此函数将要求用户输入一个整数,然后将其按升序插入到链表中。 Will not insert if current value already existed. 如果当前值已存在,将不会插入。

typedef struct _listnode{
    int item;
    struct _listnode *next;
} ListNode;         

typedef struct _linkedlist{
    int size;
    ListNode *head;
} LinkedList;           

void insertSortedLinkedList(LinkedList *l)
{
    ListNode *cur = l->head;
    ListNode* newNode = malloc(sizeof(ListNode)); // create the node to be inserted
    int x;
    printf("please input an integer you want to add to the linked list:");
    scanf("%d", &x);
    newNode->item = x;
    newNode->next = NULL;

    if (l->head == NULL) // linkedlist is empty, inserting as first element
    {
        l->head = malloc(sizeof(ListNode));
        l->head->item = x;
        l->head->next = NULL;
        l->size++;
    }
    else
    {

        if (x < l->head->item) // data is smaller than first element, we will insert at first element and update head.
        {
            newNode->next = l->head;
            l->head = newNode;
            l->size++;
            return;
        }
        while (cur->next != NULL) // loop through the linkedlist
        {
            if (cur->next->item > x) // next element is bigger than data, we will insert it now.
            {
                if (cur->item != x) // if current element is not same as data, it must not have already existed.
                {
                    newNode->next = cur->next;
                    cur->next = newNode;
                    l->size++;
                    return;
                }
            }
            if (cur->next == NULL) // we have reached the last element and data is even greater than that. we will then insert it as last element.
            {
                cur->next = newNode;
                l->size++;
                return;
            }
            cur = cur->next;
        }
    }
}

Somehow, there's a bug in it. 不知何故,其中有一个错误。 When I try to insert the following, I get these result. 当我尝试插入以下内容时,我得到了这些结果。 It also doesn't insert if the data is bigger than those existed. 如果数据大于现有数据,则也不会插入。

Insert : 10
Result : 10
Insert : 5
Result : 5 10
Insert : 8
Result : 5 8 10
Insert : 10
Result : 5 8 10
Insert : 7
Result : 5 7 8 10
Insert : 9
Result : 5 7 8 9 10
Insert : 6 
Result : 5 6 7 8 9 10
Insert : 5
Result : 5 6 5 7 8 9 10 << why?

You test for equality in the wrong place: you always skip the first node. 您在错误的位置测试是否相等:始终跳过第一个节点。 You also need to improve the allocation scheme: you allocate memory twice for the head node and forget to free memory if the integer is already in the list. 您还需要改进分配方案:您为头节点分配了两次内存,如果整数已经在列表中,则忘记释放内存。

Here is an improved version: 这是一个改进的版本:

void insertSortedLinkedList(LinkedList *l)
{
    ListNode *cur, *newNode;
    int x;

    printf("please input an integer you want to add to the linked list:");
    if (scanf("%d", &x) != 1)
        return;

    newNode = malloc(sizeof(ListNode)); // create the node to be inserted
    newNode->item = x;
    newNode->next = NULL;

    if (l->head == NULL)
    {
        // linkedlist is empty, inserting as first element
        l->head = newNode;
        l->size++;
        return;
    }
    if (x < l->head->item)
    {
        // data is smaller than first element, we will insert at first element and update head.
        newNode->next = l->head;
        l->head = newNode;
        l->size++;
        return;
    }
    for (cur = l->head;; cur = cur->next) // loop through the linkedlist
    {
        if (cur->item == x)
        {
            // element already in the list
            free(newNode);
            return;
        }
        if (!cur->next || cur->next->item > x)
        {
            // next element is bigger than data or end of list, we will insert it now.
            newNode->next = cur->next;
            cur->next = newNode;
            l->size++;
            return;
        }
    }
}

This code can be made shorter using a pointer to the link: 可以使用指向链接的指针来简化此代码:

void insertSortedLinkedList(LinkedList *l)
{
    ListNode **curp, *cur, *newNode;
    int x;

    printf("please input an integer you want to add to the linked list:");
    if (scanf("%d", &x) != 1)
        return;

    for (curp = &l->head; (cur = *curp) != NULL; curp = &cur->next) {
        if (cur->item == x)
            return;
        if (cur->item > x)
            break;
    }
    // cur element is bigger than data or end of list, we will insert it now.
    newNode = malloc(sizeof(ListNode)); // create the node to be inserted
    newNode->item = x;
    newNode->next = cur;
    *curp = newNode;
    l->size++;
}

Problem is that you never reach your if-condition because when cur->next == NULL your loop breaks: 问题是您永远不会达到if条件,因为当cur->next == NULL您的循环会中断:

while (cur->next != NULL) // loop through the linkedlist
    ....
        if (cur->next == NULL) // we have reached the last element and data is even greater than that. we will then insert it as last element.
        {
           ...
        }
    ...
    }

Instead, you should have used while(cur != NULL) as loop, and set cur->next == NULL as first if-condition, so that (cur->next->item doesn't crash your program when cur == NULL . 相反,您应该使用while(cur != NULL)作为循环,并将cur->next == NULL为第一个if条件,以便在cur == NULL时, (cur->next->item不会使程序崩溃。 cur == NULL

NOTE: in this case, your loop condition won't be important because return in if (cur->next == NULL) will be breaking the loop. 注意:在这种情况下,您的循环条件将不重要,因为if (cur->next == NULL)将破坏循环, if (cur->next == NULL) return in。 It's only important not to quit loop before you get to execute that if -condition. 它不退出环只有重要的是你得到执行之前if -condition。

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

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