链表的基本操作:建立,头删,尾删,头插,尾插,查找


前言

下面我会来介绍链表的建立,头删,尾删,头插,尾插,查找,查找删除又分为不同的方法


一、链表的预备

我们将在头文件中建立结点,以及对数据类型进行定义,方便后续的修改

1.1链表类型的定义

 typedef int SLTDateType;//SLT为链表的简写与SL顺序表区分
 //可以根据自己的需要修改类型

1. 2链表的建立

typedef struct SListNode {
	SLTDateType date;//存储的数据
	struct SListNode* next;//用于存储下一个结点的位置
}SLTNode;

二、链表的基本操作

2.1链表的打印(SLTPrint)

void SLTPrint(SLTNode* phead) {//打印
	//链表为空照样可以打印所以不需要
//assert检查是否为空
	SListNode* cur = phead;
	while (cur) {
		printf("%d->", cur->date);
		cur = cur->next;
		//指向下一个结点
	}
	printf("NULL\n");
}

在这里插入图片描述

2.2新节点的建立(BuySLTNode)

SLTNode* BuySLTNode(SLTDateType x) {//建立一个新的结点
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL) {//判断新节点是否为空
		perror("BuySLTNode");
		return NULL;
	}
	//不为空对新结点进行初始化
	newnode->next = NULL;
	newnode->date = x;
	return newnode;//返回新的结点
}

2.3链表的尾插(SLTPushBack)

在这里插入图片描述

void SLTPushBack(SLTNode** pphead,SLTDateType x) {//尾插
	assert(pphead);
	//这里之所以传二级指针是因为我们需要对头指针指向的位置进行修改
	//举个例子:我们修改int的变量要传int*类型
	//那么我们要修改int*类型就要传int**类型
	//头指针类型为SLTNode*类型我们要修改就要传
	//SLTNode**类型才能对其内容进行修改
	SLTNode* newnode = BuySLTNode(x);
	//插入前先建立一个新节点
	if (*pphead == NULL) {
		*pphead = newnode;
		//链表本身就为空,直接让他指向新结点
	}
	else {
		SLTNode* tail = *pphead;
		while (tail->next != NULL) {
			//寻找链表的尾结点
			tail = tail->next;
		}
		tail->next = newnode;
		//找到尾结点以后让其指针域指向新的结点
	}
}

2.4链表的头插(SLTPushFront)

在这里插入图片描述

void SLTPushFront(SLTNode** pphead, SLTDateType x) {//头插
	//头插比较简单只需要把新结点接上改变头指针的指向就行了
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);//建立新结点
	newnode->next = *pphead ;
	//让新结点的指针域指向*pphead所指向的位置
	*pphead = newnode;//头指针指向新结点
	//无论原先链表为不为空都适用
}

2.5链表的尾删(SLTPopBack)

在这里插入图片描述

void SLTPopBack2(SLTNode** pphead) {//尾删 
	assert(pphead);
	assert(*pphead);//肯定要有结点才能删,所以要判断是否为空
	if ((*pphead)->next == NULL) {//只有一个结点的情况
		free(*pphead);//直接把结点释放掉置空就完事了
		*pphead = NULL;
	}

	else {//两个及两个结点以上的情况
		SLTNode* prev = NULL;//用来存tail前一个结点
		SLTNode* tail = *pphead;//用来找尾结点
		while (tail->next != NULL) {
			prev = tail;
			tail = tail->next;
		}
		free(tail);//找到尾结点后释放
		prev->next = NULL;
//	让尾结点前一个元素的指针域置为空,因为你后面一个结点释放掉了
//没有必要让prev存一个没有用的地址
	}
}

2.6链表的头删(SLTPopFront)

在这里插入图片描述

void SLTPopFront(SLTNode** pphead ) {//头删
	assert(pphead);
	assert(*pphead);//肯定要有结点才能删,所以要判断是否为空
	SLTNode* first = *pphead;//保存头指针当前指向结点
	*pphead = first->next;//让头指针指向当前结点的下一个指针域
	free(first);
	first = NULL;
}

2.7链表的插入1(在指定结点之前的插入)(SLTInsertBefore)

在这里插入图片描述

void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDateType x) {//在pos之前插入元素
	assert(pos);//判断结点是否有意义
	assert(pphead);
	if (*pphead == pos) {//在pos前插入此时pos为头结点
		SLTNode* newnode = BuySLTNode(x);
		newnode->next = *pphead;
		*pphead = newnode;
		//等价于头插
		//SLTPushFront(pphead,x);
	}
	else {//pos不为头结点
		SLTNode  * prev=*pphead;
		while (prev->next != pos) {
			prev = prev->next;
			//寻找pos之前的一个结点
		}
		SLTNode* newnode = BuySLTNode(x);
		newnode->next =pos;
		//新结点后面接上pos
		prev->next = newnode;
		//原先pos之前的结点再接上新结点
	}
}

2.75链表的插入2(在指定结点之后插入)(SLTInsertAfter)

在这里插入图片描述

void SLTInsertAfter( SLTNode*pos, SLTDateType x) {//从pos后面插入,常用
	 //不需要遍历链表也能插入
	assert(pos);
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = pos->next;
	//新结点的指针域指向pos的指针域,相当于新结点接上 
	//pos后面的元素
	pos->next = newnode;//pos接上新结点
}

2.8 链表的删除(删除指定的结点)(SLTErase)

在这里插入图片描述

void  SLTErase (SLTNode** pphead, SLTNode* pos) {//删除指定结点pos
	assert(pphead);
	assert(pos);//判断结点是否有意义
	if (*pphead == pos) {//要删除元素为头结点
		SLTNode* first = *pphead;//保存当前头结点
		*pphead = first->next;//头指针指向下一个位置
		free(first);//释放
		first = NULL;
		//SLTPopFront
		//相当于头删
	}
	else {
		SLTNode* prev = *pphead;
		while (prev->next != pos) {
			prev = prev->next;
		}
		//寻找pos之前的一个结点
		prev->next = pos->next;
		//prev指针域存pos后面的结点
		free(pos);
		pos = NULL;
	}
}

2.85链表的删除(删除指定结点后面一个结点)(SLTEraseAfter)

在这里插入图片描述

void SLTEraseAfter( SLTNode* pos) {//pos后面一个结点的删除,常用
	assert(pos);
	assert(pos->next);//判断pos后面是否又结点
	//不需要遍历链表也能插入
	SLTNode* del = pos->next;//要删除结点
	pos->next = del->next;
	//pos的指针域存要删除结点的下一个结点
	free(del);
	del = NULL;
}

2.9链表的删除(SLTDestroy)

void SLTDestroy(SLTNode** pphead) {
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur) {
		SLTNode*tmp = cur->next;//保存当前节点的下一个结点
		free(cur);
		cur = tmp;//让当前结点指向下一个结点
	}
	*pphead = NULL;
}
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值