【C语言】单链表的函数封装

单链表函数封装思维导图

单链表函数封装代码和测试

头文件: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

测试结果
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值