无头链表的两种实现方法
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");
}
总结
个人感觉第二种方法有一点面向对象的思想,而且比第一种方法更加易于理解。其中还有很多功能没有实现,如:指定位置插入,三种删除法等。你可以自己动手尝试一下实现上述功能~
以上是关于无头链表的两种实现方法的主要内容,如果未能解决你的问题,请参考以下文章