自己编写链表函数库详解

本文详细探讨了如何从零开始编写自己的链表函数库,涵盖了头文件的创建,以及一系列关键的链表操作函数实现,包括插入、删除、遍历等核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

头文件

#ifndef _LINKLIST_H
#define _LINKLIST_H

#define SUCCESS 10000
#define FAILURE 10001
#define TRUE    10002
#define FALSE   10003

typedef int ElemType;

struct node
{
    ElemType data;      //数据域
    struct node *next;  //指针域
};

typedef struct node Node;

int InitLinkList(Node **l);
int InsertLinkList(Node *l, int n, ElemType e);
int TraverseLinkList(Node *l, void(*p)(ElemType));
int LinkList_Len(Node *l);
int LinkListEmpty(Node *l);
int GetElem(Node *l, int n, ElemType *e);
int LocateElem(Node *l, ElemType e, int (*p)(ElemType,ElemType));
int DeleteLinkList(Node *l, int p, ElemType *e);
int ClearLinkList(Node *l);      
int DestroyLinkList(Node **l);
int ReverseLinkList(Node *l);

#endif

函数库

#include "LinkList.h"
#include <stdlib.h>

//初始化条件:结构体指针已存在,并且传入函数
//参数:Node **l l是一个指针,l的类型是Node **,l指向的类型是Node *
//函数功能:创建一个首结点,该结点指针域为NULL
int InitLinkList(Node **l)
{
    (*l) = (Node *)malloc(sizeof(Node) * 1);
    if(NULL == *l)
    {
        return FAILURE;
    }

    (*l)->next = NULL;

    return SUCCESS;
}

//初始化条件;头指针传入函数,位置n不大于链表的长度
//参数:l 头指针 n 要插入的位置 e 要插入的数据
//函数功能:在链表中新插入一个结点
int InsertLinkList(Node *l, int n, ElemType e)
{
    Node *p = l;                //定义一个指针指向头结点
    int k = 1;                      //移动的次数

    if (NULL == l)              //入参判断
    {
        return FAILURE;
    }

    while (k < n && p != NULL)  //p移动到指向要插入位置前一个结点
    {
        p = p->next;
        k++;
    }

    if (k > n || NULL == p) //所有意外情况都包含进去了
    {
        return FAILURE;
    }

    Node *q = (Node *)malloc(sizeof(Node) * 1); //  给新节点分配空间
    if (NULL == q)          //检查是否分配成功
    {
        return FAILURE;
    }

    q->data = e;            //给新创建的结点赋值
    q->next = p->next;      //新结点指向原来n处的结点
    p->next = q;            //原来n的前一个结点指向新结点

    return SUCCESS;
}

//初始化条件,头指针传入函数
//参数:l 头指针 p 函数指针,指向输出函数
//函数功能:逐个输出链表每个结点的值
int TraverseLinkList(Node *l, void(*p)(ElemType))
{
    Node *q = l;                //定义一个指针指向头结点

    if (NULL == l)               //入参判断
    {
        return FAILURE;
    }

    while (q->next != NULL)     //当q指向最后一个结点的时候结束循环
    {
        q = q->next;            //q指向后一个结点
        p(q->data);             //输出q指向结点的数据
    }

    return SUCCESS;
}

//初始化条件:头指针传入函数
//参数:l头指针
//函数功能:求出链表的长度
int LinkList_Len(Node *l)
{
    if (NULL == l)
    {
        return FAILURE;
    }

    int len = 1;
    Node *p = l->next;

    while (p)
    {
        len++;
        p = p->next;
    }

    return len;
}

//初始化条件:
//参数 l 头指针
//函数功能,判断链表是否为空
int LinkListEmpty(Node *l)
{
    return (NULL == l->next) ? TRUE : FALSE; //头结点之后没有结点,为空链表
}

//初始化条件:头指针传入函数,结点n不小于1,结点n要存在
//参数: l 头指针 n 要查看的位置 e 保存查看的那个结点的数据
//函数功能:得到链表中第n个结点的数据并返回其值
int GetElem(Node *l, int n, ElemType *e)
{
    if (NULL == l || n < 1)
    {
        return FAILURE;
    }

    Node *p = l;
    int i;

    for (i = 0; i < n && p != NULL; i++)
    {
        p = p->next;
    }

    if (!p)
    {
        return FAILURE;
    }

    *e = p->data;
    
    return SUCCESS;
}

//初始化条件:头指针传入函数
//参数 l 头指针 e 要查找的元素 p 函数指针 指向比较函数
//函数功能:查看e在链表中的第几个结点
int LocateElem(Node *l, ElemType e, int (*p)(ElemType,ElemType))
{
    if (NULL == l)                  //入参判断
    {
        return FAILURE;
    }

    Node *q = l->next;              //定义一个结点指向第一个节点
    int len = 1;                    //结点的个数

    while (q)                       //挨个比较e与结点数据是否相等
    {   
        if (TRUE ==p(e,q->data))    //如果相等,返回第几个结点
        {
            return len;
        }
        q = q->next;                //指向下一个结点
        len++;                      //结点个数加1
    }

    return FAILURE;                 //如果没有,返回失败
}

/*
 *参数: l 头指针
 *      p 要删除的位置,不能大于链表长度,不能小于1 
 *      e要保存p处结点的数据
 *函数功能:删除p处结点,并保存其数据域的值
 *返回值:SUCCESS/FAILURE
 */
int DeleteLinkList(Node *l, int p, ElemType *e)
{
    if (NULL == l)              //入参判断
    {
        return FAILURE;
    }

    int k = 1;                  //移动次数
    Node *q = l;

    while (k < p && q != NULL)
    {
        q = q->next;
        k++;
    }
                                //找到要删除的位置前一个结点
    if (k > p || NULL == q)
    {
        return FAILURE;
    }

    Node *n = q->next;          //定义一个指针指向要删除的结点
    *e = n->data;               //保存要删除结点的数据
    q->next = n->next;      //将要删除的结点与要删除的结点后面一个结点建立联系
    free(n);                //释放给要删除结点分配的空间

    return SUCCESS;
}

/*
 *参数:l 头指针
 *实现功能:删除除了头结点外的所有结点
 *返回值:SUCCESS/FAILURE
 */
int ClearLinkList(Node *l)
{
    if (NULL == l)              //入参判断
    {
        return FAILURE; 
    }
    
    Node *p = l->next;          //指针p指向第一个结点
    while (p)                   //while循环删除第一个结点以后所有结点
    {
        l->next = p->next;      
        free(p);
        p = l->next;
    }

    return SUCCESS;
}


/*
 * 参数:l头指针 不为空
 * 实现功能:销毁链表,释放为链表分配的空间
 * 返回值:SUCCESS/FAILURE
 */
int DestroyLinkList(Node **l)
{
    if (NULL == l)          //入参判断
    {
        return FAILURE;
    }

    free(*l);               //释放链表空间
    *l = NULL;              //不变为空指针,会成野指针,内存泄漏

    return SUCCESS;
}

/*
 *参数:l 头指针 不为空
 *实现功能:反转链表
 *返回值:TRUE/FALSE
 */
int ReverseLinkList(Node *l)
{
    if (NULL == l)          //入参判断
    {
        return FAILURE;
    }

    Node *p = l->next;      //p指向第一个结点
    l->next = NULL;         //首结点与第一个结点断开

    while (p)               //执行循环直到最后一个结点
    {
        Node *q = p;        //指针q指向p
        p = p -> next;      //p指向下一个结点
        q->next = l->next;  //将q结点与头结点后面一个结点相连
        l->next = q;        //头结点与q相连
    }

    return SUCCESS;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值