数据结构
链表
题目预览:
1.设计一个算法删除单链表L(有头结点)中的一个最小值结点。

/**************************************************************************************
*
*
* file name: demo_3.c
* author : Tongyaqi1110@163.com
* date : 2024/04/22
* function : 设计一个算法,删除单链表最小值结点
* note : None
*
* CopyRight (c) 2024 Tongyaqi1110@163.com All Right Reserved
*************************************************************************************/
#include <stdio.h>
/************************************************
*
* func name : DeleteMin
* function : 插入一个元素后保持该顺序表仍然递增有序排列
*
* argument : @LList_t *Head
*
* retval : DataType_t
* note : None
* author : tongyaqi1110@163.com
* data : 2024/04/22
*
* ************************************************/
// 指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改
#include <stdlib.h>
#include <stdbool.h>
typedef int DataType_t;
// 构造链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct LinkedList
{
DataType_t data; // 结点的数据域
struct LinkedList *next; // 结点的指针域
} LList_t;
// 创建一个空链表,空链表应该有一个头结点,对链表进行初始化
LList_t *LList_Create(void)
{
// 1.创建一个头结点并对头结点申请内存
LList_t *Head = (LList_t *)calloc(1, sizeof(LList_t));
if (NULL == Head)
{
perror("Calloc memory for Head is Failed");
exit(-1);
}
// 2.对头结点进行初始化,头结点是不存储有效内容的!!!
Head->next = NULL;
// 3.把头结点的地址返回即可
return Head;
}
// 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
LList_t *LList_NewNode(DataType_t data)
{
// 1.创建一个新结点并对新结点申请内存
LList_t *New = (LList_t *)calloc(1, sizeof(LList_t));
if (NULL == New)
{
perror("Calloc memory for NewNode is Failed");
return NULL;
}
// 2.对新结点的数据域和指针域进行初始化
New->data = data;
New->next = NULL;
return New;
}
// 头插
bool LList_HeadInsert(LList_t *Head, DataType_t data)
{
// 1.创建新的结点,并对新结点进行初始化
LList_t *New = LList_NewNode(data);
if (NULL == New)
{
printf("can not insert new node\n");
return false;
}
// 2.判断链表是否为空,如果为空,则直接插入即可
if (NULL == Head->next)
{
Head->next = New;
return true;
}
// 3.如果链表为非空,则把新结点插入到链表的头部
New->next = Head->next;
Head->next = New;
return true;
}
// 先初始化三个指针变量
LList_t *q = NULL;
LList_t *h = NULL;
LList_t *p = NULL;
bool DeleteMin(LList_t *Head)
{
//判空
if (NULL == Head->next)
{
return false;
}
//三个指针都指向首结点
q = Head->next;
h = Head->next;
p = Head;
//遍历找到最小值结点
//注意,循环中比较后h和q指向同一个位置
do
{
if (h->data < q->next->data)
{
q = q->next;
}
else
{
h = q->next;
q = q->next;
}
} while (q->next);
// 遍历找出h的前驱
while (p->next != h)
{
p = p->next;
}
//已经找到了最小节点h的前驱,前驱指向最小值结点的后面
p->next = h->next;
free(h);
}
// 遍历
void LList_Print(LList_t *Head)
{
// 对链表的头文件的地址进行备份
LList_t *Phead = Head;
// 首结点
while (Phead->next)
{
// 把头的直接后继作为新的头结点
Phead = Phead->next;
// 输出头结点的直接后继的数据域
printf("%d ", Phead->data);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
LList_t *Head = LList_Create();
LList_HeadInsert(Head, 1);
LList_HeadInsert(Head, 5);
LList_HeadInsert(Head, 7);
LList_HeadInsert(Head, 4);
LList_HeadInsert(Head, 3);
LList_HeadInsert(Head, 6);
LList_Print(Head);
DeleteMin(Head);
LList_Print(Head);
return 0;
}