链表的定义

  • 链表:由一系列结点(链表中每一个元素称为结点)组成,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

  • 链表这种存储方式,其元素个数是不受限定的,当进行添加元素的时候存储的个数就会随之改变。
  • 链表和数组的优缺点对比:
数据形式 优点 缺点
链表 运行时确定大小,快速插入和删除元素 不能随机访问,用户必须提供编程支持
数组 C直接支持,提供随机访问 在编译时确定大小,插入和删除元素很费时
  • 在链表中有一个头指针变量,这个指针变量保存一个地址,通过这个地址来找到这个链表,头指针节点指向第一个节点,在链表中每个节点包含两个部分:数据部分和指针部分。虽然结构体不能含有与本身类型相同的结构,但是可以含有之相同类型结构的指针,这种定义是链表的基础,链表中每一项都包含在何处能找到下一项的信息。而最后一个节点的指针指向必须为空NULL,从链表的原理来看不用担心链表的长度会超出范围这种问题。
  • 链表的声明
typedef struct ListNode{int val;struct ListNode* next;ListNode(int x) :val(x), next(NULL){}
};

链表的基本操作

一、创建单链表
  • 创建头节点head,并且将当前结点p指向头结点(p=head);
  • 创建下一个结点q,当前结点p的下一结点为q(p->next=q);
  • 结点p后移一位(p = p->next);
#include <iostream>
#include<vector>using namespace std;struct ListNode{int val;struct ListNode* next;ListNode(int x) :val(x), next(NULL){}
};int main(){int num;cin >> num;ListNode *head = new ListNode(num);ListNode *p = head;// 利用尾插法创建一个链表while (cin >> num){ListNode* q = new ListNode(num);p->next = q; p = p->next;}// 遍历这个链表,并输出每个结点的元素ListNode *m = head;while (m != nullptr){cout << m->val << endl;m = m->next;}return 0;
}
二、插入节点
  • 判断原链表是否是空链表,如果是,将head指向新增结点;
  • 如果不是空链表,向链表尾部插入新结点;
ListNode* insertNode(ListNode* head, int data){ListNode *newNode = new ListNode(data);ListNode *p = head;if (p == nullptr){head = newNode;} else {while (p->next != nullptr){p = p->next;}p->next = newNode;}return head;
}
三、删除节点

ListNode *deleteNode(ListNode* head, int data){ListNode *p = head;// 首先判断是不是空链表if (p == nullptr){return head;} else {// 判断是不是删除头节点if (p->val == data){head = p->next;delete p;return head;} else {// 如果有该结点,遍历到待删除节点的前一节点while (p->next != nullptr && p->next->val != data){p = p->next;}// 遍历完整个链表都没有待删除节点if (p->next == nullptr){return head;} else {ListNode *deleteNode = p->next;p->next = deleteNode->next;delete deleteNode;return head;}}}
}
四、遍历链表
  • 定义一个用于遍历的临时指针,用while循环实现遍历输出等操作;
void ScanList() {// 定义一个临时变量来指向头struct Node *temp = head;       while (temp != NULL){printf("%d\n",temp->a);// temp指向下一个的地址 即实现++操作temp = temp->next;       }
}
五、 查询指定的节点(遍历)
struct Node *FindNode(int a ) {struct Node *temp = head;while(temp != NULL) {if(a == temp->a) {return temp;}temp = temp->next;}return NULL;
}
六、链表清空
  • FreeList函数仍是采用遍历的方式一个一个的将节点内存释放,最后实现全部删除的效果,但是要注意在最后应该讲头尾节点至NULL否则下次的链表将会接着这次的头尾。
void FreeList() {// 定义一个临时变量来指向头struct Node *temp = head;       while (temp != NULL) {struct Node *pt = temp;// temp指向下一个的地址 即实现++操作temp = temp->next;      // 释放当前free(pt);                    }// 头尾清空,不然下次的头就接着0x10head = NULL;end = NULL;
}
七、反转链表
  • 假设pNode是当前的节点,pPrev是pNode前面的节点,PNext是PNode后面的节点,那么:
    • 当pNode不为nullptr,且pNext不为nullptr的时候:
      ① 将pNode指向pPrev(pNode->next = pPrev);
      ② 将pNode给pPrev(pPrev= pNode);
      ③ 将pNext给pNode(pNode = pNext);
    • 当pNode不为nullptr,且pNext==nullptr的时候,把反转后的头部指向pNode;
