单链表有头节点


/*
    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--;
        }
    }
}


  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值