C++ 数据结构算法 学习笔记(3)-链表

C++ 数据结构算法 学习笔记(3)-链表

原理精讲

链表是线性表的链式存储方式,逻辑上相邻的数据在计算机内的存储位置不必须相邻,那么 怎么表示逻辑上的相邻关系呢?可以给每个元素附加一个指针域,指向下一个元素的存储位 置。如图所示:

在这里插入图片描述
从图中可以看出,每个结点包含两个域:数据域和指针域,指针域存储下一个结点的地址, 因此指针指向的类型也是结点类型

链表的核心要素:

  • 每个节点由数据域和指针域组成
  • 指针域指向下一个节点的内存地址

其结构体的定义:

typedef struct LinkNode{
	ElemType data;
	struct LinkNode *next;
}LinkList,LinkNode; 

单链表的概念

链表的节点均单向指向下一个节点,形成一条单向访问的数据链

他可以想象成一条链,每一节都挨在一起.如下图所示
在这里插入图片描述
在这里插入图片描述

需要注意的是链表头结点都不会有数据,它只有指针域,指向下一个元素的存储位.

而最后一个节点会有数据,但是他的指针域会指向NULL的位置!

单链表的初始化

代码例子如下:

typedef struct _LinkNode
{
	int data;
	struct _LinkNode* next;
}LinkNode, LinkList;

bool InitList(LinkList*& L)
{
	L = new LinkNode;
	if (!L) return false;
	L->next = NULL;
	return true;
}

在这里插入图片描述

正如之前所说的, 头结点不会有数据存储,只会有指针域,指向下一个元素的存储位

问题:为什么 LinkList*& L 需要使用引用?

答: 这是因为如果没有引用的话,原本在main函数里传递的这个指针将传的是一个形参. 这将导致main函数里的 LinkList*指针不会正真的指向 InitList函数里的 new LinkNode. 当InitList函数结束时 main函数里的 LinkList*还是会指向NULL

单链表的前插法

代码例子如下:

bool ListInsert_front(LinkList*& L, LinkNode* node)
{
	if (!L || !node) return false;

	node->next = L->next;
	L->next = node;
	return true;
}

在这里插入图片描述

这里需要深入了解的地方是:

  • 当一个新的节点插入时,头节点的指针域需指向新的节点位置
  • 而新的节点位置需指向之前头节点指向的位置, 所以代码就是以这个原理执行的.

单链表的尾插法

代码例子如下:

bool ListInsert_end(LinkList*& L, LinkNode* node)
{

	if (!L || !node) return false;
	LinkNode* last = NULL;
	last = L;
	while (last->next)
	{
		last = last->next;
	}
	node->next = NULL;
	last->next = node;
}

在这里插入图片描述

这里需要注意的地方是:

  • 代码里的while循环是为了寻找到链表的最后一个节点, 所以里面的判断为last->next. 当这个为false时,last将会指向最后一个节点.

  • 因此,把node当成最后一个节点修改它的指针域为 NULL,并且把原本应该是最后一个节点的指针域指向新的node位置.

单链表任意位置的插入

bool LinkInsert(LinkList*& L, int i, int& e)
{
	if (!L) return false;

	int j = 0;
	LinkList* p, *s;
	p = L;
	
	while (p && j < i - 1)  //Search for the position i-1 node, p will pointing to the node
	{
		p = p->next;
		j++;
	}
	if (!p || j > i - 1)
	{
		return false;
	}

	s = new LinkNode; //Construct new node
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

在这里插入图片描述

这里需要注意的地方是:

  • while (p && j < i - 1)这个循环之所以要-1是因为我们先要指向要插入节点的位置的前一个节点. 以便可以让当前的这个节点的指针域指向新的节点s

  • 代码里需要if (!p || j > i - 1)的原因是用户可能输入要插入的值为负数,这样的话是不可能能在链表里插入的,所以我们要做防御式编程. 而 !p的 目的也是一样可能链表只有5个节点 但是用户输入要在第10个节点插入!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值