跳转至

简单线性链表

一个轻量级的整数线性链表实现,提供头插法建表、指定位置插入与删除、数组批量导入等功能。

原代码存在三处缺陷:listinsert 分配结点后未链入链表;listdelete 分配了无用结点造成内存泄漏,且被删元素无法回传;两函数的位置越界判断有误。以下给出修正后代码。

修正后完整代码

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

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

#define INTARRLEN(a) (sizeof(a)/sizeof(int))

typedef int elemtype;
typedef int status;

typedef struct lnode
{
    elemtype data;
    struct lnode * next;
} lnode, * linklist;

status listcreate(linklist &l, int n)
{
    l = (linklist)malloc(sizeof(lnode));
    l->next = NULL;
    for (int i = 0; i < n; i++)
    {
        linklist p = (linklist)malloc(sizeof(lnode));
        scanf("%d", &p->data);
        p->next = l->next;
        l->next = p;
    }
    return OK;
}

status listinsert(linklist &l, int i, elemtype e)
{
    linklist p = l;
    int j = 0;
    while (p && j < i - 1) { p = p->next; ++j; }
    if (!p || j > i - 1) return ERROR;                   // 修正:越界条件改为 j > i-1
    linklist s = (linklist)malloc(sizeof(lnode));
    s->data = e;
    s->next = p->next;
    p->next = s;                                         // 修正:将新结点链入链表
    return OK;
}

status listdelete(linklist &l, int i, elemtype &e)       // 修正:参数改为引用
{
    linklist p = l;
    int j = 0;
    while (p->next && j < i - 1) { p = p->next; ++j; }
    if (!(p->next) || j > i - 1) return ERROR;
    lnode * q = p->next;                                 // 修正:去掉无用 malloc
    p->next = q->next;
    e = q->data;
    free(q);
    return OK;
}

status printlist(linklist &l)
{
    lnode * templ = l;
    templ = templ->next;
    while (templ)
    {
        printf("%d ", templ->data);
        templ = templ->next;
    }
    printf("\n");                                        // 新增:输出换行
    return OK;                                           // 新增:补充返回值
}

status arraylist(linklist &l, elemtype arr[], int n)
{
    l = (linklist)malloc(sizeof(lnode));
    l->next = NULL;
    for (int i = 0; i < n; i++)
    {
        linklist p = (linklist)malloc(sizeof(lnode));
        p->data = arr[i];
        p->next = l->next;
        l->next = p;
    }
    return OK;
}

int main()
{
    linklist L;
    int a[] = {1, 2, 5, 6245, 232, 514, 124, 2, 22};
    arraylist(L, a, INTARRLEN(a));
    printlist(L);

    elemtype deleted;                                    // 新增:接收被删元素
    listdelete(L, 3, deleted);
    printf("删除第 3 个元素: %d\n", deleted);
    printlist(L);

    listinsert(L, 2, 999);
    printf("在第 2 位插入 999:\n");
    printlist(L);

    return 0;
}

listcreatearraylist 均使用头插法,每次新结点插在头结点之后,因此数组元素的存储顺序与输入顺序相反。listinsert 修正后将 s 正确链入;listdelete 改为引用传参并去除了多余的 malloc 调用。位置越界判断统一使用 j > i - 1 逻辑。