单链表的学习

这篇博客详细介绍了单链表的基本操作,包括如何初始化头节点,增加、删除、查阅和修改节点,以及清空整个链表的函数实现。通过工作指针的移动和节点指针的更新,确保了操作的正确性,并提供了错误检查。示例代码展示了链表的动态操作过程。

注意:

(1)单链表的查阅,删除,插入,都是先将工作指针移动到要操作的节点的前一个节点。

(2)链表的空表判定是num==0 或者 head->next=NULL

指针的移动:

for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
	{
		g=g->next;
	}

一、链表的操作

1、链表的节点结构

分为两个域,数据域保存线性表的数据,指针域存放下一个节点的地址

//链表节点结构 
typedef struct node
{
	int dat;// 数据域 
	struct node *next;//指针域 
}listjd;
int num;//节点计数

2、头结点的初始化

头结点的存在,是可有可无的,存在的意义是统一删除插入操作

//链表头节点的初始化,返回头节点的位置 
listjd* Init()
{
	listjd* hst=(listjd*)malloc(sizeof(listjd));//头结点的内存申请,并赋给头指针hst
	hst->dat=0;//头结点的数据域一般不用,或者用来存放链表的长度
	hst->next=NULL;//避免野指针
	return hst;//返回头指针的地址 
}

3、增

//增  (头指针,选择头插还是尾插,增加的数据值)
void addlist(listjd* hst,int n,int data)
{
	int j;
	listjd *x;//新增节点的地址
	listjd *g=hst;//工作指针
	if(!hst || n>num+1 || n<1)//头节点地址申请失败  或要插入的位置超出表尾 或 插入位置在头节点前 非法
	{
		printf("!!!!!!\n");
		return;
	}

	//新节点的初始化
	x=(listjd*)malloc(sizeof(listjd));//申请新新节点的空间
	x->dat=data;//将数据放入新节点的数据域
	x->next=NULL;//将新节点的指针域指向空,避免野指针

	for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
	{
		g=g->next;
	}
	x->next=g->next;//将工作指针(要新增节点地址的前一个节点地址)的数据域指向赋给新节点的数据域
	g->next=x;//将新节点的地址赋给前一个节点的数据域
	num++;//链表长度增加1
}

4、删

//删(头指针,删除的位置),返回删除的节点数据
int dellist(listjd* hst,int n)
{
	int j;
	int m;//删除的节点数据
	listjd *g=hst;//工作指针
	listjd *L;//留守指针
	if(!hst || n>num || n<1)//头节点地址申请失败  或 要删除的位置超出表尾 或 删除位置在头节点前 非法
	{
		printf("非法!!!\n");
		return 0;
	}
	for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
	{
		g=g->next;
	}
	L=g;//留守指针同工作指针的指向
	g=g->next;//工作指针移动到要删除的节点
	m=g->dat;//将删除的节点的数据保存
	L->next=g->next;//将删除节点的指针域赋给前一个节点,断开了前一个节点和删除节点的链接
	g->next=NULL;//断开删除节点和下一个节点的链接
	free(g);//释放删除的节点内存
	num--;//表长度减1
	g=NULL;
	return m;//返回删除的节点数据
}

5、查

//查(头指针,查阅的数据),返回数据所在的节点位置
int redlist(listjd* hst,int n)
{
	int j=0;//查阅节点的计数
	listjd *g=hst;//工作指针指向头节点
	if(!hst)//头节点地址申请失败 
	{
		printf("!!!!!!\n");
		return 0;
	}
	while(n!=g->dat)//查阅的数字和工作指针指向的节点 的数据域中数据不相同
	{
		g=g->next;//移动工作指针到下一个节点
		j++;//节点位置计数增加
		if(g==NULL)//如果到了表尾还没有查到
		{
			return j=0;
		}
	}
	return j;//返回查到的节点位置
}

6、清

//清除链表,返回链表长度
int clearalllist(listjd* hst)
{
	listjd* g;//工作指针
	while(num!=0 || hst->next!=NULL)//不为空表
	{
		//相当于执行num次删除第一个节点的工作
		g=hst->next;//工作指针指向第一个节点
		hst->next=g->next;//将第一个节点的指针域赋给头节点,断开了头节点和删除节点的链接
		g->next=NULL;
		free(g);
		num--;
	}
	if((num==0) || (hst->next=NULL))//为空表时
	{
		hst->next=NULL;
	}
	return num;//返回此时为0的表长度
}

二、总函数

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

