单链表常见操作图文详解

标签: 单链表
1453人阅读 评论(0) 收藏 举报
分类:

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

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

     无头单链表,也就是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;
}





查看评论

单链表的基本操作-----图形解析

首先我们需要思考的是为什么需要单链表呢? 单链表和顺序表相比较,又有什么优点呢? 在顺序表中,当我们需要头插,或者在顺序表的中间位置插入元素时,就必须将后面的元素一一后移,再将需要插入的元...
  • qq_34992845
  • qq_34992845
  • 2016-12-31 01:12:28
  • 4436

单链表基本操作详解

#  单链表基本操作 文中提到的内容的链接一并列在这里: 顺序表:http://blog.csdn.net/bitboss/article/details/51559175 冒泡排序:...
  • bitboss
  • bitboss
  • 2016-06-04 22:12:46
  • 3168

C语言——带头节点单链表常见操作

#include #include typedef struct stu { int data; //存放数据 struct stu* next; //下一个节点地址 }Node...
  • qq_36782456
  • qq_36782456
  • 2017-04-20 17:04:20
  • 997

速达3000XP操作详解(图文)

  • 2017年03月03日 11:21
  • 1.95MB
  • 下载

单链表面试题——基础篇

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用 总结: 1.若线性表需要频繁查找,很少进行插入、删除操作,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构; 2.当线性表...
  • sssssuuuuu666
  • sssssuuuuu666
  • 2017-06-13 17:37:37
  • 633

线性表-单链表

  • 2014年05月12日 16:22
  • 7KB
  • 下载

单链表的常见操作

  • 2013年01月10日 09:40
  • 4KB
  • 下载

数据结构之链表基本操作总结

数组与链表的区别  数组(顺序存储)和链表(链式存储)是两种不同的数据存储方式。 数组是一组具有相同类型和名称的变量的集合,这些变量称为数组的元素,每个数组元素都有一个编号,这个编号称...
  • Lily_whl
  • Lily_whl
  • 2017-05-11 18:22:11
  • 2471

Java单链表基本操作(四)--单链表反转

单链表反转是笔试面试中考察最多的算法之一,是单链表里必须要熟练掌握的算法。/** * @author Gavenyeah * @date Start_Time:2016年4月1日 上午11:38...
  • y999666
  • y999666
  • 2016-04-01 11:47:11
  • 779

数据结构之Java单链表反转

本文为数据结构基础,研究得不是很深。用Java实现单链表的反转,虽然本文研究得不是很深,但是因为是数据结构,所以必须是在对Java内存比较清楚的情况下才能真正的搞懂吃透,如果对Java内存不够清楚,那...
  • qq_24692041
  • qq_24692041
  • 2017-03-16 15:44:37
  • 2383
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 62万+
    积分: 9770
    排名: 2259
    博客专栏
    最新评论
    云计算
    资源整合和企业成本节约的一把利器!!!