顺序存储结构如数组,进行插入与删除操作,往往会比较复杂,因为牵扯到了大量数组元素的后移操作,导致算法时间复杂度很高,但是链式存储结构的很好的解决了这一问题,链表在进行插入与删除操作时,只需遍历一遍线性表就可以搞定。缺点是不能进行随机访问,并且交换两个元素十分麻烦,往往指针会混乱,同样也不推荐将需要排序的数据使用链式结构储存,用顺序存储结构则更为轻松。

下面是单链表的定义及其操作的c++代码

#include <stdio.h>
#include <malloc.h>
#include <string.h>typedef int ElemType;typedef struct _NODE
{ElemType data;struct _NODE* next;
}NODE;typedef NODE* LinkList;/*
函数名   :GetElem
功能描述 :用e返回L中第i的元素
输入     :sl,e,i
sl,已存在顺序表
输出     :成功返回bool类型,true,否则返回false
全局变量 :无
调用模块 :
作者     :zhang·haochen
日期     :2019 - 01 - 19
修改     :
修改日期 :
版本     :ver 1.0
*/bool GetElem(LinkList s1,ElemType* e,int i)
{NODE* Ppos = s1;int j = 0;while (Ppos&&j < i){Ppos = Ppos->next;j++;}if (Ppos==NULL)return false;*e = Ppos->data;return true;
}/*
函数名   :ListInsert
功能描述 :在线性表第i个位置插入新元素e
输入     :sl,e,i
sl,已存在顺序表
输出     :插入成功返回bool类型,true,否则返回false
全局变量 :无
调用模块 :
作者     :zhang·haochen
日期     :2019 - 01 - 19
修改     :
修改日期 :
版本     :ver 1.0
*/bool LinkListInsert(LinkList* s1,int i,ElemType e)
{//插入位置小于0,错误的插入位置if (i < 0)return false;//插入位置为0,头插if (i == 0){NODE* pnew = (NODE*)malloc(sizeof(NODE));pnew->data = e;pnew->next = *s1;*s1 = pnew;return true;}//判断插入位置是否合法NODE* pPos = *s1;//(重点)寻找插入位置的前一个结点比如插入位置为5,则pPos从0往后移动4次,找到4(5的前一个).for (int j = 1; j < i&&pPos != NULL;j++){pPos = pPos->next;}//判断i的位置是否合法if (pPos == NULL)return false;//合法时pPos不为空,且是i的前一个NODE* pnew = (NODE*)malloc(sizeof(NODE));pnew->data = e;pnew ->next = pPos->next;pPos->next = pnew;return true;
}/*
函数名  :LinkListDelete
功能描述:删除单链表L中第i个位置的元素
输入    :L,i
L,已存在顺序表
i,删除位置,范围 0 <= i < 链表长度
输出    :bool值,删除成功true,否则false
全局变量:无
调用模块:无
作者    :zhang·haochen
日期    :2019-01-19
修改    :
修改日期:
版本    :ver 0.1
*/bool LinkListDelete(LinkList* s1,int i)
{//若删除位置小于0,则删除失败if (i<0)return false;//删除位置为0,为头删if (0 == i){NODE* pPos = *s1;*s1 = pPos->next;free(pPos);pPos = NULL;return true;}//寻找待删除节点的前一个节点else{NODE* pPos = *s1;for (int j = 1; j < i&&pPos != NULL; j++){pPos = pPos->next;}//找不到if (pPos == NULL || pPos->next == NULL)return false;NODE* pnew = (NODE*)malloc(sizeof(NODE));NODE* t;t = pPos->next;pPos->next = t->next;free(t);t = NULL;return true;}
}/*
函数名  :ClearLinkList
功能描述:清空链表
输入    :L
L,已存在顺序表
输出    :
全局变量:无
调用模块:LinkListDelete
作者    :zhang·haochen
日期    :2019-01-19
修改    :
修改日期:
版本    :ver 0.1
*/void ClearLinkList(LinkList* s1)
{while (*s1){LinkListDelete(s1, 0);}
}void ShowLinkList(const LinkList s1)
{NODE* pPos = s1;while (pPos!=NULL){printf("%d,",pPos->data);pPos = pPos->next;}puts("\b;");
}/*
函数名  :LinkListReverse
功能描述:清空链表
输入    :s1
s1,已存在顺序表
输出    :
全局变量:无
调用模块:
作者    :zhang·haochen
日期    :2019-01-20
修改    :
修改日期:
版本    :ver 0.1
*/void LinkListRerverse(LinkList* s1)
{if (*s1 == NULL || (*s1)->next == NULL)return;NODE *p1 = *s1;NODE *p2 = p1->next;NODE *p3 = p2->next;p2->next = p1;while (p3 != NULL){p1 = p2;p2 = p3;p3 = p3->next;p2->next = p1;}(*s1)->next = NULL;*s1 = p2;
}int main()
{LinkList s1 = NULL;LinkListInsert(&s1, 0, 1);LinkListInsert(&s1, 1, 2);LinkListInsert(&s1, 2, 3);LinkListInsert(&s1, 3, 4);LinkListInsert(&s1, 4, 5);LinkListInsert(&s1, 5, 6);LinkListInsert(&s1, 6, 7);LinkListInsert(&s1, 7, 8);LinkListDelete(&s1, 0);ShowLinkList(s1);LinkListRerverse(&s1);ShowLinkList(s1);return 0;
}

