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

下面是单链表的定义及其操作的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. Windows平板电脑将取代苹果在企业市场地位
  2. 基于ssm的水果商城系统项目总结
  3. CFHD打的爽就继续下去,打的不爽就?
  4. 通过ssh访问Back Track 5
  5. 【数学】概念的理解 —— 有序对(ordered pair)
  6. 只有python可以爬虫吗_无所不能的Python之爬虫那点事儿
  7. 信息学奥赛一本通 1005:地球人口承载力估计| OpenJudge NOI 小学奥数 7653
  8. 租房系统代码java_基于Java的租房管理系统的设计及实现.doc
  9. Nacos 新增命名空间
  10. bat脚本 rar压缩文件 rar压缩文件带一层路径 带路径压缩
  11. go1.5源代码安装
  12. AUTOSAR —— CAN网络管理(CanNm)
  13. 16张图详解计算机网络协议(万字)
  14. java如何实现对word设置只读或者加密
  15. 10-赵志勇机器学习-meanshift
  16. Jmeter入门教程之配置原件(二)
  17. 第7周项目5 排队看病模拟
  18. 题解 P1985 【[USACO07OPEN]翻转棋】
  19. C#筛选DataTable的数据
  20. 减少用户投诉,就选中国移动二次号查询

热门文章

  1. c语言单招试题,高职单招数学模拟试题
  2. 足不出户指挥千里 华为智慧屏让导演隔空指挥
  3. 软件项目常见风险及其预防措施
  4. excel表格数据的批量插入
  5. 快速合并两个TList【delphi7】
  6. ie浏览器使用pdf时需要先安装软件Adobe Reader 9
  7. 软件工程理论与实践—吕云翔 课后习题第二章答案
  8. c语言中求匀加速直线速度,速求C语言编程题 c语言编程速度求
  9. 测开转回开发经历感悟
  10. 信捷PLC 流程指令STL,S使用