C语言单链表操作笔记2.0

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <malloc.h>


/*自定义类型*/ 
typedef int Status;          
typedef struct Link {          
    Status data;  
    struct Link *next;
} link;
typedef struct LNode {
    Status data;  
    struct LNode *next;
} LNode, *LinkList;

/*自定义类型end*/ 

/* 预定义函数 */
link* initLink();                                            // 初始化 单链表
link* InsetElem(link *p, Status location, Status elem);      // 插入元素 单链表
link* deleteElem(link *p, Status location);                  // 删除元素 单链表
Status LinkLength(link *p);                                  // 查询表长度 单链表
Status SelectElem(link* p, Status elem);                     // 查询元素位置 单链表
link* AmendElem(link* p, Status location, Status nextElem);  // 修改元素数据 单链表
Status DestroyLink(link *p);                                 // 销毁 单链表
Status ClearList(link *p);                                   // 清空 链表
Status judgeLinkEmpty(link* p);                              // 判断链表是否为空
LinkList HeadInsert(LinkList L, Status n);                   // 头插法 单链表
LinkList FooterInsert(LinkList L, Status n);                 // 尾插法 单链表

LNode* initLinkList1(LinkList J);                            // 初始化循环单链表表J
LNode* initLinkList(LinkList K);                             // 初始化循环单链表表K
LinkList Connect(LinkList J, LinkList K);                    // 合并JK循环单链表

void print(link* p);                                         // 输出表信息
void print1(LNode *L);                                       // 输出循环表
/* 预定义函数end */

// 链表增删改查
int main(int argc, char const *argv[])
{  
    printf("初始化链表:"); 
    link * p = initLink();
    print(p);

    printf("链表插入元素:");
    link * InsetElemData = InsetElem(p, 5, 5);
    print(InsetElemData);

    printf("链表删除元素:");
    link * deleteElemData = deleteElem(InsetElemData, 0);
    print(deleteElemData);

    printf("查询链表长度:");
    Status LinkLengthData = LinkLength(deleteElemData);
    printf("链表长度:%d\n", LinkLengthData);

    printf("链表查询元素:");
    Status SelectElemData = SelectElem(deleteElemData, 5);
    if (SelectElemData == -1)
    {
        printf("查询元素不存在");
    }else printf("查询元素在第 <%d> 位\n", SelectElemData);
    
    printf("链表修改元素:");
    link *AmendElemData = AmendElem(deleteElemData, 5, 520);
    print(AmendElemData);
 
   /* 
    printf("销毁列表:");
    Status DestroyLinkData = DestroyLink(deleteElemData);
    if (DestroyLinkData == 1)
    printf("deleteElemData单链表已经销毁!\n");
    */

    printf("清空链表:");
    Status ClearListData = ClearList(deleteElemData);
    if (ClearListData == 1)
    printf("deleteElemData单链表已经清空!\n");

    printf("判断链表是否为空:");
    Status JLEData = judgeLinkEmpty(deleteElemData);
    if (JLEData == 1)
    {
        printf("deleteElemData单链表为空!\n");
    }else printf("deleteElemData单链表不为空!\n");

    
    LinkList L, J, K, ConnectData;

    link *LData = (link*)HeadInsert(L, 5);
    printf("头插法简历链表:");
    print(LData);

    link *FooterInsertData = (link*)FooterInsert(L, 5);
    printf("尾插法简历链表:");
    print(FooterInsertData);

     printf("初始化链表:\n");
    J = initLinkList(J);
    K = initLinkList1(K);
    print1(J);  
    print1(K);

    printf("合并循环表:\n");
    ConnectData = Connect(J, K);
    print1(ConnectData);

    return 0;

}

/* 初始化单链表 */
link* initLink() 
{
    Status i;
    link * p = (link*) malloc(sizeof(link));        // 创建头节点
    p->data = 4;                                    // 头结点数据域一般存储数据长度
    link * temp = p;                                // 创建头指针,指向头节点
    /* 生成链表 */
    for (i = 0; i < 5; i++)
    {
        link * arr = (link*) malloc(sizeof(link)); // 创建节点
        arr->data = i;                             // 给arr[i]的data赋值
        arr->next = NULL;                          // 给arr[i]的指针置空,用于保存下一个结点地址                    
        temp->next = arr;                          // 将arr[i]装入到头指针的地址temp->next中,同时也会存储到头结点p的next下,一直持续到结束
        temp = temp->next;                         // 后,再将temp->next替换为头指针继续下一层循环,
    }
    return p;
}

