/*
Create_Empty_LinkedListWithHead:创建一条空链表
返回值:
返回头节点的地址
*/
struct Head *Create_Empty_LinkedListWithHead()
{
// 创建头节点
struct Head *head = malloc(sizeof(*head));
// 按照空链表的特性赋值
head->first = head->last = NULL;
head->num = 0;
return head;
}
bool Is_Head(struct Head *head)
{
if (head->num == 0 && head->first == NULL && head->last == NULL)
return true;
return false;
}
struct Head *create_Head_int()
{
// 创建头节点
struct Head *head = malloc(sizeof(*head));
head->first = head->last = NULL; // 初始化头节点的first和last指针为NULL
head->num = 0; // 初始化链表节点数量为0
int x;
printf("输入整型数据:");
scanf("%d", &x); // 输入第一个整数数据
while (x != 0)
{
// 创建新节点并赋值
struct Node *p = malloc(sizeof(*p));
p->data = x;
p->next = NULL;
if (head->first == NULL)
{
// 如果链表为空,将新节点设为头节点同时也是尾节点
head->first = p;
head->last = p;
}
else
{
// 将新节点连接到链表尾部
head->last->next = p;
head->last = p;
}
head->num++; // 更新链表节点数量
scanf("%d", &x); // 继续输入下一个整数数据
}
return head; // 返回创建的链表头节点指针
}
// 打印链表
void Printf_Head(struct Head *head)
{
if (head == NULL)
return;
struct Node *p = head->first; // 当前节点指针,指向链表的第一个节点
if (Is_Head(head)) // 判断是否为头节点
printf("num=%d\n", head->num); // 如果是头节点,只打印节点数量
else
{
// 如果不是头节点,打印节点数量/头节点地址和尾节点地址
printf("num=%d head->first=%d head->last=%d\n", head->num, head->first, head->last);
}
while (p)
{
printf("%d->", p->data); // 打印当前节点的数据值
p = p->next; // 移动到下一个节点
printf("\n"); // 换行
}
}
/*
Insert_node_y:在head指向的链表中,查找值为x的元素,在其前面增加一个值为y的元素
若有多个值为x的元素则增加在第一个前面
若没有则增加在最后
@head:头节点指针
@x:
@y
返回值:
考虑看看是否需要返回值
可要 : 将头节点地址返回
不要 :也行,外面也可以拿到该头节点的地址
在该函数中变得只是头节点内部的成员
*/
struct Head *Insert_node_y(struct Head *head, Elemtype x, Elemtype y)
{
if (head == NULL)
return head;
// 创建新数据节点并赋值
struct Node *pnew = malloc(sizeof(*pnew)); // 分配内存空间用于新节点
pnew->data = y; // 设置新节点的数据为y
pnew->next = NULL; // 将新节点的下一个节点指针初始化为NULL
// 查找
struct Node *p = head->first; // 遍历指针,从链表的第一个节点开始遍历
struct Node *pre = NULL; // 前驱指针,用于记录当前节点的前一个节点
while (p)
{
if (p->data == x) // 找到值为x的节点
break;
pre = p; // 更新前驱指针为当前节点
p = p->next; // 移动遍历指针到下一个节点
}
// 增加
if (p) // 如果找到了节点值为x的节点
{
if (p == head->first) // 在首节点前面增加
{
pnew->next = p; // 新节点的下一个节点指向原来的首节点
head->first = pnew; // 更新首节点为新节点
}
else // 在中间节点或尾节点前面增加
{
pnew->next = p; // 新节点的下一个节点指向当前节点
pre->next = pnew; // 前驱节点的下一个节点指向新节点
}
}
else // 如果未找到节点值为x的节点
{
// 空表
if (Is_Empty_LinkedListWithHead(head)) // 判断链表是否为空表
{
head->first = head->last = pnew; // 首尾节点都指向新节点
}
else // 非空表
{
head->last->next = pnew; // 将新节点链接到尾节点的后面
head->last = pnew; // 更新尾节点为新节点
}
}
head->num++; // 链表节点数量加1
return head;
}
/*
Delete_node_all_x:在head指向的链表中,查找值为x的元素,将其删除
若有多个值为x的元素则删除所有
若没有则不删除
@head:头节点指针
@x:
返回值:
无
*/
// 删除数据节点
void Delete_node_x(struct Head *head, Elemtype x)
{
if (head == NULL) // 如果头节点为空,直接返回
return;
struct Node *p = head->first; // 当前节点指针,指向链表的第一个节点
struct Node *pre = NULL; // 前驱节点指针,初始化为NULL
// 查找要删除的节点
while (p)
{
if (p->data == x) // 如果当前节点的数据等于要删除的数据x
break; // 跳出循环,找到了要删除的节点
pre = p; // 更新前驱节点指针
p = p->next; // 移动到下一个节点
}
// 找到要删除的节点,执行删除操作
if (p)
{
if (p == head->first)
{ // 如果要删除的节点是首节点
if (head->first == head->last)
{ // 如果链表中只有一个节点而且还要被删除
head->last = NULL;
}
head->first = p->next; // 更新头节点指针,指向下一个节点
p->next = NULL;
free(p); // 释放删除节点的内存
p = NULL;
}
else if (p == head->last)
{ // 如果要删除的节点是尾节点
head->last = pre; // 更新尾节点指针,指向前驱节点
pre->next = NULL;
free(p); // 释放删除节点的内存
p = NULL;
}
else
{ // 如果要删除的节点是中间节点
pre->next = p->next; // 前驱节点指向后继节点
p->next = NULL;
free(p); // 释放删除节点的内存
p = NULL;
}
head->num--; // 更新链表节点数量
}
}
void Delete_node_all_x_2(struct Head *head, Elemtype x)
{
if (head == NULL)
return;
struct Node *p = head->first; // 遍历指针
struct Node *pre = NULL;
while (p)
{
// 查找
while (p)
{
if (p->data == x)
break;
pre = p;
p = p->next;
}
// 找到执行删除操作
if (p)
{
// 执行删除操作
if (p == head->first) // 首节点
{
if (head->first == head->last) // 链表中只有一个节点而且还要被删除
{
head->last = NULL;
}
head->first = p->next;
p->next = NULL;
free(p);
p = head->first;
}
else if (p == head->last) // 尾节点
{
head->last = pre;
pre->next = NULL;
free(p);
p = NULL;
}
else // 中间节点
{
pre->next = p->next;
p->next = NULL;
free(p);
p = pre->next;
}
head->num--;
}
}
}
单链表有头节点
最新推荐文章于 2024-07-15 12:54:34 发布