一、什么是带表头的单链表
在单链表中,因为头结点没有直接前驱结点,所以在进行插入和删除操作时,需要特殊的处理。为了简化操作,在单链表之前添加一个空的头结点,实际的元素结点从第二个结点开始,由此称为带表头的单链表。
二、各个功能实现
(一)初始化
带表头单链表的初始化是指:构造一个仅带有一个表头结点的空单链表。
1、算法步骤
(1)为表头结点申请动态空间
(2)设置头结点的直接后继结点,即第一个数据结点为
N
U
L
L
NULL
NULL,即构造了一个空链表
(3)链表长度置
0
0
0
2、算法代码
// 带表头单链表的初始化
Status Init(HeaderSingleList* list)
{
list->head = malloc(sizeof(Node));
if (!list->head)
{
return Error;
}
list->head->link = NULL;
list->n = 0;
return OK;
}
(二)插入
带表头单链表的每个节点都有直接前驱结点,所以在进行插入操作时无需特殊化处理,简化了插入操作。
1、算法步骤
(1)判断所要插入的位置是否越界
(2)为新节点
n
e
w
N
o
d
e
newNode
newNode 申请动态空间,并给结点数据段赋值
(3)找到要插入位置的前一个结点
b
e
f
o
r
e
N
o
d
e
beforeNode
beforeNode
(4)将
n
e
w
N
o
d
e
newNode
newNode 的后继结点赋值为
b
e
f
o
r
e
N
o
d
e
−
>
l
i
n
k
beforeNode->link
beforeNode−>link ,
b
e
f
o
r
e
N
o
d
e
beforeNode
beforeNode 结点的后继结点赋值为
n
e
w
N
o
d
e
newNode
newNode
(5)表长++
2、算法代码
// 带表头单链表的插入
Status Insert(HeaderSingleList* list, int i, int value)
{
// 如果插入的位置越界,则返回错误
if (i < -1 || i > list->n - 1)
{
return Error;
}
Node* newNode = malloc(sizeof(Node));
Node* before = list->head;
for (int j = 0; j <= i; j++)
{
before = before->link;
}
newNode->value = value;
newNode->link = before->link;
before->link = newNode;
list->n++;
}
(三)删除
带表头单链表的每个节点都有直接前驱结点,所以在进行删除操作时无需特殊化处理,简化了删除操作。
1、算法步骤
(1)替换link
(2)释放删除的空间
2、算法代码
void Delete(HeaderSingleList* list, int i)
{
if (list->n == 0)
{
return Error;
}
if (i < 0 || i >list->n - 1)
{
return Error;
}
Node* beforeNode = list->head;
Node* deleteNode = NULL;
// 找到要删除节点的前一个结点
for (int j = 0; j < i; j++)
{
beforeNode = beforeNode->link;
}
// 此时的 beforNode 是所要删除结点的前一个结点
deleteNode = beforeNode->link; // 要删除的结点deleteNode 为 beforNode 的下一个结点
beforeNode->link = deleteNode->link; // 将要删除结点的前一个结点的 link 指向 要删除结点的下一个结点
free(deleteNode);
printf("调用了 Delete(\%d) 函数\n", i);
list->n--;
}
三、全部代码
#include <stdio.h>
#define ElemType int
#define Error 0
#define OK 1
#define Overflow 2
#define Underflow 3
#define NotPresent 4
#define Duplicate 5
typedef int Status;
// 结点结构体
typedef struct node
{
ElemType value;
struct node* link;
}Node;
// 单链表结构体
typedef struct headerSingleList
{
Node* head;
int n;
}HeaderSingleList;
// 带表头单链表的初始化
Status Init(HeaderSingleList* list)
{
list->head = malloc(sizeof(Node));
if (!list->head)
{
return Error;
}
list->head->link = NULL;
list->n = 0;
return OK;
}
// 带表头单链表的插入
Status Insert(HeaderSingleList* list, int i, int value)
{
// 如果插入的位置越界,则返回错误
if (i < -1 || i > list->n - 1)
{
return Error;
}
Node* newNode = malloc(sizeof(Node));
Node* before = list->head;
for (int j = 0; j <= i; j++)
{
before = before->link;
}
newNode->value = value;
newNode->link = before->link;
before->link = newNode;
list->n++;
}
void Delete(HeaderSingleList* list, int i)
{
if (list->n == 0)
{
return Error;
}
if (i < 0 || i >list->n - 1)
{
return Error;
}
Node* beforeNode = list->head;
Node* deleteNode = NULL;
// 找到要删除节点的前一个结点
for (int j = 0; j < i; j++)
{
beforeNode = beforeNode->link;
}
// 此时的 beforNode 是所要删除结点的前一个结点
deleteNode = beforeNode->link; // 要删除的结点deleteNode 为 beforNode 的下一个结点
beforeNode->link = deleteNode->link; // 将要删除结点的前一个结点的 link 指向 要删除结点的下一个结点
free(deleteNode);
printf("调用了 Delete(\%d) 函数\n", i);
list->n--;
}
void GetValue(HeaderSingleList* list, int i, int* value)
{
printf("调用了 GetValue() 函数\n");
Node* node = list->head;
for (int j = 0; j < i; j++)
{
node = node->link;
}
*value = node->value;
}
// 单链表的销毁
void Destory(HeaderSingleList* list)
{
printf("调用了 Destory() 函数\n");
Node* node = list->head;
while (list->head)
{
node = node->link;
free(list->head);
list->head = node;
}
}
void PrintAllValue(HeaderSingleList* list)
{
if (list->n == 0) {
return Error;
}
Node* node = list->head->link;
while (node)
{
printf("%d -> ", node->value);
node = node->link;
}
printf("NULL\n\n");
}
int main()
{
HeaderSingleList* list = malloc(sizeof(HeaderSingleList));
Init(list);
Insert(list, -1, 4);
Insert(list, -1, 3);
Insert(list, -1, 2);
Insert(list, -1, 1);
Insert(list, -1, 0);
PrintAllValue(list);
Delete(list, 1);
PrintAllValue(list);
Destory(list);
PrintAllValue(list);
}