有头单向链表的函数操作(详细版)

 【1】代码展示

#include <stdio.h>
#include <stdlib.h>
typedef char datatype; // 重定义字符类型
typedef struct node
{
    datatype data;     // 数据用来存数据
    struct node *next; // 指针域用来存下一个节点的地址
} Node_t, *Node_p;     // 重定义结构体数据类型,和结构体指针类型
/*创建一个空的单向链表*/
Node_p Create()
{
    Node_p p = (Node_p)malloc(sizeof(Node_t)); // 开辟一个节点大小的堆区空间
    if (NULL == p)                             // 开辟失败
    {
        printf("malloc lost");
        return NULL;
    }
    p->next = NULL; // 初始化头节点指针域
    return p;       // 开辟成功,返回
}

/*计算链表的长度*/
int Length(Node_p p)
{
    int len = 0;            // 定义一个变量来表示长度,并赋初始值为0
    while (p->next != NULL) // 当指针域不等于NULL就说明没到最后一个节点
    {
        p = p->next; // 指针向下一个节点移动
        len++;       // 长度加加
    }
    return len; // 返回长度值
}

/*向项链表中插入数据*/
void Insert(Node_p p, int post, int data)
// p 保存链表的头指针   post 要插入的位置   data  要插入的数据
{
    // 容错判断
    if (post < 0 || post > Length(p)) // 插入位置小于0或大于链表长度
    {
        printf("post error");
    }
    Node_p p_new = NULL;           // 创建一个指针,置空备用,用来存放要插入的新数据
    for (int i = 0; i < post; i++) // for循环遍历到要查如位置前的那该个节点
        p = p->next;
    p_new = (Node_p)malloc(sizeof(Node_t)); // 开辟一个节点大小堆区空间存放新数据
    if (NULL == p_new)
    {
        printf("malloc lost");
    }
    p_new->data = data; // 在数据域存放要查入的数据
    p_new->next = NULL; // 初始化为NULL;
    // 链接新节点时,要先连后面,再连前面(否则,先连前面后面的地址就找不到了)
    p_new->next = p->next; // 让新节点链接到要插入的位置节点上
    p->next = p_new;       // 让要插入位置前的那个节点连接到新的节点上
}

/*修改链表的内容*/
void Modify(Node_p p, int post, int data)
// p 保存链表的头指针  post  要修改的数据位置  data   要修改成的数据
{
    // 容错判断
    if (post < 0 || post > Length(p))
    {
        printf("error\n");
    }
    for (int i = 0; i < post; i++) // for循环遍历到要插入位置前的那该个节点
        p = p->next;
    Node_p mod = p->next; // 定义一个指针指向要插入位置的节点
    mod->data = data;     // 修改要修改的值
}

/*删除链表的内容*/
void Delete(Node_p p, int post)
// p 保存链表的头指针  post  要删除的数据位置
{
    // 容错判断
    if (post < 0 || post > Length(p))
    {
        printf("delete error\n");
    }
    for (int i = 0; i < post; i++)
        p = p->next;
    Node_p p_del; // 定义一个指针指向要删除的节点
    p_del = p->next;
    p->next = p_del->next; // 让被删除的节点前的那个节点链接到被删除的那个节点后的节点
    free(p_del);           // 释放被删除的那个节点
    p_del = NULL;          // 将指向被删除的那个节点的指针置空
}

/*查找链表中的内容*/
int Search(Node_p p, int post)
// p 保存链表的头指针  post  要查询的数据位置
{
    // 容错判断
    if (post < 0 || post > Length(p))
    {
        printf("error\n");
        return -1;
    }
    for (int i = 0; i <= post; i++) // for 循环遍历到要查询的节点位置
        p = p->next;
    return p->data; // 返回查询的节点数据域中的内容
}

/*清空链表的内容*/
void Clear(Node_p p)
{
    Node_p p_del = NULL;  // 定义一个指针置空待用,永远指向要清空的节点
    p_del = p->next;      // 头节点不需要清除,所以先指向头节点下一个节点
    while (p_del != NULL) // 当p_del所指向的节点不为空时,进入循环
    {
        p->next = p_del->next; // 让头节点跨过要清除的节点,链接下一个节点
        free(p_del);           // 把这个要清空的节点free删除掉
        p_del = p->next;       // 然后让p_del 指向下一个要清空的节点
    }
}

/*删除指定数据的节点*/
void DeleteSame(Node_p p, int data)
{
    Node_p q = p->next; // 头节点数据域无效,所以要先移动到下一个节点
    while (q != NULL)   // 只要节点不是NULL,就进入循环
    {
        if (q->data == data) // 如果该节点的数据域内容和指定数据相等
        {
            p->next = q->next; // 越过该节点(数据域和指定数据数据相等),链接下一个节点
            free(q);           // 把该节点free释放掉
            q = p->next;       // 让该指针指向下一节点,以便下一次判断
        }
        else // 如果该节点的数据域内容和指定数据不相等
        {
            p = p->next; // 两个指针都往后移动,以便进行下一次比较和删除
            q = q->next;
        }
    }
}

/*转置链表*/
void Reserve(Node_p p)
{
    Node_p q = NULL; // 创建两个指针置空待用
    Node_p t = NULL;
    q = p->next;      // 让q指针指向头节点的下一个节点
    p->next = NULL;   // 让头节点的指针域置空,和后面的链表断开
    while (q != NULL) // q不等于NULL就一直循环     整个操作就只是对q指针进行操作,t指针只负责保存下一个节点
    {
        t = q->next; // 让t等于q的下一个节点,保存一下q的下一个节点
        // 把q节点用头插法插入到 头节点和与头节点相连的那个节点之间
        q->next = p->next;
        p->next = q;
        q = t; // 让q再移到刚才保存的下一个节点处
    }
}

/*遍历链表*/
void show(Node_p p)
// p 保存链表的头指针
{
    while (p->next != NULL)
    {
        p = p->next;
        printf("%d ", p->data);
    }
    printf("\n");
}

int main(int argc, char const *argv[])
{
    Node_p H = Create(); // 创建空链表
    Insert(H, 0, 1);     // 插入数据
    Insert(H, 1, 2);
    Insert(H, 2, 1);
    Insert(H, 3, 4);
    Insert(H, 4, 5);
    printf("插入后: ");
    printf("长度: %d\n数据: ", Length(H));
    show(H);      // 遍历链表
    Delete(H, 1); // 删除数据
    printf("删除后: ");
    show(H);
    printf("查询数据: ");
    Search(H, 2);     // 查询数据
    Modify(H, 2, 10); // 修改数据
    printf("修改后: ");
    show(H);
    Reserve(H); // 转置链表
    printf("倒置后: ");
    show(H);
    DeleteSame(H, 1); // 删除指定数据节点
    printf("删除指定数据节点: ");
    show(H);
    Clear(H);
    printf("清空后: ");
    printf("长度:%d\n", Length(H));
    return 0;
}

 【2】运行结果

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值