下面举上几个往年公司可能出的笔试题

1.求出单链表中的倒数第四个元素

思路,可以定义四个链表节点指针,分别指向第0,1,2,3个节点,然后同时往后遍历,直到,第四个指针的next域为NULL,则此时第一个指针所指的节点为倒数第四个节点。

ElemType FindLast4th(LinkList* l1)
{if (*l1 == NULL || (*l1)->next == NULL || (*l1)->next->next == NULL || (*l1)->next->next->next == NULL)return -1;NODE* p1 = *l1;NODE* p2 = *l1;p2 = p2->next;p2 = p2->next;p2 = p2->next;while (p2->next!=NULL){p1 = p1->next;p2 = p2->next;}return p1->data;
}int main()
{LinkList s1 = NULL;ElemType e;LinkListInsert(&s1, 0, 5);LinkListInsert(&s1, 0, 4);LinkListInsert(&s1, 0, 3);LinkListInsert(&s1, 0, 2);LinkListInsert(&s1, 0, 1);ShowLinkList(s1);printf("倒数第四个为:%d\n",FindLast4th(&s1));return 0;
}

2.单链表交换任意两个元素(不包括表头)

思路,交换第i,j个元素,定义两个链表节点指针,并都把头指针赋给他们,根据需要交换的两个下标,分别找出他们的前继节点i-1和j-1,在定义四个变量分别用来保存i节点与i+1节点,j节点与j+1节点。然后进行判断当i与j相邻时(即j-i=1或i-j=1),一种操作,其余情况在另一种操作中。具体操作见代码。

   bool SwapLinkList(LinkList* s1,int i,int j)
{if (i == 0 || j == 0)return false;NODE* prepPosi = *s1;NODE* prepPosj = *s1;for (int k = 1; k < i; k++){prepPosi = prepPosi->next;}for (int k = 1; k < j; k++){prepPosj = prepPosj->next;}NODE* pi, *pj,*posti,*postj;pi = prepPosi->next;pj = prepPosj->next;posti = pi->next;postj = pj->next;if (j - i == 1){prepPosi->next = pj;pj->next = pi;pi->next = postj;return true;}if (i - j == 1){prepPosj->next = pi;pi->next = pj;pj->next = posti;return true;}prepPosi->next = pj;pj->next = posti;prepPosj->next = pi;pi->next = postj;return true;
}

3.大数相加(就是计算机不能表示的整数(往往有很多位),进行相加)

思路首先这两个大数使用2个挺大的字符数组存储,然后比较两个数的长度,较短的那个数,相差几位,就往前面补几个0;然后使用链表头插,存进事先创建的链表中。大概就完成了,具体看代码。

/*
函数名   :AddBigNum
功能描述 :非常大的数相加
输入     :L2,数1和数1的长度,数2和数2的长度L2,已存在空链表表
输出     :
全局变量 :无
调用模块 :
作者     :zhang·haochen
日期     :2019 - 01 - 22
修改     :
修改日期 :
版本     :ver 0.1
*/
void AddBigNum(char* s1,int len1,char* s2,int len2,CLinkList** l2)
{//定义进位数为p,且初值为0;int p = 0;char c;if (len1 > len2){int news2 = len2+len1-len2;for (int oldlen2=len2; news2 >=0; news2--,oldlen2--){if (news2 > len1-len2-1){s2[news2] = s2[oldlen2];}elses2[news2] = '0';}}else if (len1 < len2){int news1 = len1+len2-len1;for (int oldlen1=len1; news1 >=0; news1--,oldlen1--){if (news1 > len2-len1-1){s1[news1] = s1[oldlen1];}elses1[news1] = '0';}}int i = strlen(s1) - 1, j = strlen(s2) - 1;while (i >= 0 && j >= 0){c= (((s1[i]-'0') +( s2[j]-'0' )+p) % 10)+'0';p = ((s1[i--]-'0') +( s2[j--]-'0')+p) / 10;LinkListInsert2(l2,0,c);        //头插}if (p == 1)    //最多会一位,即最多前面多个1{LinkListInsert2(l2, 0, '1');    //头插}
}int main()
{CLinkList* l2 = NULL;char s1[100] = "6658142543636282449368";char s2[100] = "64531546346853468453468";int len1 = strlen(s1);int len2 = strlen(s2);AddBigNum(s1,len1, s2,len2, &l2);ShowCLinkList2(l2);return 0;
}

