数据结构学习记录(三)链表的定义和操作
顺序存储结构如数组,进行插入与删除操作,往往会比较复杂,因为牵扯到了大量数组元素的后移操作,导致算法时间复杂度很高,但是链式存储结构的很好的解决了这一问题,链表在进行插入与删除操作时,只需遍历一遍线性表就可以搞定。缺点是不能进行随机访问,并且交换两个元素十分麻烦,往往指针会混乱,同样也不推荐将需要排序的数据使用链式结构储存,用顺序存储结构则更为轻松。
下面是单链表的定义及其操作的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;
}
上述各类函数,都由本人多次测试过,没出现问题。有疑问的小伙伴请评论问题,看到会尽快回复的。
数据结构学习记录(三)链表的定义和操作相关推荐
- MySQL学习记录 (三) ----- SQL数据定义语句(DDL)
相关文章: <MySQL学习记录 (一) ----- 有关数据库的基本概念和MySQL常用命令> <MySQL学习记录 (二) ----- SQL数据查询语句(DQL)> &l ...
- css学习记录三:文本属性
css学习记录三:CSS文本属性 一.文本属性的作用 二.文本颜色 三.文本对齐 四.装饰文本 五.文本缩进 六.行间距 一.文本属性的作用 CSSS Text(文本)属性可定义文本的外观,比如文本的 ...
- Kafka学习记录(三)——Broker
Kafka学习记录(三)--Broker 目录 Kafka学习记录(三)--Broker 对应课程 Zookeeper存储的Kafka信息 Broker总体工作流程 Broker的服役和退役 Kafk ...
- 【C语言进阶深度学习记录】十七 宏定义的使用与分析
文章目录 1 C语言中的宏定义 1.1 定义宏常量 1.2 宏定义表达式 1.3 宏表达式与函数的对比 1.4 宏表达式的作用域 2 C语言中的内置宏 3 宏定义的代码综合示例 4 总结 1 C语言中 ...
- (王道408考研数据结构)第二章线性表-第三节2:双链表的定义及其操作(插入和删除)
文章目录 一:双链表的定义 二:双链表代码描述 三:双链表的初始化 四:双链表的插入 五:双链表的删除 一:双链表的定义 双链表:双链表在单链表的基础上再增加一个指针域,用于指向它的前驱结点 二:双链 ...
- (王道408考研数据结构)第二章线性表-第三节1:单链表的定义及其操作(插入和删除,建立之尾插和头插)
文章目录 一:单链表相关 (1)单链表的定义 (2)头指针与头结点 二:单链表代码描述 三:单链表的初始化 四:单链表的插入 五:单链表的删除 六:单链表查找 (1)按位查找 (2)按值查找 七:单链 ...
- webrtc学习记录三【创建基于RTCPeerConnection本机内的1v1音视频互通】
系列文章目录 webrtc学习记录一[媒体录制MediaRecorder] webrtc学习记录二[基于socket.io创建信令服务器聊天室] 目录 系列文章目录 前言 一.媒体能力的协商过程 1. ...
- 数据结构学习之单链表
节点类 #ifndef Node_H #define Node_H template <class Type> class Node //单链节点类 { public: Type data ...
- 【内核链表】数据结构——深入理解内核链表的概念和操作笔记
内核链表 一.内核链表的前置概念 1.容器 2.通用解决方案 二.通用型链表节点的设计 1.初始化 2.增删操作 3.查找节点 4.遍历链表 5.示例代码 三.内核链表 1.普通链表弊端 2.内核链表 ...
最新文章
- IDEA中的maven工程Java未被识别的解决方法
- 飞秋官方下载 某些大型企业
- shell脚本打开一个新终端并运行指定脚本
- css 引入的 方式有哪些? link与post有什么区别??
- python查看mongo库容量_mongo查看数据库空间大小
- 【随感】我觉得,世界上最美好的乐器是钢琴和架子鼓
- springmvc源码-我们自定义的参数解析器是如何放入到spring容器中的
- python之time:基于python语言利用time模块计算运行时间—计算机器学习模型训练前后的时间代码实现
- 2022年如何申请延迟还款(国家助学贷款)
- 【原创】Magisk+Shamiko过APP ROOT检测
- 测试人员如何做好需求分析
- Web安全学习系列(1)
- DataCastle员工离职预测数据竞赛个人总结
- sublime3编程c语言,Sublime Text 3 实现C语言代码的编译和运行(示例讲解)
- 【Unity 3D 从入门到实战】Unity 3D 组件总结
- 怎么进入BAT的研发部门?
- python常见的数据类型形式化定义_详解:规整数据(Tidy Data)的理论与Python实践
- Caesar密码的生成与破解
- ADS1.2 Error:(Fatal) L6002u:could not open file C:/...
- 翻开播客的B面:小众乌托邦的商业想象力