/* 
 *插入元素 单链表:
 * link *p:      链表数据
 * Status: int类型
 * Status location:插入位置
 * Status elem:    插入元素
 *  */
link* InsetElem(link *p, Status location, Status elem)
{   
    Status i;
    link * temp = p;                                // 创建临时节点,指向链表
    for (i = 0; i < location; i++)                  // 遍历,获取添加点的前地址
    {
       if (temp == NULL)                            // 判断传入的链表是否为空
       {
           printf("插入位置无效\n");
           return p;
       }
       temp = temp->next;                           // 获取插入前元素地址
    }
    link * addElem = (link*) malloc(sizeof(link));  // 创建结点存储添加元素
    addElem->data = elem;                           // 添加插入元素value值
    addElem->next = temp->next;                     // 替换元素地址
    temp->next = addElem;                           // 保存元素入指针

    return p;    
}

/* 
 *删除元素 单链表
 *  link*p: 要修改的链表
 *  Status location:位置
 *  */
link* deleteElem(link*p, Status location)
{
    Status i;
    link * temp = p;                                // 创建临时节点指向链表
    for (i = 0; i < location; i++)                  // 遍历删除位置,获取删除前一个元素的地址
    {
        temp = temp->next;                          // 获取插入前元素地址
    }
    link * delElem = temp->next;                    // 创建指针指向删除元素地址,防丢失
    temp->next = temp->next->next;                  // 修改删除节点域,将下一个节点指针与替换是一个节点指针域
    free(delElem);                                  // 释放内存
    return p;
}           

/* 查询表长度 */
Status LinkLength(link *p)
{
    link *temp = p;                     // 创建临时节点指向链表
    Status i = 0;                       // 定义记录
    while (temp->next != NULL){
        i++;                            // 记录自增
        temp = temp->next;              // 头指针指向下一节点
    }    
    return i;   
}

/* 
 * 查询元素位置 单链表:
 *   link* p:查询链表
 *   Status elem:查询元素
 * */
Status SelectElem(link* p, Status elem)
{
    link *temp = p;             // 创建临时节点指向链表
    Status i = 1;               // 标记元素查询位置
    while (temp->next)          // 循环查询链表
    {
        temp = temp->next;      // 更新地址
        if (temp->data == elem) // 判断当前地址data是否与查询的elem相同
        {
            return i;           // 相同输出 i;
        }
        i++;                    // 不相同 i 自增继续循环
    }
    return -1;                  // 都没有输出 -1
}           

/* 
 *修改元素数据 单链表:
 * link* p: 要修改的单链表
 * Status location:修改元素位置
 * Status nextElem:修改后的元素
 * */
link* AmendElem(link* p, Status location, Status nextElem)
{
    Status i;
    link *temp = p;                         // 创建临时节点
    temp = temp->next;                      // 临时节点指向首元节点
    for (i = 1; i < location; i++)          // 遍历链表获取修改元素的前一个元素地址
    {
        temp = temp->next;                  // 获取修改元素的前一个元素地址
    }
    temp->data = nextElem;                  // 修改数据
    return p;
}

// 判断链表是否为空
Status judgeLinkEmpty(link* p)
{
    link * temp = p;          // 创建临时节点
    if (temp->next == NULL)   // 判断节点指针域是否为空
    return true;              // 空返回true 非空false 
    else  return false;       
}

// 销毁单链表
Status DestroyLink(link *p)
{
    link *temp = p;                       // 创建头指针,指向表p
    while (temp->next)                    /* 循环指针下一地址是否为空 */ 
    {
        link * delElem = temp->next;      // 创建指针指向删除元素地址,防丢失
        temp->next = temp->next->next;    // 修改删除节点域,将下一个节点指针与替换是一个节点指针域
        free(delElem);                    // 释放内存
    }
    return true;
}

// 清空链表
Status ClearList(link *p)
{
    link * CurrentNode, *NextNode;      // 创建当前指针、指向下一节点指针
    CurrentNode = p->next;              // 记录首元节点地址
    while (CurrentNode != NULL)         // 判断是否为空,循环释放所有节点
    {
        NextNode = CurrentNode->next;   // 记录下一节地址
        free(CurrentNode);              // 释放上一节点
        CurrentNode = NextNode;         // 重置上一节点记录信息       
    }
    p->next = NULL;                     // 所有节点释放完成,头节点指针赋值为NULL结束循环;                
    return true;
}                             

/* 
 *头插法(倒序):
 * LinkList L: 单链表
 * Status n:插入数量
 * */
