头文件
#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;
}