当前位置: 首页 > news >正文

C语言数据结构-单向链表

头文件:link.h

#ifndef __LINK_H__
#define __LINK_H__

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

typedef int DataType;

/*节点数据类型*/
typedef struct node
{
    DataType data;              //数据域
    struct node *pNext;         //指针域
}LinkNode;

/* 标签数据类型 */
typedef struct list
{
    LinkNode *pHead;           //链表头节点指针
    int cLen;                  //当前链表节点个数
}LinkList;

#endif

源文件:link.c

#include "link.h"

创建一个新节点:
LinkList *createLinkList()
{
    LinkList *pList = NULL;

    pList = malloc(sizeof(LinkList));
    if (NULL == pList)
    {
        perror("fail to malloc");
        return NULL;
    }
    pList->pHead = NULL;
    pList->cLen = 0;

    return pList;
}

头插:
int insertHeadLinkList(LinkList *pList, DataType data)
{
    LinkNode * pInsertNode = malloc(sizeof(LinkNode));
    if (NULL == pInsertNode)
    {
        perror("fail to malloc");
        return -1;
    }
    pInsertNode->data = data;

    pInsertNode->pNext = pList->pHead;
    pList->pHead = pInsertNode;
    pList->cLen++;

    return 0;
}

遍历:

void showLinkList(LinkList *pList)
{
    LinkNode *pTmpNode = pList->pHead;

    while (pTmpNode != NULL)
    {
        printf("%d ", pTmpNode->data);
        pTmpNode = pTmpNode->pNext;
    }
    printf("\n");

}

判空:

int isEmptyLinkList(LinkList *pList)
{
    return pList->cLen == 0;
}

尾插:
int insertTailLinkList(LinkList *pList, DataType data)
{
    LinkNode *pInsertNode = malloc(sizeof(LinkNode));
    if (NULL == pInsertNode)
    {
        perror("fail to malloc");
        return -1;
    }
    pInsertNode->data = data;
    pInsertNode->pNext = NULL;

    if (isEmptyLinkList(pList))
    {
        pList->pHead = pInsertNode;
    }
    else
    {
        LinkNode *pTmpNode = pList->pHead;
        while (pTmpNode->pNext != NULL)
        {
            pTmpNode = pTmpNode->pNext;
        }
        pTmpNode->pNext = pInsertNode;
    }
    pList->cLen++;

    return 0;
}

头删:

int deleteHeadLinkList(LinkList *pList)
{
    if (isEmptyLinkList(pList))
    {
        return 0;
    }

    LinkNode *pFreeNode = pList->pHead;
    pList->pHead = pFreeNode->pNext;
    free(pFreeNode);
    pList->cLen--;

    return 0;
}

尾删:

int deleteTailLinkList(LinkList *pList)
{
    if (isEmptyLinkList(pList))
    {
        return 0;
    }
    else if (1 == pList->cLen)
    {
        deleteHeadLinkList(pList);
    }
    else
    {
        LinkNode *pTmpNode = pList->pHead;
        while (pTmpNode->pNext->pNext != NULL)
        {
            pTmpNode = pTmpNode->pNext;
        }
        free(pTmpNode->pNext);
        pTmpNode->pNext = NULL;
        pList->cLen--;
    }

    return 0;
}

查找单链表的某个节点:

LinkNode *findLinkList(LinkList *pList, DataType findData)
{
    LinkNode *pTmpNode = pList->pHead;

    while (pTmpNode != NULL)
    {
        if (pTmpNode->data == findData)
        {
            return pTmpNode;
        }
        pTmpNode = pTmpNode->pNext;
    }

    return NULL;
}

单链表倒置:

int reverseLinkList(LinkList *pList, DataType oldData, DataType newData)
{
    LinkNode *pTmpNode = NULL;
    while ((pTmpNode = findLinkList(pList, oldData)) != NULL)
    {
        pTmpNode->data = newData;
    }
    
    return 0;
}

销毁链表:

void destroyLinkList(LinkList **ppList)
{
    while ((*ppList)->pHead != NULL)
    {
        deleteHeadLinkList(*ppList);
    }
    free(*ppList);
    *ppList = NULL;

}

查找中间节点:
LinkNode *findMidLinkNode(LinkList *pList)
{
    LinkNode *pFast = pList->pHead;
    LinkNode *pSlow = pFast;

    while (pFast != NULL)
    {
        pFast = pFast->pNext;
        if (NULL == pFast)
        {
            break;
        }
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
    }

    return pSlow;
}

查找最后一个节点:

LinkNode *findLastKNode(LinkList *pList, int K)
{
    LinkNode *pFast = pList->pHead;
    LinkNode *pSlow = pFast;
    int i = 0;
    for (; i < K; i++)
    {
        pFast = pFast->pNext;
    }
    while (pFast != NULL)
    {
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
    }

    return pSlow;
}

删除某个节点:

int deletePointNode(LinkList *pList, DataType deleteData)
{
    LinkNode *pPreNode = pList->pHead;
    LinkNode *pFreeNode = pList->pHead;

    while (pFreeNode != NULL)
    {
        if (pFreeNode->data == deleteData)
        {
            if (pPreNode == pFreeNode)
            {
                pList->pHead = pFreeNode->pNext;
                free(pFreeNode);
                pPreNode = pList->pHead;
                pFreeNode = pList->pHead;
            }
            else
            {
                pPreNode->pNext = pFreeNode->pNext;
                free(pFreeNode);
                pFreeNode = pPreNode->pNext;
            }
            pList->cLen--;
        }
        else
        {
            pPreNode = pFreeNode;
            pFreeNode = pFreeNode->pNext;
        }
    }

    return 1;
}

