无头链表的两种实现方法

无头链表的两种实现方法

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");
}

总结

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值