#ifndef __DOUBLE_H__
#define __DOUBLE_H__
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef int Elemtype;
struct Node
{
Elemtype data; // 数据域
struct Node *prev; // 指向上一个节点
struct Node *next; // 指向下一个节点
};
struct Head
{
struct Node *first;
struct Node *last;
int num;
};
extern struct Head *Create_Empty_DoubleLinkedListWithHead();
extern struct Head *Create_Empty_DoubleLinkedListWithHead_1();
extern struct Head *Create_Input_DoubleLinkedListWithHead();
extern bool Is_Head(struct Head *head);
extern void Print_DoubleLinkedListWithHead(struct Head *head);
extern struct Head *Insert_node_y(struct Head *head, Elemtype x, Elemtype y);
extern struct Head *Insert_node_y_2(struct Head *head, Elemtype x, Elemtype y);
extern void Delete_all_x(struct Head *head, Elemtype x);
extern void Delete_all_x_2(struct Head *head, Elemtype x);
#endif
#include "double.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
Create_Empty_DoubleLinkedListWithHead:创建一条带头结点的空双向链表
返回值:
返回头节点地址
*/
struct Head *Create_Empty_DoubleLinkedListWithHead()
{
struct Head *p = malloc(sizeof(*p));
if (p == NULL)
return NULL;
p->first = malloc(sizeof(*p));
if (p->first == NULL)
{
free(p);
return NULL;
}
p->first->prev = p->first->next = NULL;
p->num = 0;
return p;
}
struct Head *Create_Empty_DoubleLinkedListWithHead_1()
{
struct Head *head = malloc(sizeof(*head));
head->first = head->last = NULL;
head->num = 0;
return head;
}
/*
从键盘上输入数据创建一条整型数据双向链表
Create_Input_DoubleLinkedListWithHead:创建一条带头结点的空双向链表
返回值:
返回头节点地址
*/
struct Head *Create_Input_DoubleLinkedListWithHead()
{
// 创建头结点
struct Head *head = malloc(sizeof(*head));
if (head == NULL)
return NULL;
head->first = head->last = NULL; // 初始化链表的第一个和最后一个节点为NULL
head->num = 0; // 初始化链表节点数量为0
int x;
printf("请输入整型数据:");
scanf("%d", &x);
// 读取用户输入的整型数据,直到输入为0为止
while (x != 0)
{
// 创建新的节点
struct Node *p = malloc(sizeof(*p));
if (p == NULL)
return NULL;
p->data = x; // 将用户输入的数据存储到节点中
p->next = NULL; // 初始化节点的下一个节点指针为NULL
// 如果链表为空,则将新节点设置为第一个节点,并更新最后一个节点指针
if (head->first == NULL)
{
head->first = p;
head->last = p;
p->prev = NULL; // 第一个节点的前一个节点指针为NULL
}
else
{
// 如果链表不为空,则将新节点连接到链表的最后一个节点,并更新最后一个节点指针
head->last->next = p;
p->prev = head->last;
head->last = p;
}
p->next = NULL; // 更新新节点的下一个节点指针为NULL
head->num++; // 更新链表节点数量
scanf("%d", &x); // 继续读取用户输入的整型数据
}
return head; // 返回创建好的带头结点的双向链表
}
// 判空
bool Is_Head(struct Head *head)
{
if (head->num == 0 && head->first == NULL && head->last == NULL)
return true;
return false;
}
/*
Print_DoubleLinkedListWithHead:输出一条带头结点的整型双向链表
@head:要输出的链表的头节点指针
返回值:
无
*/
void Print_DoubleLinkedListWithHead(struct Head *head)
{
if (head == NULL)
return;
struct Node *p = head->first;
printf("=========================\n");
if (Is_Empty_LinkedListWithHead(head))
{
printf("num = %d\n", head->num);
}
else
{
printf("num = %d, first->data = %d, last->data = %d\n", head->num,
head->first->data, head->last->data);
}
printf("Next:");
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
printf("Prev:");
p = head->last;
while (p)
{
printf("%d ", p->data);
p = p->prev;
}
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;
// 创造新节点保存y
struct Node *pnew = malloc(sizeof(*pnew));
pnew->data = y;
pnew->next = NULL;
pnew->prev = NULL;
// 查找
struct Node *p = head->first; // 遍历指针,从链表的第一个节点开始遍历
struct Node *pre = NULL; // 前驱指针,用于记录当前节点的前一个节点
while (p)
{
if (p->data == x)
break;
pre = p;
p = p->next;
}
// 增加
if (p) // 找到x
{
if (p == head->first) // x在首节点
{
pnew->next = p;
head->first = pnew;
p->prev = pnew;
}
else // x不在首节点
{
pnew->next = p;
pre->next = pnew;
p->prev = pnew;
pnew->prev = pre;
}
}
else // 未找到
{
if (Is_Head(head))
head->first = head->last = pnew; // 首尾节点都指向新节点
else
{
head->last->next = pnew;
pnew->prev = head->last;
head->last = pnew;
}
}
head->num++;
return head;
}
struct Head *Insert_node_y_2(struct Head *head, Elemtype x, Elemtype y)
{
if (head == NULL)
return head;
// 创建新节点保存y
struct Node *pnew = malloc(sizeof(*pnew)); // 创建新节点并分配内存空间
pnew->data = y; // 设置新节点的数据为y
pnew->next = NULL; // 设置新节点的下一个节点指针为NULL,表示当前节点为链表末尾节点
pnew->prev = NULL; // 设置新节点的前一个节点指针为NULL,表示当前节点为链表首节点
// 遍历链表查找值为x的节点
struct Node *p = head->first; // 使用指针p遍历链表,从首节点开始
while (p)
{
if (p->data == x) // 如果当前节点的数据等于x,则表示找到了目标节点
break;
p = p->next; // 否则继续向后遍历下一个节点
}
// 插入新节点
if (p) // 如果找到了值为x的节点
{
if (p->prev) // 如果x节点不是首节点
{
p->prev->next = pnew; // 将新节点插入到x节点之前
pnew->prev = p->prev;
}
else // 如果x节点是首节点
{
head->first = pnew; // 更新首节点为新节点
}
pnew->next = p; // 更新新节点的下一个节点为x节点
p->prev = pnew; // 更新x节点的前一个节点为新节点
}
else // 如果未找到值为x的节点
{
if (head->last) // 如果链表非空
{
head->last->next = pnew; // 将新节点插入到链表末尾
pnew->prev = head->last;
head->last = pnew; // 更新链表末尾为新节点
}
else // 如果链表为空
{
head->first = pnew; // 更新首节点为新节点
head->last = pnew; // 更新末尾节点为新节点
}
}
head->num++; // 增加链表节点数量
return head; //
}
/*
Delete_all_x:在head指向的带头结点的双向链表中,找到值为x的节点,将其删除
如果有多个值为x的节点则全部删除
如果没有则不删除
@head:
@x:
@y:
返回值:
无
*/
void Delete_all_x(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;
if (head->first != NULL)
{
head->first->prev = NULL;
}
p->next = NULL;
free(p);
p = head->first;
}
else if (p == head->last) // 如果p在尾节点
{
head->last = pre;
pre->next = NULL;
p->prev = NULL;
free(p);
p = NULL;
}
else
{
pre->next = p->next;
p->next->prev = pre;
p->next = NULL;
p->prev = NULL;
free(p);
p = pre->next;
}
head->num--;
}
printf("-------\n");
}
}
void Delete_all_x_2(struct Head *head, Elemtype x)
{
if (head == NULL)
{
return; // 如果链表为空,直接返回
}
struct Node *p = head->first; // 使用指针p遍历链表,从首节点开始
struct Node *next = NULL; // 用于暂存下一个节点
struct Node *pre = NULL; // 用于记录当前节点的前一个节点
while (p != NULL)
{ // 循环查找和删除值为x的节点
if (p->data == x)
{ // 如果当前节点的数据等于x,则删除该节点
next = p->next; // 先保存下一个节点的指针
if (p == head->first)
{ // 如果是首节点
head->first = next;
if (next != NULL)
{
next->prev = NULL; // 更新新的首节点的前一个节点指针为NULL
}
else
{ // 如果只有一个节点
head->last = NULL;
}
}
else
{
pre->next = p->next; // 将前一个节点的next指针指向下一个节点
if (next != NULL)
{
next->prev = pre; // 更新下一个节点的prev指针为前一个节点
}
else
{ // 如果是尾节点
head->last = pre; // 更新尾节点为前一个节点
}
}
free(p); // 释放当前节点的内存空间
p = next; // 移动到下一个节点
head->num--; // 减少链表节点数量的计数器
}
else
{
pre = p; // 记录当前节点为前一个节点
p = p->next; // 移动到下一个节点
}
}
}