数据结构—单链表

news/2024/10/23 5:33:40/

目录

1.前言

2.了解单链表

3.单链表代码实现

      3.1 单链表结构体实现

      3.2 创建节点

      3.3  打印单链表

      3.4 尾插 

      3.5  头插 

      3. 6 头删

      3.7  尾删

      3.8  查找

      3.9  插入

           3.9.1 在pos位置之前插入 

           3.9.2  在pos位置之后插入(主要使用这种功能)---不需要找pos前一个

      3.10 删除

             3.10.1 删除pos位置的值

             3.10.2  删除pos后一个(主要使用这种功能)---不需要找pos前一个

      3.11 单链表总结


1.前言

          学习了顺序表发现有以下缺点:


        1.1 空间不够,需要扩容(扩容有一定的空间浪费)。

        1.2 头插、头删(需要移动数据)时间复杂度是O(N),效率低。

         所以我们学习单链表来按需申请释放空间,不需要移动数据,提高效率。


2.了解单链表

  概念:单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

  特点:每个结点除了存放数据元素外,还要存储指向下一个节点的指针

  优点:不要求大片连续空间,改变容量方便。。

  缺点:不可随机存取,要耗费一定空间存放指针。

  单链表逻辑及重要性:


3.单链表代码实现

      3.1 单链表结构体实现

typedef int SLTDataType; 
typedef struct SListNode
{SLTDataType data;//存放数据struct SListNode* next;//指向下一个结构体的指针
}SLTNode;

       3.2 创建节点

void TestSList1()
{//struct SListNode* SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));assert(n1);SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));assert(n2);SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));assert(n3);SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));assert(n4);n1->data = 1;n2->data = 2;n3->data = 3;n4->data = 4;n1->next = n2;n2->next = n3;n3->next = n4;n4->next = NULL;
}

      3.3  打印单链表

cur = cur->next理解:

第一次进来cur指向的是链表的头,cur=cur—>next说明把下一个节点的地址赋给cur,现在的cur指向的是第二个结构体,是第二个结构体的地址.......

循环下去就可以打印出节点里的data数据,直到cur=NULL。

void SListPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

       3.4 尾插 

 注意点:

当链表为空的时候,newnode给phead时,由于phead是一个形参,函数中形参的改变不会改变实参。

这时要改变指针变量(plist)就要传指针变量的地址——就要传二级指针。

void SListPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);if (*pphead == NULL){*pphead = newnode;}else{// 找尾节点SLTNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}

         3.5  头插 

单链表头插不需要和尾插一样要特殊处理

void SListPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);newnode->next = *pphead;*pphead = newnode;
}

          3. 6 头删

void SListPopFront(SLTNode** pphead)
{assert(*pphead != NULL);//暴力检查//if (*pphead == NULL)  //温柔检查//	return;SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}

         3.7  尾删

void SListPopBack(SLTNode** pphead)
{assert(*pphead);// 1、只有一个节点// 2、多个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{  //两种方法   /*SLTNode* tailPrev = NULL;SLTNode* tail = *pphead;while (tail->next != NULL){tailPrev = tail;tail = tail->next;}free(tail);tailPrev->next = NULL;*/
//SLTNode* tail = *pphead;while (tail->next->next != NULL){tail = tail->next;}free(tail->next);tail->next = NULL;}	
}

      3.8  查找

SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x)return cur;cur = cur->next;}return NULL;
}

       3.9  插入

              3.9.1 在pos位置之前插入 

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x){  assert(pos);assert(ppheart);//头插if (pos= *pphead){SListPushFront(pphead.x);}else{SLTNNode* prev= *ppheart;while(prev->next !=pos){prev=prev->next;}SLTNode* newnode=BuySListNode(x);prev->next=newnode;newnode->next=pos;  }

           3.9.2  在pos位置之后插入(主要使用这种功能)---不需要找pos前一个

void SListInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);/*SLTNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;*/// 不在乎链接顺序SLTNode* newnode = BuySListNode(x);SLTNode* next = pos->next;// pos newnode nextpos->next = newnode;newnode->next = next;
}

      3.10 删除

             3.10.1 删除pos位置的值

void SListErase(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pos);assert(ppheart);//头删    if (pos= *pphead){SListPopFront(pphead);}else{ SLTNode* prev= *pphesd;while(prev->next !=pos){prev=prev->next;}prev->next= pos->next;free(pos);}

            3.10.2  删除pos后一个(主要使用这种功能)---不需要找pos前一个

void SListEraseAfter(SLTNode* pos)
{assert(pos);if (pos->next == NULL)return;SLTNode* del = pos->next;//pos->next = pos->next->next;//这样就释放不了节点pos->next = del->next;free(del);del = NULL;
}

          3.11 单链表总结

        由单链表的在pos位置之后插入和删除pos位置之后的值可知,单链表没有完全解决顺序表的缺陷,所以我们后面学习双向的链表来提高效率。


http://www.ppmy.cn/news/45375.html

相关文章

代码随想录训练营day44|完全背包;518、零钱兑换 II;377、组合总和 Ⅳ

完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。 代码模板: //先遍历物品,再遍历背包 private static void testCompletePack(){int[] weight {1, 3, 4};int[] value {15, 20, 30};int bagWeight 4;int[] dp new int[bagWe…

zsh: command not found: python问题解决

项目场景: mac电脑python命令打印不出来 问题描述 zsh: command not found: python没有python命令,但是本地安装了puyhon 原因分析: 没有配置python环境 解决方案: 提示:这里填写该问题的具体解决方案: 如…

堆排序及top-k问题

堆排序及top-k问题 堆排序建堆向上调整建堆向下建堆 堆排序 top-k问题,建堆的应用 堆排序 堆排序,听名字就是要对堆进行排序,但当我们是无序数据时,首先我们就需要建立一个堆 建堆 这里让我们来回忆一下前面的堆,改…

【C/C++】C++ 四种强制转换

文章目录 基本概念适用场景及代码案例测试运行Demo 基本概念 C 中有四种强制转换方式,分别是: static_cast:用于基本数据类型之间的转换,以及具有继承关系的指针或引用之间的转换。static_cast 在编译时进行类型检查,…

计算机视觉的热门研究方向与发展趋势

计算机视觉产业链 工业界:对学术研究提出需求 最火的两个概念:自动驾驶和元宇宙 相关热点研究方向: (1)建图技术:三维重建技术,包括SLAM、定位、建图、更新等技术;(2&…

基于LDA+SVM实现人脸识别模型

基于LDASVM实现人脸识别模型 描述 人脸识别(图像识别)是机器学习领域十经典的应用,在本质上,人脸识别属于监督学习中的分类问题。前面章节中我们已经学习了支持向量机(SVM),该算法在图像分类领…

又一科研利器诞生!能对话的论文阅读器,hammerScholar

文|智商掉了一地 hammerScholar 新升级,用对话式读论文工具提升科研生产力~ 不得不说,自从 AIGC 这个概念出现以来,它极强的内容理解与生成能力也推动着各种生产力工具层出不穷,除了一些浏览器和代码插件以外&#xff…

26岁转行网络安全,成功上岸安全开发!

前言 我是去年 9 月 22 日才正式学习网络安全的,之前在国营单位工作了 4 年,在长沙一个月工资只有 5000 块,而且看不到任何晋升的希望,如果想要往上走,那背后就一定要有关系才行。 而且国营单位的气氛是你干的多了&a…