摘要:思路查找倒数第个节点,可以看做是查找正序第个节点可以根据第一题的结果取数组的第个节点使用思路输入一个链表,反转链表后,输出新链表的表头。
前言
在写项目的时候会发现,并没有使用很多关于链表的东西,大多数情况使用的都是数组,但是由于在准备校招,很多公司都会考到这个问题,所以准备对链表的相关操作进行总结,并对其中的重难点进行强调,最后还会附加几道关于链表的算法题,那么现在就开始吧!
链表的基础操作 创建一个链表结构了解过链表的同学应该都知道,链表有几个特点:
可以动态扩展空间(在js中,数组也是这样的,但是有的语言中数组的长度是固定的,不能动态添加,如c语言)
需要一个头节点
需要知道下一个节点的地址
可以将链表中的每个节点看成是一个对象,这个对象中有两个属性,一个是该节点的值,一个是该节点的下一个节点的地址(如果是双链表,还要添加前一个节点地址的属性)
function LinkedList(){ //辅助类:表示要加入链表的项 let node = function(element){ this.element = element; this.next = null;//这个节点的下一个节点暂时为空 } let length = 0; let head = null; this.append() = function(element){};//向链表的尾部添加节点 this.insert() = function(position,element){};//在指定的位置添加节点 this.remove = function(element){};//将指定的节点删除掉 this.removeAt = function(position){};//将指定位置的节点删除 this.searchElement = function(element){};//查找指定元素的位置 this.searchPosition = function(position){};//查找指定位置的元素 }
上面代码中包含了很多要实现的操作,包括最基本的增删以及查询。下面我们就来一一的实现上面列举的方法:
实现增加节点的操作在尾节点处添加节点
function append(element){ let node = new Node(element);//1 let current;//2 //3 if(head === null){ head = node }else{ current = head while(current.next){ current = current.next } current.next = node } length++;//4 }
根据传入的元素定义一个节点,该元素作为这个节点的值
定义一个变量表示当前的节点
判断是否含有头节点,如果没有头节点,说明链表中还没有值,将传进来的这个值作为头节点;否则,对链表进行遍历,找到最后一个节点,将其next属性赋值为新增的节点
链表的长度+1
在任意位置添加节点
将这个位置的前一个节点的next属性赋值为这个节点,并将它原先的下一个节点保存下来,赋值给现在这个节点的next属性
function insert(position,element){ if(position >=0 && position <= length){ //当position为length时,表示在尾节点处添加,包含了append方法 let node = new Node(element); let current = head; let previous;//当前节点的前一个节点,在position处添加节点,就是在previos和current之间添加 if(position = 0){ node.next = head; head = node; }else{ for(let i = 0;i< position;i++){ pervious = current; current = current.next; } pervious.next = node; node.next = current; } length++; return true; }else{ return false; } }
检查postion是否越界,若没有越界,则创建一个节点
定义一个变量表示当前的节点,初始化为头节点,表示从头节点开始遍历;一个变量表示当前节点的前一个节点,作用是插入节点时方便找到前一个节点
判断是否在头节点前添加,如果是就将头节点赋给node的next属性,并且头节点改为这个节点;否则,遍历出这个位置的节点,将该节点插入到这个位置的节点前面
链表的长度+1
实现删除节点的操作基本思路:删除节点的操作就是将目标节点前面的那个节点的指针指向目标节点的有一个节点
删除指定节点
function removed(element){ let node = new Node(element); let pervious; let nextNode; let current = head; if(head != null){ while (current != node){ pervious = current; current = current.next; nextNode = current.next; } pervious.next = nextNode; length--; return true; }else{ return false; } }
删除指定位置的节点
function removedAt(position){ //判断所给位置是否溢出 if(position > -1 && position < length){ let current = head; let pervious; let nextNode; let i = 0; while(i < position){ pervious = current; current = current.next; nextNode = current.next; } pervious.next = nextNode; length--; return true; }else{ return false; } }实现查询节点的操作
其实查询节点和删除节点差不多,都是通过遍历,找到相应的节点或是相应的位置,然后进行操作,说起来比删除节点还要简单
查询某个位置是哪个节点
function searchElement(element){ //输入元素,找到该元素后返回该元素的位置 if(head != null){ let node = new Node(element); let current; let index = 0; if(head == node){ return 0; }else{ current = head; while(current != node){ current = current.next; index++; } return index; } }else{ return -1; } }
查询某个节点是在哪个位置
function searchPosition(position){ //查找某一个位置的元素是什么 if(position > -1 && position < length){ let i = 0; let current = head; while(i< position){ current = current.next; i++; } return current; }else{ return null; } }思路总结
关于链表的操作还有很多,复杂一点的链表还有双链表(在初始化节点的时候增加一个前节点)和循环链表(尾节点的下一个节点是头节点),这些链表的操作也是可以使用js实现的,这里就不多说了。总结一下,链表的核心在于
链表中节点可看做一个对象,有两个属性值,一个是节点值,一个是指针
链表的增删就是改变指针指向
链表查找时,重点是current = current.next
有关链表的算法题这里总结几道在牛客网上的剑指offer中刷到的几道关于链表的算法题,这些题在笔试中还是很有可能遇到的,接着往下看吧!
1. 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
思路:(1)将链表值从头到尾输出到一个数组中,然后将这个数组进行反转得到ArrayList
(2)使用数组的unshift方法,将链表值倒序放进数组
(3)先使用栈存放顺序遍历的结果,利用栈先进后出的特性,出栈的时候用数组保存
//使用思路2的方法 function Node(element){ this.val = element this.next = null } function logList(head){ if(head != null){ let ArrayList = []; while(head){ ArrayList.unshift(head.element); head = head.next; } return ArrayList; }else{ return []; } }
2. 输入一个链表,输出该链表中倒数第k个结点。
思路:(1)查找倒数第k个节点,可以看做是查找正序第length-k个节点
(2)可以根据第一题的结果取数组的第k-1个节点
//使用思路2 function Node(element){ this.element = element; this.next = null; } function FindKthToTail(head, k) { let array = [] while(head != null){ array.unshift(head) head = head.next; } return array[k-1]; }
3. 输入一个链表,反转链表后,输出新链表的表头。
思路:把倒序后的链表放进一个数组中,然后将这个数组的每一位的next属性指向下一位
function ListNode(x){ this.val = x; this.next = null; } function ReverseList(pHead) { if(pHead){ let arr = []; while(pHead){ arr.unshift(pHead); pHead = pHead.next; } for(let i =0;i< arr.length;i++){ arr[i].next = arr[i+1] } return arr[0] } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/99257.html
摘要:网易跨境电商考拉海购在线笔试现场技术面面。如何看待校招面试招聘,对公司而言,是寻找劳动力对员工而言,是寻找未来的同事。 如何准备校招技术面试 标签 : 面试 [TOC] 2017 年互联网校招已近尾声,作为一个非 CS 专业的应届生,零 ACM 经验、零期刊论文发表,我通过自己的努力和准备,从找实习到校招一路运气不错,面试全部通过,谨以此文记录我的校招感悟。 写在前面 写作动机 ...
摘要:前端面试总结先说背景,本人年月毕业,去年十月校招到今年月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含基础,基础,常见算法和数据结构,框架,计算机网络相关知识,可能有的点很细,有的点很大,参考个人情况进行总结,方便对知识 前端面试总结 先说背景,本人2018年7月毕业,去年十月校招到今年10月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含: ...
摘要:前端面试总结先说背景,本人年月毕业,去年十月校招到今年月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含基础,基础,常见算法和数据结构,框架,计算机网络相关知识,可能有的点很细,有的点很大,参考个人情况进行总结,方便对知识 前端面试总结 先说背景,本人2018年7月毕业,去年十月校招到今年10月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含: ...
摘要:而遍历链表,则是跟着首元素一直遍历至尾元素。单链表代码实现类实现类用来设置链表的节点相关信息本节点信息指向下一个节点的指针类实现类实现的是一些对链表进行操作的方法,包括插入删除节点查找节点等。 单链表初识 链表是由一组节点组合成的集合.每个节点都使用一个对象的引用指向它的后继,指向另一个节点的引用叫做链 数组元素靠他们的位置进行引用,链表元素则是靠相互之间的关系进行引用,在下图中bre...
阅读 2394·2021-11-11 16:54
阅读 1203·2021-09-22 15:23
阅读 3643·2021-09-07 09:59
阅读 1989·2021-09-02 15:41
阅读 3282·2021-08-17 10:13
阅读 3036·2019-08-30 15:53
阅读 1234·2019-08-30 13:57
阅读 1209·2019-08-29 15:16