数据结构单向链表和循环链表的插入 | 第二套

1,874 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

为什么是圆形? 在单向链表中,为了访问链表的任何节点,我们从第一个节点开始遍历。如果我们位于列表中间的任何节点,则无法访问给定节点之前的节点。这个问题可以通过稍微改变单链表的结构来解决。在单向链表中,下一部分(指向下一个节点的指针)为 NULL。如果我们利用这个链接指向第一个节点,那么我们就可以到达前面的节点。

在我们这篇文章中,解释了使用单向链表在循环链表中实现和插入节点。

实现 
为了实现一个循环单向链表,我们使用一个指向链表最后一个节点的外部指针。如果我们有一个指针 last 指向最后一个节点,那么 last -> next 将指向第一个节点。

指针last指向节点 Z 并且 last -> next 指向节点 P。

为什么我们采用指向最后一个节点而不是第一个节点的指针?
为了在开头插入一个节点,我们需要遍历整个链表。此外,为了在最后插入,必须遍历整个列表。如果我们使用指向最后一个节点的指针而不是
开始*指针,那么在这两种情况下都不需要遍历整个列表。因此,无论列表的长度如何,在开头或结尾插入都需要恒定的时间。

插入 
节点可以通过三种方式添加: 

  • 插入空列表
  • 在列表开头插入
  • 在列表末尾插入
  • 在节点之间插入

在空列表中插入 
最初,当列表为空时,最后一个指针将为 NULL。

插入后,T是最后一个节点,所以指针last指向节点T。而节点T是第一个也是最后一个节点,所以T指向自己。 
将节点插入空列表的函数,

struct Node *addToEmpty(struct Node *last, int data)
{
	if (last != NULL)
	return last;

	struct Node *temp =
		(struct Node*)malloc(sizeof(struct Node));

	temp -> data = data;
	last = temp;
	temp -> next = last;

	return last;
}

在列表的开头插入 
在列表的开头插入一个节点,请执行以下步骤: \

  1. 创建一个节点,例如 T。 \
  2. 使 T -> next = last -> next。 \
  3. 上一个 -> 下一个 = T。

在列表的开头插入节点的函数,

struct Node *addBegin(struct Node *last, int data)
{
if (last == NULL)
	return addToEmpty(last, data);

struct Node *temp
		= (struct Node *)malloc(sizeof(struct Node));

temp -> data = data;

temp -> next = last -> next;
last -> next = temp;

return last;
}

在列表末尾插入 
在列表末尾插入一个节点,请执行以下步骤:

  1. 创建一个节点,例如 T。
  2. 使 T -> next = last -> next; 
  3. last -> next = T。 
  4. last = T。

在列表末尾插入节点的函数

struct Node *addEnd(struct Node *last, int data)
{
if (last == NULL)
	return addToEmpty(last, data);

struct Node *temp =
		(struct Node *)malloc(sizeof(struct Node));

temp -> data = data;

temp -> next = last -> next;
last -> next = temp;
last = temp;

return last;
}

在节点之间插入 要在两个节点之间插入一个节点,请执行以下步骤:

  1. 创建一个节点,例如 T。
  2. 搜索需要在其后插入 T 的节点,例如该节点是 P。
  3. 使 T -> next = P -> next; 
  4. P -> next = T. 假设需要在节点值为10后插入12,

在List末尾插入节点的函数,

struct Node *addAfter(struct Node *last, int data, int item)
{
	if (last == NULL)
	return NULL;

	struct Node *temp, *p;
	p = last -> next;
	do
	{
		if (p ->data == item)
		{
			temp = (struct Node *)malloc(sizeof(struct Node));
			temp -> data = data;
			temp -> next = p -> next;
			p -> next = temp;
			if (p == last)
				last = temp;

			return last;
		}
		p = p -> next;
	} while (p != last -> next);

	cout << item << " not present in the list." << endl;
	return last;
}

下面是一个完整的程序,它使用上述所有方法来创建一个循环单向链表。

#include<bits/stdc++.h>
using namespace std;

struct Node
{
	int data;
	struct Node *next;
};

struct Node *addToEmpty(struct Node *last, int data)
{
	if (last != NULL)
	return last;

	struct Node *temp =
		(struct Node*)malloc(sizeof(struct Node));

	temp -> data = data;
	last = temp;

	last -> next = last;

	return last;
}

struct Node *addBegin(struct Node *last, int data)
{
	if (last == NULL)
		return addToEmpty(last, data);

	struct Node *temp =
			(struct Node *)malloc(sizeof(struct Node));

	temp -> data = data;
	temp -> next = last -> next;
	last -> next = temp;

	return last;
}

struct Node *addEnd(struct Node *last, int data)
{
	if (last == NULL)
		return addToEmpty(last, data);
	
	struct Node *temp =
		(struct Node *)malloc(sizeof(struct Node));

	temp -> data = data;
	temp -> next = last -> next;
	last -> next = temp;
	last = temp;

	return last;
}

struct Node *addAfter(struct Node *last, int data, int item)
{
	if (last == NULL)
		return NULL;

	struct Node *temp, *p;
	p = last -> next;
	do
	{
		if (p ->data == item)
		{
			temp = (struct Node *)malloc(sizeof(struct Node));
			temp -> data = data;
			temp -> next = p -> next;
			p -> next = temp;

			if (p == last)
				last = temp;
			return last;
		}
		p = p -> next;
	} while(p != last -> next);

	cout << item << " not present in the list." << endl;
	return last;

}

void traverse(struct Node *last)
{
	struct Node *p;

	if (last == NULL)
	{
		cout << "List is empty." << endl;
		return;
	}

	p = last -> next;

	do
	{
		cout << p -> data << " ";
		p = p -> next;

	}
	while(p != last->next);

}

int main()
{
	struct Node *last = NULL;

	last = addToEmpty(last, 6);
	last = addBegin(last, 4);
	last = addBegin(last, 2);
	last = addEnd(last, 8);
	last = addEnd(last, 12);
	last = addAfter(last, 10, 8);

	traverse(last);

	return 0;
}

输出:

2 4 6 8 10 12