上述各类函数,都由本人多次测试过,没出现问题。有疑问的小伙伴请评论问题,看到会尽快回复的。

数据结构学习记录(三)链表的定义和操作相关推荐

  1. MySQL学习记录 (三) ----- SQL数据定义语句(DDL)

    相关文章: <MySQL学习记录 (一) ----- 有关数据库的基本概念和MySQL常用命令> <MySQL学习记录 (二) ----- SQL数据查询语句(DQL)> &l ...

  2. css学习记录三:文本属性

    css学习记录三:CSS文本属性 一.文本属性的作用 二.文本颜色 三.文本对齐 四.装饰文本 五.文本缩进 六.行间距 一.文本属性的作用 CSSS Text(文本)属性可定义文本的外观,比如文本的 ...

  3. Kafka学习记录(三)——Broker

    Kafka学习记录(三)--Broker 目录 Kafka学习记录(三)--Broker 对应课程 Zookeeper存储的Kafka信息 Broker总体工作流程 Broker的服役和退役 Kafk ...

  4. 【C语言进阶深度学习记录】十七 宏定义的使用与分析

    文章目录 1 C语言中的宏定义 1.1 定义宏常量 1.2 宏定义表达式 1.3 宏表达式与函数的对比 1.4 宏表达式的作用域 2 C语言中的内置宏 3 宏定义的代码综合示例 4 总结 1 C语言中 ...

  5. (王道408考研数据结构)第二章线性表-第三节2:双链表的定义及其操作(插入和删除)

    文章目录 一:双链表的定义 二:双链表代码描述 三:双链表的初始化 四:双链表的插入 五:双链表的删除 一:双链表的定义 双链表:双链表在单链表的基础上再增加一个指针域,用于指向它的前驱结点 二:双链 ...

  6. (王道408考研数据结构)第二章线性表-第三节1:单链表的定义及其操作(插入和删除,建立之尾插和头插)

    文章目录 一:单链表相关 (1)单链表的定义 (2)头指针与头结点 二:单链表代码描述 三:单链表的初始化 四:单链表的插入 五:单链表的删除 六:单链表查找 (1)按位查找 (2)按值查找 七:单链 ...

  7. webrtc学习记录三【创建基于RTCPeerConnection本机内的1v1音视频互通】

    系列文章目录 webrtc学习记录一[媒体录制MediaRecorder] webrtc学习记录二[基于socket.io创建信令服务器聊天室] 目录 系列文章目录 前言 一.媒体能力的协商过程 1. ...

  8. 数据结构学习之单链表

    节点类 #ifndef Node_H #define Node_H template <class Type> class Node //单链节点类 { public: Type data ...

  9. 【内核链表】数据结构——深入理解内核链表的概念和操作笔记

    内核链表 一.内核链表的前置概念 1.容器 2.通用解决方案 二.通用型链表节点的设计 1.初始化 2.增删操作 3.查找节点 4.遍历链表 5.示例代码 三.内核链表 1.普通链表弊端 2.内核链表 ...

最新文章

  1. IDEA中的maven工程Java未被识别的解决方法
  2. 飞秋官方下载 某些大型企业
  3. shell脚本打开一个新终端并运行指定脚本
  4. css 引入的 方式有哪些? link与post有什么区别??
  5. python查看mongo库容量_mongo查看数据库空间大小
  6. 【随感】我觉得,世界上最美好的乐器是钢琴和架子鼓
  7. springmvc源码-我们自定义的参数解析器是如何放入到spring容器中的
  8. python之time:基于python语言利用time模块计算运行时间—计算机器学习模型训练前后的时间代码实现
  9. 2022年如何申请延迟还款(国家助学贷款)
  10. 【原创】Magisk+Shamiko过APP ROOT检测
  11. 测试人员如何做好需求分析
  12. Web安全学习系列(1)
  13. DataCastle员工离职预测数据竞赛个人总结
  14. sublime3编程c语言,Sublime Text 3 实现C语言代码的编译和运行(示例讲解)
  15. 【Unity 3D 从入门到实战】Unity 3D 组件总结
  16. 怎么进入BAT的研发部门?
  17. python常见的数据类型形式化定义_详解:规整数据(Tidy Data)的理论与Python实践
  18. Caesar密码的生成与破解
  19. ADS1.2 Error:(Fatal) L6002u:could not open file C:/...
  20. 翻开播客的B面:小众乌托邦的商业想象力

热门文章

  1. RHEL8.3升级openssh8.6(shell脚本)
  2. pip下载源的两种修改方法
  3. StringBuffer和StringBuild的使用
  4. VC界面编程skill tips-CListCtrl
  5. 信息管理毕业设计 SSM的员工_学生宿舍后勤管理系统(源码+论文)
  6. 象征性消费行为与体验营销
  7. tomcat9设置编码
  8. 数据结构与算法入门(Java)
  9. 山东大学软件学院操作系统课程设计Nachos-实验四-基本文件系统扩展
  10. java网络基本知识