//链表节点结构 
typedef struct node
{
	int dat;// 数据域 
	struct node *next;//指针域 
}listjd;
int num;//节点计数

//链表头节点的初始化,返回头节点的位置 
listjd* Init()
{
	listjd* hst=(listjd*)malloc(sizeof(listjd));//头结点的内存申请,并赋给头指针hst
	hst->dat=0;//头结点的数据域一般不用,或者用来存放链表的长度
	hst->next=NULL;//避免野指针
	return hst;//返回头指针的地址 
}

//增  (头指针,选择头插还是尾插,增加的数据值) 
void addlist(listjd* hst,int n,int data)
{
	int j;
	listjd *x;//新增节点的地址
	listjd *g=hst;//工作指针
	if(!hst || n>num+1 || n<1)//头节点地址申请失败  或要插入的位置超出表尾 或 插入位置在头节点前 非法
	{
		printf("!!!!!!\n");
		return;
	}

	//新节点的初始化
	x=(listjd*)malloc(sizeof(listjd));//申请新新节点的空间
	x->dat=data;//将数据放入新节点的数据域
	x->next=NULL;//将新节点的指针域指向空,避免野指针

	for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
	{
		g=g->next;
	}
	x->next=g->next;//将工作指针(要新增节点地址的前一个节点地址)的数据域指向赋给新节点的数据域
	g->next=x;//将新节点的地址赋给前一个节点的数据域
	num++;//链表长度增加1
}

//删(头指针,删除的位置),返回删除的节点数据
int dellist(listjd* hst,int n)
{
	int j;
	int m;//删除的节点数据
	listjd *g=hst;//工作指针
	listjd *L;//留守指针
	if(!hst || n>num || n<1)//头节点地址申请失败  或 要删除的位置超出表尾 或 删除位置在头节点前 非法
	{
		printf("非法!!!\n");
		return 0;
	}
	for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
	{
		g=g->next;
	}
	L=g;//留守指针同工作指针的指向
	g=g->next;//工作指针移动到要删除的节点
	m=g->dat;//将删除的节点的数据保存
	L->next=g->next;//将删除节点的指针域赋给前一个节点,断开了前一个节点和删除节点的链接
	g->next=NULL;//断开删除节点和下一个节点的链接
	free(g);//释放删除的节点内存
	num--;//表长度减1
	g=NULL;
	return m;//返回删除的节点数据
}

//查(头指针,查阅的数据),返回数据所在的节点位置
int redlist(listjd* hst,int n)
{
	int j=0;//查阅节点的计数
	listjd *g=hst;//工作指针指向头节点
	if(!hst)//头节点地址申请失败 
	{
		printf("!!!!!!\n");
		return 0;
	}
	while(n!=g->dat)//查阅的数字和工作指针指向的节点 的数据域中数据不相同
	{
		g=g->next;//移动工作指针到下一个节点
		j++;//节点位置计数增加
		if(g==NULL)//如果到了表尾还没有查到
		{
			return j=0;
		}
	}
	return j;//返回查到的节点位置
}

//清除链表,返回链表长度
int clearalllist(listjd* hst)
{
	listjd* g;//工作指针
	while(num!=0 || hst->next!=NULL)//不为空表
	{
		//相当于执行num次删除第一个节点的工作
		g=hst->next;//工作指针指向第一个节点
		hst->next=g->next;//将第一个节点的指针域赋给头节点,断开了头节点和删除节点的链接
		g->next=NULL;
		free(g);
		num--;
	}
	if((num==0) || (hst->next=NULL))//为空表时
	{
		hst->next=NULL;
	}
	return num;//返回此时为0的表长度
}

void main()
{
	int m;
	int j;
	listjd* hst=Init();////链表头节点的初始化,返回头节点的位置 
	listjd* p=hst;//工作指针指向头节点
	addlist(hst,1,10);//增  (头指针,选择头插还是尾插,增加的数据值) 
	addlist(hst,2,20);
	addlist(hst,3,30);

	m=dellist(hst,3);//删(头指针,删除的位置),返回删除的节点数据
	printf("被删除的数据为:%d\n",m);

	j=redlist(hst,50);//查(头指针,查阅的数据),返回数据所在的节点位置
	if(j==0)
	{printf("查询失败,没有对应数据\n");}
	else
	{printf("查阅的数据位置为:%d\n",j);}
	
	clearalllist(hst);//清除链表,返回链表长度
	printf("链表长度为:%d\n",num);

	while(p!=NULL)//展示链表的数据
	{
		p=p->next;
		printf("%d ",p->dat);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值