无头链表的两种实现方法

Posted 乌云中的闪电

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无头链表的两种实现方法相关的知识,希望对你有一定的参考价值。

无头链表的两种实现方法

1.利用二级指针实现

思路:创建一个指针list = NULL;该指针永远指向新的节点。

1.1创建结构体

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

1.2初始化新的节点

struct Node* CreateNode(int data)
{
	struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
	NewNode->next = NULL;
	NewNode->Data = data;
	return NewNode;
}

1.3插入

void Insert_By_Head(struct Node** list, int data)
{
	struct Node* NewNode = CreateNode(data);
	NewNode->next = (*list);
	(*list) = NewNode;   
}

此处形参必须为二级指针,原因:由于函数不会改变实参大小,若传入的实参是struct Node类型的一级指针,在函数中进行赋值运算,但实参list并不会改变,只有将list的地址(struct Node** list)传入函数,才能改变list指针。

补充:尾插法:

void Insert_By_Tail(struct Node* list, int data)
{
	struct Node* pMove = list;
	struct Node* NewNode = CreateNode(data);
	while (pMove->next)
		pMove = (pMove)->next;
	NewNode->next = NULL;
	(pMove->next) = NewNode;
}

1.4打印

void Print_Node(struct Node* list)
{
	struct Node* pMove = list;
	while (pMove)
	{
		printf("%d, ", pMove->Data);
		pMove = pMove->next;
	}
	printf("\\n");
}

个人感觉二级指针比较难以理解,需要花时间思考一下

2.用结构体描述无头链表

用结构体封装的方式去描述一种结构

2.1创建节点结构体

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

2.2创建链表

struct List
{
	struct Node* FrontNode;
	struct Node* TailNode;
	int size;
};

这里的FrontNode和TailNode分别代表链表的第一位与最后一位,size为链表的节点数,每次调用插入函数时都会进行一次++操作。

2.3创建节点

struct Node* CreateNode(int data)
{
	struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
	NewNode->Data = data;
	NewNode->next = NULL;
}

2.4初始化链表

struct List* CreateList()
{
	struct List* list = (struct List*)malloc(sizeof(struct List));
	list->FrontNode = list->TailNode = NULL;
	list->size = 0;
	return list;
}

2.5头插与尾插

头插:

void Insert_By_Head(struct List* list, int data)
{
	struct Node* NewNode = CreateNode(data);
	if (!list->size)
	{
		list->TailNode = NewNode;
		list->FrontNode = NewNode;
	}
	else
	{
		NewNode->next = list->FrontNode;
		list->FrontNode = NewNode;
	}
	list->size++;
}

尾插:

void Insert_By_Tail(struct List* list, int data)
{
	struct Node* NewNode = CreateNode(data);
	if (!list->size)
	{
		list->FrontNode = NewNode;
		list->TailNode = NewNode;
	}
	else
	{
		list->TailNode->next = NewNode;
		list->TailNode = NewNode;
	}
	list->size++;
}

其中,我们分别把list->FrontNode = NewNode;list->TailNode = NewNode;两条语句从条件语句中抽象出来。于是,经过优化,最后的代码如下:

头插:

void Insert_By_Head(struct List* list, int data)
{
	struct Node* NewNode = CreateNode(data);
	if (!list->size)
		list->TailNode = NewNode;
	else
		NewNode->next = list->FrontNode;
	list->FrontNode = NewNode;
	list->size++;
}

尾插:

void Insert_By_Tail(struct List* list, int data)
{
	struct Node* NewNode = CreateNode(data);
	if (!list->size)
		list->FrontNode = NewNode;
	else
		list->TailNode->next = NewNode;
	list->TailNode = NewNode;
	list->size++;
}

这是一对非常对称的代码,不是吗?

2.6打印

void PrintList(struct List* list)
{
	struct Node* pMove = list->FrontNode;
	while (pMove)
	{
		printf("%d\\t", pMove->Data);
		pMove = pMove->next;
	}
	printf("\\n");
}

总结

个人感觉第二种方法有一点面向对象的思想,而且比第一种方法更加易于理解。其中还有很多功能没有实现,如:指定位置插入,三种删除法等。你可以自己动手尝试一下实现上述功能~

以上是关于无头链表的两种实现方法的主要内容,如果未能解决你的问题,请参考以下文章

无头链表的两种实现方法

无头链表的两种实现方法

数据结构《二》链表的实现

[ 数据结构--C语言 ] 无头单向非循环链表的简单实现(单链表)

复杂链表的复制(递归的两种实现方式)

数据结构69:链表逆置,链表反转,链表翻转