C语言实现单链表

链表和我们之前实现过的顺序表一样,都是简单的数据结构,链表分为单向链表、双向链表、循环链表。而单向链表又分为两种实现方法,一种为带头节点的单链表,一种为不带头节点的单链表。我们来具体看看不带头节点的单链表的实现
单链表:它是一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个节点。

这里写图片描述
今天我们来实现一些单链表的简单接口

先看看单链表的结构:
(为了通用性,我们将类型重命名为DataType)

typedef int DataType;

//链表
typedef struct Node
{
    DataType *data;
    struct Node *next;
}Node, *pNode, *pList;

接下来看看我们要实现的接口:

void InitLinkList(pList *pplist);//初始化链表
pNode BuyNode(DataType d);//创建链表节点
void PushBack(pList *pplist, DataType d);//尾插
void PopBack(pList *pplist);//尾删
void PushFront(pList *pplist, DataType d);//头插
void PopFront(pList *pplist);//头删
void PrintList(pList plist);//打印链表
pNode Find(pList plist, DataType d);//查找指定元素
void Remove(pList *pplist, DataType d);//删除指定的一个元素
void RemoveAll(pList *pplist, DataType d);//删除指定的所有元素
void Insert(pList *pplist, pNode pos, DataType d);//指定位置的后面插入
void Erase(pList *pplist, pNode pos);//指定位置删除
void DestroyList(pList *pplist);//销毁链表

来看看每个接口的具体实现:

pNode BuyNode(DataType d)
{
    pNode newNode = (pNode)malloc(sizeof(Node));
    if (newNode == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    newNode->data = d;
    newNode->next = NULL;
    return newNode;
}
void InitLinkList(pList *pplist)
{
    assert(pplist);
    *pplist = NULL;
}
void PushBack(pList *pplist, DataType d)
{
    assert(pplist);
    pNode newNode = BuyNode(d);
    pNode cur = *pplist;
    //链表没有节点
    if (*pplist == NULL)
    {
        *pplist = newNode;
        return;
    }
    //链表有节点
    while (cur->next != NULL)
    {
        cur = cur->next;
    }
    cur->next = newNode;
}
void PopBack(pList *pplist)
{
    pNode cur = *pplist;
    pNode prev = NULL;
    assert(pplist);
    //链表没有节点
    if (*pplist == NULL)
    {
        return;
    }
    //链表有一个节点
    if (cur->next == NULL)
    {
        free(*pplist);
        *pplist = NULL;
        return;
    }
    //链表有两个及两个以上节点
    while (cur->next != NULL)
    {
        prev = cur;//prev中保存的是cur之前的那个节点
        cur = cur->next;
    }
    prev->next = NULL;
    free(cur);
}
void PushFront(pList *pplist, DataType d)
{
    pNode newNode = BuyNode(d);
    //pNode cur = *pplist;
    assert(pplist);
    链表没有节点
    //if (*pplist == NULL)
    //{
    //  *pplist = newNode;
    //}
    链表有节点
    newNode->next = *pplist;
    *pplist = newNode;

}
void PopFront(pList *pplist)
{
    pNode cur = *pplist;
    assert(pplist);
    //链表为空
    if (*pplist == NULL)
    {
        return;
    }
    *pplist = cur->next;
    free(cur);
    cur = NULL;
}
void PrintList(pList plist)
{
    pNode cur = plist;
    while (cur)
    {
        printf("%d-->", cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
}
pNode Find(pList plist, DataType d)
{
    pNode cur = plist;
    while (cur)
    {
        if (cur->data == d)
        {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}
void Remove(pList *pplist, DataType d)
{
    pNode cur = *pplist;
    pNode prev = NULL;
    assert(pplist);
    if (cur == NULL)
    {
        return;
    }
    while (cur)
    {
        if (cur->data == d)
        {
            pNode del = cur;
            if (cur == *pplist)
            {
                *pplist = cur->next;
            }
            prev->next = cur->next;
            free(del);
            del = NULL;
            return;
        }
        else
        {
            prev = cur;
            cur = cur->next;
        }
    }
}
void RemoveAll(pList *pplist, DataType d)
{
    pNode cur = *pplist;
    pNode prev = NULL;
    assert(pplist);
    if (*pplist == NULL)
    {
        return;
    }
    while (cur)
    {
        if (cur->data == d)
        {
            pNode del = cur;
            if (cur == *pplist)
            {
                *pplist = cur->next;
            }
            else
            {
                prev->next = cur->next;
            }
            cur = cur->next;
            free(del);
            del = NULL;
        }
        else
        {
            prev = cur;
            cur = cur->next;
        }
    }

}
//在pos后面插入一个元素
void Insert(pList *pplist, pNode pos, DataType d)
{
    pNode newNode = BuyNode(d);
    assert(pplist);
    assert(pos);
    if (*pplist == NULL)
    {
        PushFront(pplist, d);
        return;
    }
    newNode->next = pos->next;
    pos->next = newNode;
}
void Erase(pList *pplist, pNode pos)
{
    assert(pplist);
    assert(pos);
    //要删除的是尾节点
    if (pos->next == NULL)
    {
        PopBack(pplist);
    }
    //删除的是非尾节点
    else
    {
        pNode del = pos->next;
        pos->data = pos->next->data;
        pos->next = pos->next->next;
        free(del);
        del = NULL;
    }
}
void DestroyList(pList *pplist)
{
    assert(pplist);
    pNode cur = *pplist;
    while (cur)
    {
        pNode del = cur;
        cur = cur->next;
        printf("del:%d\n", del->data);
        free(del);
        del = NULL;
    }
}

由于这些接口都较为简单,所以不进行具体的测试展示,读者可以自行测试
单链表中还有很多的面试题,之后会汇总起来一一实现。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值