搬砖:单链表常见操作图文详解

https://blog.csdn.net/fanyun_01/article/details/79831877

好文,,是我需要的。csdn垃圾,图复制不过来,,,,,

 

单链表的最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能。

     单链表分为两种:有头链表和无头链表。

     无头单链表,也就是phead一只是一个指针,指向链表的第一个节点。

     

带头节点的单链表:只不过头结点的data不保存信息。


//构建一个节点

    typedef struct Node
    {
        DataType data;
        struct Node *next;
     
    }Node,*PHead;

    //1.初始化单链表
    void InitListNode(PNode *pHead)
    {
        assert(pHead);
        *pHead = NULL;
    }

    //2.构建一个结点
     PNode BuyNode(DataType _data)
    {
        PNode node = (PNode)malloc(sizeof(Node));
        if (node)
        {
             node->data = _data;
             node->next = NULL;
        }
        return node;
    }

    /*3.尾插 考虑因素:链表为空时,直接让phead指向新节点即可。 链表不空时,遍历一遍链表,找到最后一个链表,连接在最后一个链表的后面即可。 */
    void PushBack(PNode *pHead,DataType _data)
    {
        assert(pHead);
        PNode newNode = BuyNode(_data);
        if (NULL == (*pHead))
        {
            *pHead = newNode;
            return ;
        }
        PNode pCur = *pHead;
        while (pCur->next)
        {
            pCur = pCur->next;
        }
        pCur->next = newNode;
    }

尾插图解:


    /*4.尾删 考虑因素:链表为空时,直接返回
    链表中只有一个结点时,free这个节点,并将phead置空 链表中有多个节点时,遍历一遍链表,找到最后一个节点(pCur->next == NULL),并且保存最后一个节点的前一个节点的信息 */
    void PopBack(PNode *pHead)
    {
        assert(pHead);
        if (NULL == (*pHead))
        {
            return ;
        }
        else if (NULL == (*pHead)->next)
        {
            free(*pHead);
            *pHead = NULL;
        }
        else
        {
            PNode pCur = *pHead;
            PNode prev = pCur;
            while (pCur->next)
            {
                prev = pCur;
                pCur = pCur->next;
            }
            free(pCur);
            prev ->next = NULL;
        }
    }

尾删图解:


    /*5.头插 考虑因素: 链表为空时:直接让phead指向新的节点即可。 当链表有一个节点或者多个节点时: 如图示:*/
    void PushFront(PNode *pHead,DataType _data)
    {
        assert(pHead);
        PNode newNode = BuyNode(_data);
        if (NULL == (*pHead))
        {
            *pHead = newNode;
        }
        else
        {
            if (newNode)
            {
                newNode->next = *pHead;
                *pHead = newNode;
            }
        }
    }

头插示意:

 

    /*6.头删 考虑因素: 链表为空时:直接返回,不需要删除 链表不为空时:当只有一个节点时:free掉这个节点,并将phead置空。 当有多个节点时:如图示 分析可知:有一个节点和有多个节点可以使用相同的逻辑*/
    void PopFront(PNode *pHead)
    {
        assert(pHead);
        if (NULL == (*pHead))
        {
            return ;
        }
        PNode pDel = *pHead;
        *pHead = (*pHead)->next;
        free(pDel);
    }

头删图解:


    /*7.逆序打印单链表(递归): */
    void printFromTailToFront(PNode pHead)
    {
        if (pHead)
        {
            printFromTailToFront(pHead->next);
            printf("%d->",pHead->data);
        }
    }

    /*8.查找一个值为data的节点,如果存在,返回所在位置,否则,返回NULL
    只需要遍历一遍链表即可。 */
    PNode Find(PNode pHead, DataType _data)
    {
        if (NULL == pHead)
        {
            return NULL;
        }
        PNode pCur = pHead;
        while (pCur)
        {
            if (pCur->data == _data)
            {
                return pCur;
            }
            pCur = pCur->next;
        }
        return NULL;
    }
    //插入一个节点
    void InsertNode(PNode pos,DataType _data)
    {
        if (pos)
        {
            PNode newNode = BuyNode(_data);
            if (newNode)
            {
                newNode->next = pos->next;
                pos->next = newNode;
            }
        }
    }

    /*9.插入一个节点(由于是单链表,所以只能插在pos位置的后面) 需考虑的因素: ①检查参数(链表是否存在,pos位置是否为空) ②当pos位置不空时:如图示*/
    void InsertNode(PNode pos,DataType _data)
    {
        if (pos)
        {
            PNode newNode = BuyNode(_data);
            if (newNode)
            {
                newNode->next = pos->next;
                pos->next = newNode;
            }
        }
    }