#include <iostream>
#include<vector>using namespace std;struct ListNode{int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL){}
};// 反转链表
ListNode *reverse(ListNode *head) {ListNode *pPrev = nullptr;ListNode *p = head;ListNode *pReverseHead = nullptr;while (p != nullptr){ListNode *pNext = p->next;if (pNext == nullptr){pReverseHead = p;}p->next = pPrev;pPrev = p;p = pNext;}return pReverseHead;
}int main(){int num;cin >> num;ListNode *head = new ListNode(num);ListNode *p = head;while (cin >> num){ListNode *q = new ListNode(num);p->next = q;p = p->next;}p->next = nullptr;ListNode *result = reverse(head);ListNode *node = result;while (node != nullptr){cout << node->val << endl;node = node->next;}return 0;
}
八、倒数第K个节点
  • 设置快慢指针,快指针比慢指针多走k-1步,那么快指针走到终点的时候,慢指针指向倒数第K个结点;
ListNode *FindKthToTail(ListNode *pListHead, unsigned int k) {if (pListHead == nullptr || k == 0){return nullptr;}ListNode *pAhead = pListHead;// 判断K是不是超出了链表的长度for (int i = 0; i< k - 1; i++){if (pAhead->next != nullptr){pAhead = pAhead->next;} else {return nullptr;}}ListNode *pBehind = pListHead;while (pAhead->next != nullptr){pAhead = pAhead->next;pBehind = pBehind->next;}return pBehind;
}
九、判断链表是否有环
  • 可以设置快慢指针,快指针一次走两步,慢指针一次走一步,如果快指针追上了走的慢的指针,那么链表有环,如果走到了链表尾部都没有追上,说明链表无环。
  • 如果有环,返回入口节点:返回的节点一定在环内,如果计算出环中节点的个数count,快指针比慢指针多走count步,那么两个指针相遇时,就是环的入口节点。
// 判断快慢指针是否相遇
ListNode *MeetNode(ListNode *pHead){ListNode *pNode = pHead;// 判断链表是否为空if(pNode == nullptr){return nullptr;}// 设置慢指针(慢指针不能为nullptr)ListNode *slowNode = pNode -> next;if(slowNode == nullptr){return nullptr;}// 设置快指针ListNode *fastNode = slowNode -> next;while(fastNode != nullptr && slowNode != nullptr){// 相遇返回快/慢指针if(fastNode == slowNode){return fastNode;}// slow走一步slowNode = slowNode ->next;// fast走两步(走下一步需要判读是不是为nullptr)fastNode = fastNode -> next;if (fastNode -> next != nullptr){fastNode = fastNode -> next;}}return nullptr;
}// 计算环中节点的个数
int Count(ListNode *pMeet){int count = 0;ListNode * pNode = pMeet;while(pNode->next != pMeet){++count;pNode = pNode -> next;}++ count;return count;
}// 计算环的入口节点
ListNode *EntryNodeOfLoop(ListNode *pHead) {ListNode *meetNode = MeetNode(pHead);if (meetNode == nullptr){return nullptr;}int count = Count(meetNode);ListNode *aheadNode = pHead;ListNode *behindNode = pHead;for(int i = 0; i< count; i++){aheadNode = aheadNode ->next;}while(aheadNode != behindNode){aheadNode = aheadNode -> next;behindNode = behindNode -> next;}ListNode *result = aheadNode;return result;
}

