单链表的实现(c 语言)

目录

一、单链表的特点 

二、链表实现思想 

​三、具体实现 

1. 定义数据节点

2. 进行数据的头插

3. 任意位置插入数据

4. 任意数据的删除

5,对链表的打印

一、单链表的特点 

数据空间是不连续的,相较于顺序表其数据的存储和删除在相应情况下效率更高。

二、链表实现思想 

利用结构体定义一个数据节点 :包含 数据 和 指向下一个数据节点的指针

这样就可以通过调用 一个数据节点 找到 n 个数据节点 ,进而形成 表状 的数据储存形式 。

相应图解:

三、具体实现 

1. 定义数据节点

typedef int Slist_type  //重命名数据类型 ,方便后期的应用和修改

typedef struct Slist_code
{
    struct Slist_type date;        //用来存储数据
    struct Slist_code* next;      //指向下一个数据的指针     
}Slist_code;

2. 进行数据的头插

   先定义一个创建新空间的函数(方便后面的重复使用)

Slist_code* Slist_ADD()
{
    Slist_code* Newcode = (Slist_code*)malloc(sizeof(Slist_code));
    assert(Newcode);
    Newcode -> next = NULL;    
    Newcode -> date = 0;
    return Newcode; 
}

注:因为每次头插链表的起始点需要更改,所以:

       函数参数要设定传入二级指针,因为要修改指针 。

    (链表起点是一个指针,指向起始节点 ,未设置起始节点时,默认为初始化为NULL)

void Head_ADD_code(Slist_code**p,Slist_type date)
{
     assert(p);
     Slist_code* tem = Slist_ADD_code(date);
     tem->next = *p;     //新节点存放旧节点位置
     *p = tem;           //起始位置要变成新节点的位置
}

3. 任意位置插入数据

 这里插入的步骤的原理通俗点讲就是 : 新节点将上一节点干的活揽过来(新节点 存放插入位置前一个节点 存放的指针),并且 上一个节点存放的指针 要改为 指向新节点 。

(要注意到这里设置的是在寻找的对应位置后插入一个数据,如果没找到就在最后插入一个数据)

注:因为,要考虑到没有数据的情况 :再添加完第一个数据后要修改链表起点,指向首次开辟的        内存空间 。

void Arb_ADD_code(Slist_code** p ,Slist_type date)
{
	assert(p);          //检查防止传入空二级指针
	if (*p)
	{
		Slist_code* tem = *p;
		Slist_code* tem2 = *p;
		for (; tem->next != NULL;)
		{
			if (tem->date == date)          //如果找到对应位置,弹出
			{
				break;                       //此时 tem 记录的是对应的数据节点
			}
			tem = tem->next;               //没找到就 遍历到下一个节点
		}
		Slist_code* tem1 = Slist_ADD_code(date); //tem记录的(寻找到的对应位置)或
		tem1->next = tem->next;                               (最后的节点)
		tem->next = tem1;
	}
	else                //如果没有数据 
	{
		*p = Slist_ADD_code(date);
	}
}

4. 任意数据的删除

删除就是将删除位置的前后两个节点重新相连 ,后节点的位置从 要删除的节点中 找到 ,

并且,每次遍历循环时要用一个临时变量把前一个节点记住 ,这样就能既找到后节点,又找到前节点 。

注 :特殊情况 1 . 删除起点时,起点也要随之改变

                      2 . 未找到要删除的数据

                      3 . 空间无数据

void Slist_Delet(Slist_code**p,Slist_type date)
{
    assert(p);          
	Slist_code* tem = *p;
	Slist_code* tem1 = *p;
	assert(*p);                //防止无数据
	int k = 0;
	for (;tem->next != NULL; tem = tem->next)
	{
		if (tem->date == date) //查找元素
		{
			k = 1;
			break;
		}
		tem1 = tem;            //始终记录 tem 前的一个节点
	}
	if (k||tem->date == date)  //如果全不相等
	{
		Slist_code* tem2 = (*p)->next;   //先把首数据的下一个节点地址存储
		if ((*p)->date == date)          //如果首数据被删除
		{
			free(*p);
			*p = tem2;                   //起点要改为 tem2 
		}
		else
		{
			tem1->next = tem->next;     
			free(tem);
		}
	}
	else
		printf("没找到\n");
}

5,对链表的打印

打印不需要修改指针,参数传一级指针就行。

void Print_date(Slist_code* P)
{
   for(;P;P = P->next)
   {
       printf("%d\n",P->date);
   }
   printf("\n");
}

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值