LinkList HeadInsert(LinkList L, Status n)
{
    Status i;
    LNode *temp;

    /* 初始化链表 空表 */
    L = (LinkList) malloc(sizeof(LNode));           // 创建头节点
    L->next = NULL;                                 // 置空头节点地址

    printf("请输入插入元素:");
    for (i = n; i > 0; --i)
    {
        temp = (LinkList) malloc(sizeof(LNode));    // 创建节点
        scanf("%d",&temp->data);                    // 输入插入信息
        temp->next = L->next;                       // 记录上一节点所有地址                         
        L->next = temp;                             // 将所有节点接入头节点        
    }
    return L;
}

/* 
 *尾插法(升序):
 * LinkList L: 单链表
 * Status n:插入数量
 * */
LinkList FooterInsert(LinkList L, Status n)
{   
    LNode * temp;
    /* 新建空链表 */
    L = (LinkList)malloc(sizeof(LNode));          // 创建   
    L->next = NULL;
    LNode* footer = L;                            // 创建尾指针指向头结点

    /* 循环遍历创建节点 */
    printf("请输入插入%d个数字", n);
    for (Status i = 0; i < n; i++)
    {
        temp = (LinkList)malloc(sizeof(LNode));   // 创建节点
        temp->next = NULL;                        // 置空新节点地址
        scanf("%d", &temp->data);                 // 输入节点数据
        footer->next = temp;                      // 新节点插入表尾
        footer = temp;                            // 尾指针指向新节点               
    }
    return L;
}

// 创建表J
LNode* initLinkList(LinkList J)
{
    LNode *arr, *footerNext;                    // 预定义输入数组,尾指针
    /* 创建空链表 */
    J = (LinkList)malloc(sizeof(LNode));        // 创建头结点
    J->next = NULL;                             // 头节点地址置空
    footerNext = J;                             // 创建尾指针指向头节点,保存循环数据

    // 添加数据
    for (int i = 0; i < 5; i++)
    {
        arr = (LinkList)malloc(sizeof(LNode));  // 创建新结点
        arr->data = i;                          // 输入data域值
        arr->next = NULL;                       // 新节点地址置空
        footerNext->next = arr;                 // 尾指针地址指向新节点
        footerNext = footerNext->next;          // 新节点变成尾指针
    } 
    footerNext->next = J;                       // 尾节点地址指向头节点,实现循环

    return footerNext;                          // 返回尾指针
}

// 创建表K
LNode* initLinkList1(LinkList K)
{
    LNode *arr, *footerNext;
    /* 创建空链表 */
    K = (LinkList)malloc(sizeof(LNode));        // 创建头结点
    K->next = NULL;                             // 头节点地址置空
    footerNext = K;                             // 创建尾指针指向头节点,保存循环数据
    // 添加数据
    for (int i = 5; i < 10; i++)
    {
        arr = (LinkList)malloc(sizeof(LNode));  // 创建新结点
        arr->data = i;                          // 输入data域值
        arr->next = NULL;                       // 新节点地址置空
        footerNext->next = arr;                 // 尾指针下一地址指向新节点,
        footerNext = footerNext->next;          // 新节点变赋值变成尾节点
    } 
    footerNext->next = K;                       // 尾节点地址指向头节点,实现循环                 

    return footerNext;                          // 返回尾指针
}

/* 合并循环单链表:
 *  LinkList J:表J尾指针
 *  LinkList K:表K尾指针
 * */ 
LinkList Connect(LinkList J, LinkList K)
{
    LNode *LHeadNode;                               // 创建头指针 
    LHeadNode = J->next;                            // 头指针向头节点
    J->next = K->next->next;                        // K表头链接J表尾
    free(K->next);                                  // 释放K表头节点
    K->next = LHeadNode;                            // 修改尾指针,表尾地址指向头节点  
    return K;                                       
}   

/* 
 *输出表信息
 *  link* p:输出链表
 *  */
void print(link* p)
{
    link *temp = p;     //将temp指针重新指向头结点
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while (temp->next)
    {
        temp = temp->next;
        printf("%d\t", temp->data);
    }
    printf("\n");
}

/*
 *输出表信息
 *  LinkList L:输出链表
 *  */
void print1(LNode *L)
{
    LNode *nextNode = L->next; //将temp指针重新指向头结点
    //先输出后判断,当循环到与L相同结束循环。
    while (nextNode->next != L )
    {
        nextNode = nextNode->next;      
        printf("%d\t", nextNode->data);
    } 

    printf("\n");
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZiWie丶ZHANG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值