数据结构循环链表之排序插入 | 第五套

153 阅读3分钟

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

难度级别: 菜鸟 
编写一个 C 函数,在已排序的循环链表 (CLL) 中插入一个新值。例如,如果输入 CLL 如下。

插入8后,上面的CLL要改成下面的.jpg

算法:  
为新插入的节点分配内存,将数据放入新分配的节点。让指向新节点的指针为 new_node。内存分配后,以下是需要处理的三种情况。

1)链表为空:
a) 因为 new_node 是 CLL 中唯一的节点,所以做一个自循环。
new_node->next = new_node;
b) 改变头指针指向新节点。
*head_ref = new_node;

2)将在头节点之前插入新节点:
(a) 使用循环找出最后一个节点。
while(current->next != *head_ref) current = current->next;
(b) 更改最后一个节点的下一个。
current->next = new_node;
(c) 将新节点的 next 更改为指向头部。
new_node->next = *head_ref;
(d) 改变头指针指向新节点。
*head_ref = new_node;

3)新节点将被插入到头部之后的某处:
(a) 定位要在其后插入新节点的节点。
while ( current->next!= *head_ref && current->next->data data) { current = current->next; }
(b) 下一个new_node的制作如接下来所定位的指针的
new_node->next = current->next;
(c) 改变定位的指针
current->next = new_node;

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

/* 节点结构 */
class Node
{
	public:
	int data;
	Node *next;
};

/* 函数以排序方式在列表中插入一个 new_node。 请注意,
此函数需要一个指向头节点的指针,因为这可以修改输入链表的头 */
void sortedInsert(Node** head_ref, Node* new_node)
{
	Node* current = *head_ref;
	
	// 上述算法的案例1
	if (current == NULL)
	{
		new_node->next = new_node;
		*head_ref = new_node;
	}
	
	// 上述算法的案例2
	else if (current->data >= new_node->data)
	{
		/* 如果值小于 head 的值,那么我们需要更改最后一个节点的 next */
		while(current->next != *head_ref)
			current = current->next;
		current->next = new_node;
		new_node->next = *head_ref;
		*head_ref = new_node;
	}
	
	//上述算法的情况3
	else
	{
		/* 定位插入点之前的节点 */
		while (current->next!= *head_ref &&
			current->next->data < new_node->data)
		current = current->next;
	
		new_node->next = current->next;
		current->next = new_node;
	}
}

/* 打印给定链表中节点的函数 */
void printList(Node *start)
{
	Node *temp;
	
	if(start != NULL)
	{
		temp = start;
		do {
		cout<<temp->data<<" ";
		temp = temp->next;
		} while(temp != start);
	}
}

/* 驱动代码 */
int main()
{
	int arr[] = {12, 56, 2, 11, 1, 90};
	int list_size, i;
	
	/* 从空链表开始 */
	Node *start = NULL;
	Node *temp;
	
	/* 从数组 arr[] 创建链表。
        创建的链表将是 1->2->11->12->56->90 */
	for (i = 0; i< 6; i++)
	{
		temp = new Node();
		temp->data = arr[i];
		sortedInsert(&start, temp);
	}
	
	printList(start);
	
	return 0;
}

输出:  

1 2 11 12 56 90

时间复杂度:  O(n),其中 n 是给定链表中的节点数。

可以优化上述算法/代码的情况2。为了实现建议的更改,我们需要修改案例 2 以遵循。

else if (current->data >= new_node->data)
{
swap(&(current->data), &(new_node->data));

new_node->next = (*head_ref)->next;
(*head_ref)->next = new_node;
}

🥇 往期优质文章

数据结构循环链表之介绍和应用 | 第一套
数据结构单向链表和循环链表的插入 | 第二套
数据结构循环链表之循环链表遍历 | 第三套
数据结构循环链表之将一个循环链表分成两半 | 第四套

📣尾注: 想要获取更多数据结构相关的知识,你可以关注我:海拥,我希望你觉得这篇文章有帮助。

如果你看到这里,感谢你的阅读 :)

💌 欢迎大家在评论区提出意见和建议!💌

如果你真的从这篇文章中学到了一些新东西,喜欢它,收藏它并与你的小伙伴分享。🤗最后,不要忘了❤或📑支持一下哦。