插入一个节点图解:


    *10.删除pos位置上的一个节点: 需要考虑的因素: ①链表为空和pos为空,直接返回
    ②pos不为空且pos为1时,这时就可以转化为删除第一个节点,操作步骤同上面的头删
    ③当pos不是第一个节点时,分析如图示:*/
    void Erase(PNode* pHead, PNode pos)
    {
        assert(pHead);
        if ((NULL == (*pHead)) && (NULL == pos))
        {
            return ;
        }
        if((*pHead) == pos)
        {
            *pHead = pos->next;
            free(pos);
        }
        else
        {
            PNode pCur = *pHead;
            while (pCur ->next != pos)
            {
                pCur = pCur->next;
            }
            pCur->next = pos->next;
            free(pos);
        }
    }

删除pos位置结点图解:

    /*11.删除单链表中值为_data的节点*/
    void Remove(PNode* pHead, DataType _data)
    {
        assert(pHead);
        Erase(pHead, Find(*pHead,_data));
    }

    /*12.删除单链表中所有值为_data的节点:
    需考虑: ①第一个节点的值是_data,因为删除第一个节点需要修改phead的值,所以需要单独处理第一个节点的值是_data的时候。
    删除第一个节点就是上面所说的头删。
    ②如果第一个节点的值不是_data,直接处理即可。 下面处理第一个值不是_data(这里的_data为2)的情况:*/
    void RemoveAll(PNode *pHead, DataType _data)
    {
        assert(pHead);
        if (NULL == (*pHead))
        {
            return ;
        }
        PNode pDel = *pHead;
        if ((*pHead)->data == _data)
        {
            *pHead = (*pHead)->next;
            free(pDel);
        }
        PNode pCur = *pHead;
        PNode prev = pCur;
        while (pCur)
        {
            if (pCur->data == _data)
            {
                prev->next = pCur->next;
                free(pCur);
                pCur = prev->next;
            }
            else
            {
                prev = pCur;
                pCur = pCur->next;
            }
        }    
    }

删除单链表中所有值为_data的结点图解:

    /*13.打印单链表:*/
    void printList(PNode phead)
    {
        PNode pCur = phead;
        while (pCur)
        {
            printf("%d ",pCur->data);
            pCur = pCur->next;
        }
        printf("\n");
    }

    /*14.得到单链表中节点的个数: */
    size_t Size(PNode pHead)
    {
        size_t count = 0;
        while (pHead)
        {
            pHead = pHead->next;
            count++;
        }
        return count;
    }

 

 
---------------------  
作者:老樊Lu码  
来源:CSDN  
原文:https://blog.csdn.net/fanyun_01/article/details/79831877  
版权声明:本文为博主原创文章,转载请附上博文链接!

 

 

 

单链表的基本操作图解表示

2019年02月16日 18:00:11 Atalanta1 阅读数:26

   单链表就是链式存取的数据结构(也是线性表的一种),使用一组地址任意的存储单元存放的线性表中的数据元素,这些地址可以连续也可以不连续。
  链表的表示方法:结点表示:如下图所示:

data域:存放该节点的数据

next域:存放后继结点的地址

单链表结构的定义:

 
  1. typedef struct ListNode{

  2. struct ListNode *next;

  3. Datatype data;

  4. }ListNode;

初始化和销毁:

 
  1. //初始化单链表

  2. void InitList(ListNode **pFirst)

  3. {

  4. ListNode *Node = (ListNode *)malloc(sizeof(ListNode));

  5. *pFirst = NULL;

  6.  
  7.  
  8. }

  9.  
  10. //销毁

  11. void DestroyList(ListNode **pFirst)

  12. {

  13. *pFirst = NULL;

  14. }

下面为单链表基本操作的图解法:

(1)尾插:

头插:

中间插:

尾删:

头删:

中间删:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值