线性链表(单链表)的基本操作

笔记 同时被 2 个专栏收录
12 篇文章 0 订阅
8 篇文章 0 订阅

一 . 链表的特点和定义

链表是一种物理上非连续、非顺序的存储结构,数据元素之间的顺序是通过每个元素的指针关联的。

链表的特点

  1. 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成
  2. 由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间

每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
链表结构图:
在这里插入图片描述

二 . 单链表的基本操作的实现

单链表又分为有空头和无空头,下列操作在无空头的基础上进行
有空头的操作更加简便

1 . 初始化

创建结点结构体,定义头尾指针

#include<iostream>
#include<cstdlib>
using namespace std;
//结点结构体
struct Node{
	int a;
	struct Node *pNext;
};
//链表头尾指针
struct Node *g_pHead = NULL;
struct Node *g_pEnd = NULL;

2 . 添加

1) 头添加

将该结点的指向下一个的指针指向原有链表的头,然后将该结点定为新链表的头

//创建链表,在链表中增加一个数据   头添加
void AddListHead(int a) {
	//创建一个结点
	struct Node* pTemp = (struct Node*) malloc(sizeof(struct Node));
	//节点数据进行赋值	
	pTemp->a = a;
	pTemp->pNext = NULL;
	//如果链表为空
	if (NULL == g_pHead || NULL == g_pEnd) {
		//空链表 既是头也是尾
		g_pHead = pTemp;
		g_pEnd = pTemp;
	}
	//不为空链表
	else {
		pTemp->pNext = g_pHead;//将该结点的下一个指向原有链表的头
		g_pHead = pTemp;		//将该结点定为为新链表的头
	}
}

2) 尾添加

原有链表的尾的下一个指针指向该结点,将该结点定为新链表的尾。

//创建链表,在链表中增加一个数据   尾添加
void AddListEnd(int a) { 
	//创建结点
	struct Node* pTemp = (struct Node*) malloc(sizeof(struct Node));
	//节点数据进行赋值		
	pTemp->a = a;
	pTemp->pNext = NULL;
	//如果链表为空
	if (NULL == g_pHead || NULL == g_pEnd) {
		//空链表 既是头也是尾
		g_pHead = pTemp;
		g_pEnd = pTemp;
	}
	//不为空链表
	else {
		g_pEnd->pNext = pTemp;//原有链表的尾的下一个指针指向该结点
		g_pEnd = pTemp; 	   //原有链表的尾的下一个指针指向该结点
	}
}

3 . 查

1) 遍历整个链表

void ScanList() {
	//定义中间指针
	struct Node *pTemp = g_pHead;
	while (pTemp != NULL) {
		cout << pTemp->a << endl; //输出该结点的值
		pTemp = pTemp->pNext;
	}
}

2) 查询指定结点

//查询指定的结点
struct Node* SelectNode(int a) {
	//定义中间指针
	struct Node* pTemp = g_pHead;
	while (pTemp != NULL) {
		if (a == pTemp->a) {
			return pTemp;		//查询到,返回该结点的值
		}
		pTemp = pTemp->pNext;
	}
	return NULL;			//未查询到返回值为NULL
}

4 . 插入

指定位置插入结点

//指定位置插入结点
void AddListRand(int index, int a) {
	//链表为空
	if (NULL == g_pHead) {
		cout << "链表没有节点" << endl;
		return;
	}
	//找位置
	struct Node* pt = SelectNode(index);
	if (NULL == pt) {
		cout << "没有指定节点" << endl;
	}
	//有此结点
	//给a创建结点
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	//结点成员赋值
		pTemp->a = a;
		pTemp->pNext = NULL;
		if (pt == g_pEnd) {
			g_pEnd->pNext = pTemp;
			g_pEnd = pTemp;
	}
		else {
			pTemp->pNext = pt->pNext;
			pt->pNext = pTemp;
		}
}

5 . 删除

1) 尾删除

//尾删除   
void DeleteListEnd() {
	//链表为空
	if (NULL == g_pEnd) {
		cout << "链表为空,无需释放" << endl;
		return;
	}
	
	// 链表只有一个结点
	if (g_pHead == g_pEnd) {
		free(g_pHead);		//释放该结点(删除该结点)
		g_pEnd = NULL;
		g_pHead = NULL;
	}
	else {	
	//链表有多个结点
	struct Node* pt = g_pEnd;
	//找到尾巴的前一个结点
	struct Node* ptemp = g_pHead;
	while (ptemp->pNext != g_pEnd) {
		ptemp = ptemp->pNext;
	}
	ptemp->pNext = NULL;//将尾结点的上一个结点的下一个的指针指向NULL
	g_pEnd = ptemp;
	free(pt);       //释放节点(删除该结点)
	}
}

2) 头删除

//头删除   
void DeleteListHead() {
	//链表为空
	if (NULL == g_pHead) {
		cout << "链表为空,无需释放" << endl;
		return;
	}
	// 链表只有一个节点
	if (g_pHead == g_pEnd) {
		free(g_pHead);	//释放该结点(删除该结点)
		g_pEnd = NULL;
		g_pHead = NULL;
	}
	//多个结点
	else {	
	struct Node* pTemp = g_pHead;//定义中间指针记录原有链表的头
	g_pHead = g_pHead->pNext;//将链表头设置为原链表的下一个
	free(pTemp);		//释放该结点(删除该结点)
}

3) 删除指定结点

//删除指定结点
void DeleteListRand(int a) {
	//链表判断
	if (NULL == g_pHead) {
		cout << " n o" << endl;
		return;
	}
	struct Node* pTemp = SelectNode(a);//调用查询函数,查询值为a的结点,并赋值给中间结点pTemp
	// 无
	if (NULL == pTemp) {
		cout << "查无此节点" << endl;
		return;
	}
	//找到了
	//只有一个结点
	if (g_pHead == g_pEnd) {
		free(g_pHead);
		g_pHead = NULL;
		g_pEnd = NULL;
	}
	//两个结点
	else if (g_pHead->pNext == g_pEnd) {
		if (g_pHead == pTemp) {//如果头为指定结点
			DeleteListHead();//调用函数删除头结点
		}
		if(g_pEnd == pTemp){//如果尾为指定节点
			DeleteListEnd();//调用函数删除尾结点
		}
	}
	//多个结点
	else {
		if (g_pHead == pTemp) {//如果头为指定结点
			DeleteListHead();//调用函数删除头结点
		}
		else if (g_pEnd == pTemp) {//如果尾为指定节点
			DeleteListEnd();//调用函数删除尾结点
		}
		else {
			//创建中间结点
			struct Node* ptemp = SelectNode(a);//调用查询函数,查询值为a的结点,并赋值给中间结点pTemp
			//找到之后
			ptemp->pNext = pTemp->pNext;
			free(pTemp);  //释放该结点
		}
	}
}

6 . 清空链表

void freeList() {
	struct Node* pTemp = g_pHead;
	while (pTemp != NULL) {
		struct Node* pt = pTemp;
		pTemp = pTemp->pNext;
		free(pt);
	}
	//头尾清空
	g_pHead = NULL;
	g_pEnd = NULL;
}

emmmm 单链表的基操希望能够对你有帮助。。。。加油💪
单链表的基本操作的汇总见下篇博客呦。

  • 4
    点赞
  • 0
    评论
  • 12
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值