C语言实现链表的增删改查等操作

众所周知,链表的应用还是比较广泛的,其在于数据的处理比较方便;本文主要讲述用C语言实现链表的增删改查等一些功能,环境是在Linux下。

注:下文案例是建立在整型数据基础上的,如果是其他类型的数据,请参考修改即可。

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


typedef int elem_type;    //这个只是把int取了个外号,可以不需要这一步,但是记得下文的elem_type都要换成int (如果不需要这一步)


// 声明节点类型
typedef struct node_t
{
    elem_type data;       // 数据域,存放一个数据元素
    struct node_t* next;  // 指针域,存放后继节点的指针
} node;


// 创建一个空链表
node* create(void)
{
    node* n = (node*)malloc(sizeof(node));
    n->next = NULL;                                                                             

    return n;
}


// 销毁某个链表
void destroy(node* l)
{
    node* p = NULL;

    while(l != NULL)
    {
         p = l->next;
         free(l);
         l = p;                                                                              
    }
}


// 在链表尾部插入新的节点
void push_back(node* l, elem_type data)
{
    // 创建一个新节点
    node* n = (node*)malloc(sizeof(node));
    n->data = data;
    n->next = NULL;

    // 找到链表的尾节点
    while(l->next != NULL)
                l = l->next;                                                                        

    // 在尾部插入新节点
    l->next = n;
}


// 在链表头部插入节点
void push_front(node* l, elem_type data)
{
    // 创建一个新节点
    node* n = (node*)malloc(sizeof(node));
    n->data = data;
    n->next = l->next;

    // 将新节点插入头节点之后
    l->next = n;
}


// 在链表中任意位置插入节点
void insert(node* l, unsigned int pos, elem_type data)
{
    // 创建一个新节点
    node* n = (node*)malloc(sizeof(node));
    n->data = data;

    // 找到要插入新节点的位置
    while(pos-- && l->next != NULL) l = l->next;

    // 在上面找到的节点之后插入新节点                                                           
    n->next = l->next;
    l->next = n;
}


// 删除某个节点
int my_remove(node* l, elem_type data)
{
    node* p = NULL;

    // 找到待删除节点的前驱节点
    // 如果待删除的节点存在,下面循环结束后 l 就是待删除节点的前驱节点的指针
    while(l->next != NULL && l->next->data != data)
        l = l->next;

    // 目标节点不存在,删除失败返回 0
    if(l->next == NULL) return 0;

    // 将待删除节点的前驱和后继连接起来,否则链表会断为两截
    // 释放待删除的节点
    p = l->next;
    l->next = p->next;
    free(p);                                                                                    

    // 删除成功就返回 1
    return 1;
}


// 修改(更新)链表节点数据
int update(node* l, elem_type old_val, elem_type new_val)
{
    // 遍历链表找到目标节点
    l = l->next;
    while(l != NULL && l->data != old_val)
        l = l->next;

    // 如果找不到要修改的数据,就返回 0,表示修改失败
    if(l == NULL) return 0;

    // 如果找到了要修改的数据,就修改它,然后返回 1,表示修改成功
    l->data = new_val;
    return 1;
}


// 清空,即删除所有存放有数据元素的节点,就是将所有数据元素删除
void clear(node* l)
{
    node* p = l->next, *q = NULL;

    while(p != NULL)
    {
        q = p->next;                                                                        
        free(p);
        p = q;
    }

    l->next = NULL;
}


// 打印链表中所有节点的数据                                                                         
void show(node* l)
{
    // 遍历链表所有节点
    l = l->next;
    while(l != NULL)
    {
        printf("%d ", l->data);
        l = l->next;
    }

    printf("\n");
}


// 逆序
void reverse(node* l)
{
    node* p = NULL, *q = NULL;                                                                      

    // 如果链表为空(没有任何数据元素),直接返回
    if(l->next == NULL) return;

    p = l->next->next;
    l->next->next = NULL;  // 最初的第一个节点逆序后将变为尾节点

    // 从第二个节点开始,依次插入到最前面(头节点之后)
    while(p != NULL)
    {
        q = p->next;
        p->next = l->next;
        l->next = p;
        p = q;
    }
}


// 求长度
int size(node* l)
{
    int cnt = 0;

    l = l->next;

    while(l != NULL)
    {
        cnt++;                                                                              
        l = l->next;
    }
        
    return cnt;
}


// 判空
int empty(node* l)                                                                                  
{
    return !(l->next);
}


/* 使用案例 */
int main(int argc, char* argv[])
{
    node* l1 = create();

    show(l1);

    if(empty(l1))                                                                                   
    {
        printf("链表 l1 为空!\n");
    }

    push_back(l1, 5);    //尾部插入
    push_back(l1, 3);
    push_front(l1, 9);    //头部插入

    if(!empty(l1))
    {
        printf("链表 l1 不为空!\n");
    }

    push_back(l1, 4);
    printf("链表 l1 的长度为 %d\n", size(l1));  // 4

    push_front(l1, 6);

    //任意位置插入
    insert(l1, 3, 8);       // 中插
    insert(l1, 10000, 10);  // 尾插
    insert(l1, 0, 7);       // 头插

    my_remove(l1, 5);    //删除

    if(!my_remove(l1, 13))
    {
        printf("链表中不存在 13,删除失败!\n");
    }

    if(update(l1, 8, 88))    //更新
    {
        printf("8 -> 88 修改成功!\n");
    }                                                                                               

    if(!update(l1, 20, 30))
    {
        printf("20 -> 30 修改失败!\n");
    }

    printf("逆序前:\n");
    show(l1); // 7 6 9 88 3 4 10

    reverse(l1);    //逆序

    printf("逆序后:\n");
    show(l1);

    return 0;
}

 

上述运行结果如下:

/*
    链表 l1 为空!
    链表 l1 不为空!
    链表 l1 的长度为 4
    链表中不存在 13,删除失败!
    8 -> 88 修改成功!
    20 -> 30 修改失败!
    逆序前:
    7 6 9 88 3 4 10 
    逆序后:
    10 4 3 88 9 6 7
*/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值