【数据结构与算法】之链表的操作和使用相关推荐

  1. 数据结构与算法 内核链表实现商品购物系统项目+Makefile

    数据结构与算法 内核链表实现商品购物系统项目 第一章 项目实现思维 [1]编译介绍 [2]框架思维 第二章 Makefile编写 第三章 代码编写实现 [1]favorite.txt文件 [2]his ...

  2. 一文通数据结构与算法之——链表+常见题型与解题策略+Leetcode经典题

    文章目录 1 链表 1.1 常见题型及解题策略 1.1.1 LeetCode中关于链表的题目有以下五种类型题: 1.1.2 解题策略 1.2 链表的基本内容 1.2.1 链表的基本结构: 1.2.2 ...

  3. python定义链表节点_Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】...

    本文实例讲述了Python数据结构与算法之链表定义与用法.分享给大家供大家参考,具体如下: 本文将为大家讲解: (1)从链表节点的定义开始,以类的方式,面向对象的思想进行链表的设计 (2)链表类插入和 ...

  4. 数据结构与算法之链表结构寻找p、q最近的公共祖先

    链表结构,寻找p.q最近的公共祖先 数据结构与算法之链表结构寻找p.q最近的公共祖先 链表结构,寻找p.q最近的公共祖先 问题 想法 代码 问题 设一棵二叉树的结点结构为(LLINK, INFO, R ...

  5. 数据结构与算法--单链表相关面试题

    此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一.概述 获取单链表的有效元素个数[新浪面试题1] 获取单链表倒数第k个结 ...

  6. java数据接口之链表_Java数据结构和算法之链表

    三.链表 链结点 在链表中,每个数据项都被包含在'点"中,一个点是某个类的对象,这个类可认叫做LINK.因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点.每个LI ...

  7. 数据结构与算法之-----链表(List)

    [ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于​​​​​​​初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己 ...

  8. Java数据结构和算法(四)--链表

    日常开发中,数组和集合使用的很多,而数组的无序插入和删除效率都是偏低的,这点在学习ArrayList源码的时候就知道了,因为需要把要 插入索引后面的所以元素全部后移一位. 而本文会详细讲解链表,可以解 ...

  9. 数据结构与算法(一) 链表(代码示例)

    数据结构与算法 1. 什么是单链表 2. 实现单链表的增删操作 1. 插入单链表第i个结点,即插入到ai-1与ai之间的具体步骤: 2. 删除第i个结点 3. 删除链表的重复数据 4. 找出单链表中的 ...

  10. 头歌平台数据结构与算法 单链表实验 第1关:倒置链表

    任务描述 相关知识 实验目的 实验任务 实验说明 编程要求 测试说明 任务描述 本关任务:请在右侧编辑器的注释行填入适当内容来完成算法,以实现指定的功能,并通过运行来验证. 相关知识 实验目的 理解线 ...

最新文章

  1. Oracle 中对表空间使用情况进行查询
  2. Qt多线程示例--并发数据处理
  3. javascript本地缓存方案-- 存储对象和设置过期时间
  4. dedecms联动筛选_DEDECMS分类信息按联动类别筛选的实现方法
  5. 【Java】application run failed Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and
  6. Xshell 连接腾讯云、阿里云centos服务器
  7. H3CPPPOE拨号
  8. Python 2X 版本 痛苦的编码格式,一遍完美解决Unicode、GB2312、GBK编码格式的文章
  9. android studio trace,天猫Android性能优化1—AndroidStudio内置的Traceview视图
  10. 英雄联盟的角色设计思路
  11. 当下的力量实践手册读书笔记(1.30)
  12. Dungeon Architect插件介绍
  13. SW练习_POJ1912_CCW_点线关系_未AC
  14. 中科大少年班 | 实干兴“班”,这不是后浪,而是巨浪!
  15. 高等数学笔记-苏德矿-第九章-重积分(Ⅱ)-三重积分
  16. 研讨班管理系统的设计与实现【数据库课设】
  17. 使用java获取硬盘序列号
  18. SSM框架实战系列之十三_H-ui框架之一
  19. [Python]tabulate可如此优雅地创建表格
  20. [渝粤教育] 南通大学 分子生物学 参考 资料

热门文章

  1. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器出现no compatible source was found for this media问题的解决...
  2. 三、Appium-python-UI自动化之元素定位uiautomatorviewer
  3. 默认轮播,鼠标移入停止,移出继续
  4. 【转】PowerShell入门(五):Cmd命令与PowerShell命令的交互
  5. SQL之rand,round,floor,ceiling,cast小数处理函数
  6. 文本模式下的分辨率对照表
  7. 宝塔网设置伪静态进行隐藏php后缀名,nextcloud宝塔面板nginx伪静态-去除index.php
  8. hadoop搭建_hadoop分布式搭建之虚拟机克隆
  9. matplotlib画图时间长_Python学习第86课-数据可视化之matplotlib介绍
  10. int*类型和int类型_mysql8.0.19中在navicat客户端中int、bigint等类型设置长度保存后为0...