链表的基本操作

本文详细介绍了如何使用尾插法在链表中动态添加节点,包括从头尾插入、数据赋值和释放动态空间的过程,并配以示例。通过实例展示了链表的基本操作,如建立、打印和释放内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        链表的基本操作包括建立(批量存入数据)、打印(输出所有数据)、删除(在批量数据中删除指定数据)、插入(在批量数据中添加一个数据)等。

1、链表的建立

        链表的建立就是从一个空链表开始,一个9一个地添加新结点,直至所有数据都加入该链表。

        链表真正使用时,结点是动态产生的。当出现一个需要处理的数据时,首先动态申请一个结点空间,然后对结点的数据域进行赋值,再对结点的指针域进行处理,使该结点链入到整个单链表中。

按照新结点加入位置的不同,链表的建立大致有以下几种方法:

  • 前插法:新结点每次都插入到链表的最开头,作为新链表的第一个结点;
  • 尾插法:新结点每次都插入到链表的最后面,作为新链表的最后一个结点;
  • 序插法:新结点插入后保证结点域数据的有序性,该法需经搜索确定插入位置;
  • 定位法:新结点插入到链表中制定的位置。

这里主要介绍尾插法的基本思想:

(1)定义两个指针分别指向链表的第一个和最后一个结点,假设这两个指针名字为head 和tail。

(2)初始化链表,即“head=tail=NULL;”让两个工作指针均不指向任何地方。

Node* head, * tail;      //head、tail分别指向链表的头结点和尾结点                 
head = tail = NULL;      //初始化链表:空链表

 (3)通过工作指针p申请一个动态结点空间,然后将数据赋值给动态结点的数据域,指针域及时赋值为空。

p = (Node*)malloc(sizeof(Node));    //动态申请一块结点的内存用于存放数据
p->data = num;                      //将输入的值num存放入新结点的数据域
p->next = NULL;                     //新结点的指针域及时赋为空值

 (4)生成一个新结点p之后,head指针要根据原来链的情况进行不同的处理:如果原来是空链,则head等于p;如果原来非空,则head不需要做任何处理。然后将p所指向的结点,链到tail所指向的结点后面,体现“尾插”思想。最后将p赋值给tail,保证tail始终指向当前链表的最后一个结点处。

if (NULL == head)                   //如果原来链表为空
	head = p;                       //将p赋值给head,p是刚申请的第一个结点
else                                //如果原来链表非空
	tail->next = p;                 //将新结点链入尾部成为新的最后结点
tail = p;

如果原来链表为空:

如果原来链表非空:

 

(5)重复进行(3)、(4)两个步骤,直至结束。

下面的示例给出了用尾插法建立链表,再对该链表进行遍历输出所有的元素,最后利用遍历思想释放所有结点动态空间的完整过程。

#include<stdio.h>
#include<malloc.h>
typedef struct Node       //定义链表结点的类型
{
	int data;             //数据域
	struct Node* next;    //指针域
}Node;                    //定义类型的别名为Node
Node* Create();           //创建一个新的链表
void Print(Node* head);
void Release(Node* head);

int main()
{
	Node* head;             //定义头指针head
	head = Create();        //创建一个新链表,返回头指针赋值给head
	Print(head);            //链表的遍历输出每个元素的值
	Release(head);          //释放链表每个结点的存储空间
	return 0;
}
Node* Create()
{
	Node* head, * tail, * p;      //head、tail分别指向链表的头结点和尾结点
	int num;                   
	head = tail = NULL;         //链表初始化:空链表
	printf("请输入一批数据,以“-9999”结尾:\n");
	scanf_s("%d", &num);
	while (num != -9999)
	{
		p = (Node*)malloc(sizeof(Node));    //动态申请一块结点的内存用于存放数据
		p->data = num;                      //将输入的值存放入新结点的数据域
		p->next = NULL;                     //新结点的指针域及时赋为空值
		if (NULL == head)                   //如果原来链表为空
			head = p;                       //将p赋值给head,p是刚申请的第一个结点
		else                                //如果原来链表非空
			tail->next = p;                 //将新结点链入尾部成为新的最后结点
		tail = p;
		scanf_s("%d", &num);
	}
	return head;
}

void Print(Node* head)
{
	Node* p;                         //定义工作指针P
	p = head;                         //p从头指针开始
	if (NULL == head)                 //如果链表为空则输出提示信息
	{
		printf("链表为空!\n");
	}
	else
	{
		printf("链表如下:\n");
		while (p != NULL)               //用p来控制循环,p为空时指针停止
		{
			printf("%4d", p->data);
			p = p->next;
		}
	}
	printf("\n");
}

void Release(Node* head)   
{
	Node* p1, * p2;
	p1 = head;
	while (p1 != NULL)   //p1用来控制循环,
	{
		p2 = p1;               //p2指向当前删除结点处
		p1 = p1->next;           //p1指向链表下一个结点位置处
		free(p2);             //通过p2释放空间
	}
	printf("链表释放内存成功!\n");
}

运行程序,屏幕上输入数据,结果显示:

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值