单链表反转:

void invertLinkList(LinkList *pList)
{
    LinkNode *pTmpNode = pList->pHead;
    LinkNode *pInsertNode = NULL;
    
    pList->pHead = NULL;
    while (pTmpNode != NULL)
    {
        pInsertNode = pTmpNode;
        pTmpNode = pTmpNode->pNext;
        
        pInsertNode->pNext = pList->pHead;
        pList->pHead = pInsertNode;
    }
    
    return ;
}

链表排序:

void sortLinkList(LinkList *pList)
{
    //链表为空或只有一个节点不需要排序
    if (isEmptyLinkList(pList) || 1 == pList->cLen)
    {
        return ;
    }
    //保存第二个节点并且从第一个节点后断开
    LinkNode *pInsertNode = NULL;
    LinkNode *pTmpNode = pList->pHead->pNext;
    pList->pHead->pNext = NULL;

    while (pTmpNode != NULL)
    {
        //找到要插入的节点
        pInsertNode = pTmpNode;
        pTmpNode = pTmpNode->pNext;

        //判断是否需要头插
        if (pInsertNode->data < pList->pHead->data)
        {
            //头插
            pInsertNode->pNext = pList->pHead;
            pList->pHead = pInsertNode;
        }
        else
        {
            //寻找插入位置
            LinkNode *p = pList->pHead;
            while (p->pNext != NULL && p->pNext->data < pInsertNode->data)
            {
                p = p->pNext;
            }
            //节点插入
            pInsertNode->pNext = p->pNext;
            p->pNext = pInsertNode;
        }
    }
}

判断链表是否有环:

int isLoopLinkList(LinkList *pList)
{
    LinkNode *pFast = pList->pHead;
    LinkNode *pSlow = pList->pHead;

    while (pFast != NULL)
    {
        pFast = pFast->pNext;
        if (NULL == pFast)
        {
            return 0;
        }
        if (pSlow == pFast)
        {
            return 1;
        }
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
        if (pFast == pSlow)
        {
            return 1;
        }
    }
}
int main(int argc, const char *argv[])
{
    LinkList *pList = NULL;
    LinkNode *pTmpNode = NULL;

    pList = createLinkList();

//    insertHeadLinkList(pList, 1);
    insertHeadLinkList(pList, 2);
    insertHeadLinkList(pList, 3);
    insertHeadLinkList(pList, 4);

    insertTailLinkList(pList, 5);
    insertTailLinkList(pList, 3);
    insertTailLinkList(pList, 3);
    insertTailLinkList(pList, 3);
    insertTailLinkList(pList, 3);
    insertTailLinkList(pList, 3);
    insertTailLinkList(pList, 3);


    showLinkList(pList);
#if 0
    deleteHeadLinkList(pList);

    deleteTailLinkList(pList);

    showLinkList(pList);

    pTmpNode = findLinkList(pList, 3);
    if (pTmpNode != NULL)
    {
        printf("find %d\n", pTmpNode->data);
    }
    else
    {
        printf("not find\n");
    }

    reverseLinkList(pList, 3, 10);
    showLinkList(pList);
#endif
    
    pTmpNode = findMidLinkNode(pList);
    printf("mid node = %d\n", pTmpNode->data);

    pTmpNode = findLastKNode(pList, 3);
    printf("last K node = %d\n", pTmpNode->data);
#if 0    
    deletePointNode(pList, 3);
    showLinkList(pList);
    
    invertLinkList(pList);
    showLinkList(pList);

    sortLinkList(pList);
    showLinkList(pList);

//    destroyLinkList(&pList);
#endif

    //构造环形链表
    pTmpNode = pList->pHead;
    while (pTmpNode->pNext != NULL)
    {
        pTmpNode = pTmpNode->pNext;
    }
    pTmpNode->pNext = pList->pHead->pNext->pNext->pNext->pNext;

    if (isLoopLinkList(pList))
    {
        printf("is loop link.\n");
    }
    else
    {
        printf("is not loop link.\n");
    }

    return 0;
}
 

相关文章:

  • yolov5 安卓运行
  • 未授权访问漏洞利用链实战总结
  • 【LLM】使用 Ollama 和 RAGFlow 进行本地模型搭建知识库问答
  • 零代码构建 RAG 私有知识问答服务
  • 写起来比较复杂的深搜题目
  • 探索微观世界的“度量衡”:显微测量仪器解析
  • 7.6/Q1,GBD数据库最新文章解读
  • 【计网】五六章习题测试
  • 《牛客》数组中出现次数超过一半的数字
  • 班迪录屏--解决视频剪辑时声音和画面不同步的问题
  • 深度“求索”:DeepSeek+Dify构建个人知识库
  • Gradle快速入门
  • git 暂存功能使用
  • Java的动态加载及类加载器实践
  • 《进化陷阱》--AI 生成文章 《连载 2》
  • PH热榜 | 2025-05-23
  • 板卡设计资料:基于fpga的10G以太网AD、Camera数据传输适配器
  • Pluto实验报告——基于2ASK的简易的通信系统
  • 【普及+/提高】洛谷P2613 【模板】有理数取余——快读+快速幂
  • 邻近标记技术(PL)在癌症研究中的应用
  • 自己做的网站申请软著/推广怎么推
  • 高密住房和城乡建设局网站/怎样才能在百度上面做广告宣传
  • 网页网站开发手机游戏/百度提交收录
  • 市政府网站集约化建设/外贸推广渠道有哪些
  • 科网站建设/网站关键词百度自然排名优化
  • 临沂网站建设教程/单页网站怎么优化