单链表函数封装思维导图
单链表函数封装代码和测试
头文件:linkList.h
#ifndef _LINKLIST_H
#define _LINKLIST_H
#include <stdio.h>
#include <stdlib.h>
//定义单链表的结点结构体
typedef int DataType;
typedef struct Node
{
union
{
int len;//头结点数据域
DataType e;//普通结点数据域
};
struct Node *next;
}LinkList,*LinkListPtr;
//创建链表函数
LinkListPtr lick_create();
//链表判空函数
int empty_linklist(LinkListPtr L);
//申请结点 封装数据的函数
LinkListPtr create_node(DataType e);
//头插法插入数据的函数
int insert_head(LinkListPtr L,DataType e);
//遍历链表的函数
void show_linklist(LinkListPtr L);
//尾插法插入数据的函数
int insert_tail(LinkListPtr L,DataType e);
//在任意指定位置插入数据的函数
int insert_index(LinkListPtr L,int n,DataType e);
//头删法删除数据函数
int del_head(LinkListPtr L);
//尾删法删除数据函数
int del_tail(LinkListPtr L);
//在任意位置删除函数
int del_index(LinkListPtr L,int n);
//按位置修改
int update_index(LinkListPtr L,int n,DataType e);
//按值修改
int update_data(LinkListPtr L,DataType olde,DataType newe);
//按值查找函数,返回当前结点的地址
LinkListPtr find_data(LinkListPtr L,DataType e);
//反转函数
int reverse_linklist(LinkListPtr L);
//销毁链表函数
void free_linklist(LinkListPtr L);
#endif
源文件:linkList.c
#include "linkList.h"
//创建单链表函数实际上相当于创建了一个链表的头结点
LinkListPtr lick_create()
{
LinkListPtr L=(LinkListPtr)malloc(sizeof(LinkList));
if(NULL==L)
{
printf("fail lick_create\n");
return NULL;
}
//给头结点创建空间成功后要给这个结点初始化
L->len=0;
L->next=NULL;
printf("success lick_create\n");
return L;
}
//链表判空函数
int empty_linklist(LinkListPtr L)
{
if(NULL==L)
{
printf("fail empty_linklist\n");
return -1;
}
if(L->len==0||L->next==NULL)
{
return 1;
}
return 0;
}
//申请结点 封装数据的函数
LinkListPtr create_node(DataType e)
{
LinkListPtr node=(LinkListPtr)malloc(sizeof(LinkList));
if(NULL==node)
{
printf("fail create_node\n");
return NULL;
}
//封装数据
node->e=e;
//指针域先置空,后序可以根据实际情况调整
node->next=NULL;
//printf("success create_node\n");
return node;
}
//头插法插入数据的函数
int insert_head(LinkListPtr L,DataType e)
{
if(NULL==L)
{
printf("fail insert_head\n");
return 0;
}
LinkListPtr N=create_node(e); //申请结点封装数据
N->next=L->next; //新结点的指针域指向头结点的下一个结点
L->next=N; //头结点的指针域指向新结点,这样就完成了结点的插入
L->len++; //链表长度自增
printf("success insert_head\n");
return 1;
}
//遍历链表的函数
void show_linklist(LinkListPtr L)
{
if(NULL==L||empty_linklist(L))
{
printf("fail show_linklist\n");
return;
}
LinkListPtr T=L->next; //定义了一个遍历指针,初始化指向头结点的下一个结点,也就是第一个普通结点
printf("show_linklist:\n"); //提示开始遍历指针了
for(int i=0;i<L->len;i++)
{
//输出当前结点的数据域
printf("%d ",T->e);
//输出完成当前结点后,遍历指针指向下一个结点
T=T->next;
}
putchar(10);
printf("success show_linklist\n"); //提示指针遍历结束了
}
//尾插法插入数据的函数
int insert_tail(LinkListPtr L,DataType e)
{
if(NULL==L)
{
printf("fail insert_tail\n");
return 0;
}
//定义遍历指针
LinkListPtr T=L;
//遍历找到尾结点
while(T->next!=NULL){T=T->next;}
//申请结点封装数据
LinkListPtr node=create_node(e);
//尾结点后面插入一个数据
T->next=node;
//插入数据结束后,链表长度自增
L->len++;
printf("success insert_tail\n");
return 1;
}
//在任意指定位置插入数据的函数
int insert_index(LinkListPtr L,int n,DataType e)
{
if(NULL==L||n>L->len+1||n<1)
{
printf("fail insert_index\n");
return 0;
}
//定义遍历指针
LinkListPtr T=L;
//遍历找到要插入数据的位置的上一个结点
for(int i=0;i<n;i++)
{
T=T->next;
}
//申请结点封装数据
LinkListPtr node=create_node(e);
//插入数据
node->next=T->next;
T->next=node;
L->len++;
printf("success insert_index\n");
return 1;
}
//头删法删除数据函数
int del_head(LinkListPtr L)
{
if(NULL==L||empty_linklist(L))
{
printf("fail del_head\n");
return 0;
}
LinkListPtr p=L->next;
L->next=L->next->next;
L->len--;
free(p);
p=NULL;
printf("success del_head\n");
return 1;
}
//尾删法删除数据函数
int del_tail(LinkListPtr L)
{
if(NULL==L||empty_linklist(L))
{
printf("fail del_tail\n");
return 0;
}
LinkListPtr p=L;
//找到倒数第二个结点
for(int i=0;i<L->len-1;i++)
{
p=p->next;
}
LinkListPtr q=p->next; //指针指向最后一个结点的空间
p->next=NULL;
free(q);
q=NULL;
L->len--;
printf("success del_tail\n");
return 1;
}
//在任意位置删除函数
int del_index(LinkListPtr L,int n)
{
if(NULL==L||empty_linklist(L)||n<1||n>L->len)
{
printf("fail del_index\n");
return 0;
}
LinkListPtr p=L;
//找到指定位置结点的前一个结点
for(int i=0;i<n-1;i++)
{
p=p->next;
}
//找到指定位置的结点
LinkListPtr q=p->next;
p->next=q->next;
//释放指定位置指针
free(q);
p=NULL;
//长度自减
L->len--;
printf("success del_index\n");
return 1;
}
//按位置修改
int update_index(LinkListPtr L,int n,DataType e)
{
if(NULL==L||n<1||n>L->len)
{
printf("fail update_index\n");
return 0;
}
//找到这个位置的结点
LinkListPtr q=L;
for(int i=0;i<n;i++)
{
q=q->next;
}
if(q->e==e)
{
printf("fail update_index\n");
return 0;
}
q->e=e;
printf("success update_index\n");
return 1;
}
//按值修改
int update_data(LinkListPtr L,DataType olde,DataType newe)
{
if(NULL==L||olde==newe)
{
printf("fail update_index\n");
return 0;
}
LinkListPtr q=L;
for(int i=0;i<L->len;L++)
{
q=q->next;
if(q->e==olde)
{
q->e==newe;
printf("success update_index\n");
return 1;
}
}
printf("fail update_index,because find no olde\n");
return 0;
}
//按值查找函数,返回当前结点的地址
LinkListPtr find_data(LinkListPtr L,DataType e)
{
if(NULL==L||empty_linklist(L))
{
printf("fail find_data\n");
return NULL;
}
LinkListPtr q=L; //定义遍历结点
for(int i=0;i<L->len;i++)
{
q=q->next;
if(q->e==e)
{
printf("success find_data\n");
return q;
}
}
printf("fail find_data,because no DataType e in list\n");
return NULL;
}
//反转函数
int reverse_linklist(LinkListPtr L)
{
if(NULL==L||empty_linklist(L))
{
printf("fail reverse_linklist\n");
return 0;
}
//创建一个新的头结点
LinkListPtr newL=lick_create();
//用头删和头删将原来的链表的数据删除并插入新的链表,就把数据逆置了
for(int i=0;i<L->len;i++)
{
LinkListPtr temp=L->next; //把原来链表的第一个结点地址提取出来
L->next=L->next->next; //提取出来后在原来链表中删除掉
temp->next=newL->next; //头插法插入新链表中
newL->next=temp;
}
L->next=newL->next; //把新链表赋值给原来的链表
//新链表是局部变量存储在栈区,函数结束时会自动释放
printf("success reverse_linklist\n");
return 1;
}
//销毁链表函数
void free_linklist(LinkListPtr L)
{
if(NULL==L)
{
printf("fail free_linklist\n");
return;
}
//删除所有结点(除了头结点)
while(L->len!=0)
{
del_head(L);
}
//释放头结点
free(L);
L=NULL;
printf("success free_linklist\n");
}
主函数文件:main.c
#include "linkList.h"
int main(int argc, const char *argv[])
{
//创建一个新链表
LinkListPtr L=lick_create();
//头插函数测试
insert_head(L,1);
insert_head(L,2);
insert_head(L,3);
insert_head(L,5);
insert_head(L,6);
insert_head(L,8);
insert_head(L,9);
show_linklist(L);
//尾插函数测试
insert_tail(L,11);
insert_tail(L,12);
insert_tail(L,15);
insert_tail(L,16);
insert_tail(L,18);
insert_tail(L,19);
show_linklist(L);
//头删尾删函数测试
del_head(L);
show_linklist(L);
del_tail(L);
show_linklist(L);
//按位置修改函数测试
update_index(L,1,99);
show_linklist(L);
update_index(L,3,55);
show_linklist(L);
//按值修改函数测试
update_data(L,5,15);
show_linklist(L);
//按值查找函数测试(返回当前结点的地址)
LinkListPtr findPtr=find_data(L,18);
printf("findPtr->e=%d\n",findPtr->e);
//反转函数测试
reverse_linklist(L);
show_linklist(L);
//销毁链表函数测试
free_linklist(L);
return 0;
}
编译指令
gcc *.c
./a.out
测试结果