单链表的数据结构和基本操作

链表是一种线性结构,在存储数据时,在逻辑上是连续的,但是在物理空间上并不连续。

一个链表的结点由两个部分组成,分别是数据域和指针域。

而单链表就是它的每一个结点,除了记录元素的数据外,只记录其直接后继结点的地址。
在这里插入图片描述
单链表由两种实现方法:

  • 头结点实现
  • 头指针实现

头结点单链表的基本操作

头结点单链表的数据结构

typedef int ElemType;

typedef struct Node {
	ElemType data; 
	struct Node *next;
}HeadList;

头结点的初始化

头结点的初始化只需把头结点的next指针域置空即可。

void InitHeadList(HeadList* head) 
{ 
	if (head == NULL) exit(0);
	head->next = NULL; 
}

插入新结点

在这里插入图片描述
单链表插入新结点的逻辑如上图。
先找到插入位置的前一个结点p,然后申请一个新结点,然后就是:

  1. s->next = p ->next;
  2. p->next = s;
    需要注意:这两步先后顺序不可改变。

头插法插入新结点

思路:

  1. 申请一个新结点,并把新结点的next指针指向头结点的后继节点
  2. 最后把头结点的next指针指向新结点
  3. 插入成功
bool InsertOFHead(HeadList* head, ElemType val) 
{ 
	if (head == NULL) exit(0); 
	if (pos < 0) return false; 
	HeadList* newNode = ApplyNode(val, head->next); 
	if (newNode == NULL) return false; 
	head->next = newNode; 
	return true; 
}

尾插法插入新结点

思路:

  1. 先声明一个结点类型的指针p指向头结点
  2. 把p指针后置,一直到指向最后一个结点,也就是p所指向的结点的后继为空
  3. 申请一个新结点并把指针域置空,把p的后继指向新结点
  4. 插入成功
bool InsertOFTail(HeadList* head, ElemType val) 
{ 
	if (head == NULL) exit(0);
	HeadList* p = head; 
	while (p->next != NULL) p = p->next; 
	p->next = ApplyNode(val, NULL); 
	return true; 
}

按位置插入新结点

思路:

  1. 先声明一个结点类型的指针p指向头结点
  2. p向后迭代,迭代的过程中,迭代一次插入的位置也随之减1
  3. 如果p为空,则插入的位置大于链表的长度,插入失败
  4. 如果插入的位置存在,申请一个新结点,新结点的指针域指向p的next指向的结点
  5. 把p的next指针指向新结点
  6. 插入成功
bool InsertOFPos(HeadList* head, ElemType val, int pos) 
{ 
	if (head == NULL) exit(0); 
	if (pos < 0) return false; 
	HeadList* p = head; 
	while (pos && p != NULL) 
	{ 
		pos--; p = p->next; 
	}
	if (p == NULL) return false; 
	HeadList* newNode = ApplyNode(val, p->next); 
	if (newNode == NULL) return false; 
	p->next = newNode; return true; 
}

删除节点

在这里插入图片描述
单链表删除新结点的逻辑如上图。
先找到删除节点的前一个结点p的位置,q为要删除的结点,然后把p->next = q->next;,然后释放删除的结点即可完成删除。

头删

思路:

  1. 声明一个结点类型的指针q,q指向头结点next指向的结点
  2. 把头结点的next域指向q指向结点的next域
  3. 释放q指向的结点
  4. 删除成功
bool DeleteOFPos(HeadList* head) 
{ 
	if (head == NULL) exit(0); 
	HeadList *q = head->next; 
	head->next = q->next; 
	free(q); 
	return true; 
} 

尾删

思路:

  1. 声明两个指针p、q,p指向头结点,q指向头结点的下一个结点
  2. 把p和q一起迭代,直到q的next为空
  3. 把p的next置空
  4. 释放q
  5. 删除完成
bool DeleteOFTail(HeadList * head) 
{ 
	if (head == NULL) exit(0); 
	if (head->next == NULL) return false; 
	HeadList * p = head, *q = head->next; 
	while (q->next != NULL) 
	{ 
		p = q; 
		q = q->next; 
	}
	p->next = NULL; 
	free(q); 
	return true;
}

按位置删

思路:

  1. 先声明一个结点类型的指针p指向头结点
  2. p向后迭代,迭代的过程中,迭代一次插入的位置也随之减1
  3. 迭代结束如果p的next为空,删除位置没有元素,删除失败
  4. 如果删除的位置存在元素,声明一个结点类型的指针q指向删除位置的元素
  5. 把p->next = q->next;
  6. 释放q指向的结点
  7. 删除完成
bool DeleteOFPos(HeadList* head, int pos) 
{ 
	if (head == NULL) exit(0); 
	HeadList * p = head; 
	while (pos && p->next != NULL) 
	{ 
		pos--; 
		p = p->next; 
	} 
	if (p->next == NULL) return false; 
	HeadList * q = p->next; 
	p->next = q->next; 
	free(q); 
	return true; 
} 

头指针单链表的基本操作

头指针单链表的实现和头结点单链表的实现几乎一致。
和头结点单链表实现的区别: 插入时为空链的特殊处理和删除第一个结点的特殊处理。

实现代码

带头结点单链表的C语言代码实现

头指针单链表的C语言代码实现

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_200_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值