zoukankan      html  css  js  c++  java
  • 在单链表按升序插入一个值

    算法要求:在单链表按升序插入一个值。成功插入返回1,已存在返回0,插入失败返回-1。
    结点结构:
    typedef struct Node
    {
    int value;
    struct Node* next;
    }Node;
    C语言新手写单链表的有序插入算法可能会写出下面的算法: int list_insert(Node *list, int value)
    {
    Node *p, *q, *new;
    p = list;
    // 查找正确插入位置
    while (p!=NULL && p->value < value) {
    q = p;
    p = p->next;
    }
    // 已存在,返回0
    if (p!=NULL && p->value==value)
    return 0;
    new = (Node*)malloc(sizeof(Node));
    if (!new)
    return -1; // 失败,返回-1
    new->value = value;
    new->next = p;
    q->next = new;
    return 1;
    }
    仔细看,这是一个有bug的代码。如果要插入的值比链表第一个结点的值小,那么应该插入在第一个结点之前。这样就应该修改头结点的指针。但是,这个代码却实现不了这样的功能。
    经过以下修改可以修正这个bug。
    int list_insert(Node **list, int value)
    {
    Node *p, *q, *new;
    p = *list;
    q = NULL;
    // 查找正确插入位置
    while (p!=NULL && p->value < value){
    q = p;
    p = p->next;
    }
    // 已存在,返回0
    if (p!=NULL && p->value==value)
    return 0;
    new = ( Node*)malloc(sizeof(Node));
    if (!new)
    return -1; // 失败,返回-1
    new->value = value;
    new->next = p;
    if (q == NULL) // 插入在第一个位置,改变头结点指针
    *list = new;
    else // 插入位置不是第一个位置
    q->next = new;
    return 1;
    }
    这个代码没有bug了。思路清晰。但是却有冗余。有最后要判断是不是应该插入到链表的第一个位置。如果忘了判断,还是会写出第一个代码那样的bug出来。下面有一个改进的代码。
    int list_insert(Node **pnext, int value)
    {
    Node *p, *new;
    // 查找正确插入位置
    while ((p=*pnext)!=NULL && p->value < value){
    pnext = &p->next;
    }
    // 已存在,返回0
    if (p!=NULL && p->value==value)
    reutrn 0;
    new = (Node*)malloc(sizeof(Node));
    if (!new)
    return -1; // 失败,返回-1
    new->value = value;
    new->next = current;
    *pnext->new;
    return 1;
    }
    这个算法不用考虑插入的是不是第一位置,因为它已经跟其他的操作一样的。如果插入的是在第一位置,那么*pnext已经修改了头结点的指针。如果不是第一个位置,也可以正确插入。

    说明下,这儿传入的参数是头节点的地址,而不是头节点,这点主要是针对当插入的数时最小的情况,当插入的值比已有链表中所有的值都小时,就得修改头节点,这时就只有传入指针的指针,也就是头结点的地址。

    另外一个就是这里面没移动一次节点,都取了当前节点地址来赋值给linkp,这也是针对头结点这个特殊节点来的,以为我们插入一个节点,就是要找到插入点的上一个节点的link,而这个link可能是普通节点的link,也有可能是头结点,

    linkp = &t->link;

    就是来抽象这两种不同的情况,把这情况的节点的属性都看成一种节点。

  • 相关阅读:
    java开学第一周测试自我感想
    暑假第八周进度报告
    暑假第七周进度报告
    暑假第六周进度报告
    暑假第五周进度报告
    暑假第四周进度报告
    暑假第三周进度报告
    暑假第二周进度报告
    《大道至简》读后感
    暑假第一周进度报告
  • 原文地址:https://www.cnblogs.com/phix/p/7701343.html
Copyright © 2011-2022 走看看