单链表
function LinkedList() { //需要插入链表的元素 var Node = function(element) { this.element = element;//元素的值 this.next = null;//指向下一个节点项的指针 }; var length = 0;//链表的长度 var head = null;//链表中第一个节点(的引用) //向链表尾部追加元素 this.append = function(element) { var node = new Node(element), current; if(head === null) { //当链表为空时 head = node; } else { //要从第一个元素找起 current = head; //循环链表,直到找到最后一项 while(current.next) { current = current.next; } //把元素插入到链表的末尾 current.next = node; } length++; }; //从链表中根据位置移除元素并返回该元素 this.removeAt = function(position) { if (position > -1 && position < length) { var current = head, previous, index = 0; //移除第一项 if(position == 0) { head = current.next; return current.element; }else{ while(index++ < position){ previous = current;//删除指定位置前的一个元素 current = current.next; } previous.next = current.next; length--; } return current.element; }else{ return null; }; } //从链表中根据值移除元素 this.remove = function(element){ var index = this.indexOf(element); return this.removeAt(index); }; //在任意位置插入一个元素 this.insert = function(position, element) { if(position > -1 && position <= length) { var node = new Node(element), current = head, previous, index = 0; if(position === 0){ //在第一个位置添加 node.next = current; head = node; }else{ while(index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } length++; return true; }else{ return false; } }; //找到并返回一个元素的位置,如果元素不存在,返回-1 this.indexOf = function(element) { var current = head, index = 0; while(current) { if(element === current.element) { return index; } index++; current = current.next; } return -1; }; //判断链表是否为空 this.isEmpty = function() { return length === 0; }; //返回链表的长度 this.size = function() { return length; }; //查看链表中元素的值(转换为字符串) this.toString = function() { var current = head, string = ‘‘; while(current) { string += "," + current.element; current = current.next; } return string.slice(1); }; //返回链表中第一个元素 this.getHead = function() { return head; }; //查看链表(中的元素和指针,以数组形式输出) this.print = function() { var current = head, list = []; while(current) { list.push(current); current = current.next; } return list; }; } var list = new LinkedList(); list.append(5); console.log(list.toString()); console.log(list.print()); console.log(list.indexOf(115)); console.log(list.isEmpty()); console.log(list.size()); console.log(list.getHead()); console.log(list.removeAt(0)); console.log(list.toString()); console.log(list.removeAt(1)); console.log(list.toString()); list.insert(0, 500); console.log(list.toString());
删除链表中重复的结点
//思路 特殊情况:单链表,空链表 新建一个节点newHead,放在头节点前面,当头节点需要被删除时,方便返回结果 pre指针指向前一个节点(初始为newHead)cur指向当前节点(初始为头节点),next指向下一个节点(初始为null) cur不空,cur.next不空时,进入循环,依次比较节点,next保存cur.next 如果cur和next值相等,就进入循环,依次向后查找所有重复元素,然后删除中间所有重复元素(pre.next = next;),cur指向next的当前位置 如果cur和next值不相等,pre和cur依次向后移动,继续比较 最后遍历结束,退出循环,返回头节点:newHead.next function deleteDuplication(pHead) { if (!pHead || !pHead.next) return pHead; let newHead = new ListNode("head"); //新建一个节点 newHead.next = pHead; //充当新的头节点,当head节点被删除时可以返回正确的头节点 let pre = newHead; //pre指向前一个节点 let cur = pHead; //cur指向当前节点 let next = null; //next指向下一个节点 while (cur && cur.next) { //当前节点不空且下一个节点不空时,进入比较循环 next = cur.next; //next存放下个节点的位置 if (next.val === cur.val) { //cur和next值相等 //进入循环向后查找所有重复元素 while (next && next.val === cur.val) { next = next.next; //next后移一位 } //next空或者next和cur值不相等,退出循环 pre.next = next; //删除中间重复的节点 cur = next; //cur指针指向next的位置 } else { //cur和next值不相等 pre = cur; //pre和cur都后移 cur = next; } } return newHead.next; }
回文链表
var isPalindrome = function(head, queue = []) { if (!head) { return true; } queue.push(head.val); let flag = isPalindrome(head.next, queue); return queue.shift() === head.val && flag; }
查找单链表中间节点
<!--查找单链表的中间结点: 定义两个节点k1、k2,k1一次走两步,k2一次走一步, 当k2走到尽头时此时k1所在的位置中间节点。--> <!--输入:[1,2,3,4,5,6] 输出:此列表中的结点 4 (序列化形式:[4,5,6]) 由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。 --> /** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ var middleNode = function(head) { var length = 1, node = head; //测量链表长度 while(node.next !== null){ length++; node = node.next; } //设置中间长度 if(length % 2 === 0){ length = length / 2 + 1; }else{ length = Math.ceil(length / 2); } //重新查找中间长度的节点 node = head; while(length !== 1){ node = node.next; length--; } return node; };
查找单链表倒数第K个节点
//思路 简单思路: 循环到链表末尾找到 length 在找到length-k节点 需要循环两次。 //优化: 设定两个节点,间距相差k个节点,当前面的节点到达终点,取后面的节点。 前面的节点到达k后,后面的节点才出发。 //代码鲁棒性: 需要考虑head为null,k为0,k大于链表长度的情况。 function FindKthToTail(head, k) { if (!head || !k) return null; let front = head; let behind = head; let index = 1; while (front.next) { index++; front = front.next; if (index > k) { behind = behind.next; } } return (k <= index) && behind; }
单链表反转
//以链表的头部节点为基准节点 //将基准节点的下一个节点挪到头部作为头节点 //当基准节点的next为null,则其已经成为最后一个节点,链表已经反转完成 var reverseList = function (head) { let currentNode = null; let headNode = head; while (head && head.next) { currentNode = head.next; head.next = currentNode.next; currentNode.next = headNode; headNode = currentNode; } return headNode; };
数组转链表
function array2list(ary) { if(!ary.length) { return null } var node var head = {value: ary[0], next: null} var pnode = head //pnode变量用来保存前一个节点 for(var i = 1; i < ary.length; i++) { node = {value: ary[i], next:null} pnode.next = node //将前一个节点的next指向当前节点 pnode = node //将node赋值给pnode } return head }
链表转数组
function list2array(head) { if(!head) { return [] } var result = [head.value] var restValues = list2array(head.next) return result.concat(restValues) }
奇偶链表
//题目:给定单链表,将所有奇数节点组合在一起,然后是偶数节点。 //思路 特殊情况,空/单/双链表不需要修改顺序 odd指向奇数节点,even指向偶数节点,evenHead保存第一个偶节点 while循环控制后移,条件:even && odd && even.next,因为even.next需要even存在,所以要先判断even,因为odd.next夹在了中间,所以只需要判断最后的额 even.next存在 odd在even前,所以先移动odd——先改变.next指针,再将odd/even指向.next的位置。 最后连接奇偶链表,返回头节点head var oddEvenList = function(head) { if (!head || !head.next || !head.next.next) { return head; } let odd = head, //odd指向奇数节点 evenHead= head.next, even = head.next; //even指向偶数节点,evenHead保存第一个偶节点 while (even && odd && even.next) { odd.next = even.next; //奇节点指向奇节点 odd = odd.next; //odd指针移向下一个奇节点 even.next = odd.next; //偶节点指向偶节点 even = even.next; //even指针移向下一个奇节点 } odd.next = evenHead; //连接奇偶链表 return head; };
合并两个单链表
//思路: 对两个链表,各自设置一个游标节点指向头节点,对游标节点上的数值进行比较, 小节点的next等于小节点的next和大节点的较小值。数值小的那个拿出来放入到合并链表中, 如此递归。 返回小节点。 //考虑代码的鲁棒性,也是递归的终止条件,两个head为null的情况,取对方节点返回。 function Merge(pHead1, pHead2) { if (!pHead1) { return pHead2; } if (!pHead2) { return pHead1; } let head; if (pHead1.val < pHead2.val) { head = pHead1; head.next = Merge(pHead1.next, pHead2); } else { head = pHead2; head.next = Merge(pHead1, pHead2.next); } return head; }
两个链表的第一个公共节点
//思路 1.先找到两个链表的长度length1、length2 2.让长一点的链表先走length2-length1步,让长链表和短链表起点相同 3.两个链表一起前进,比较获得第一个相等的节点 时间复杂度O(length1+length2) 空间复杂度O(0) function FindFirstCommonNode(pHead1, pHead2) { if (!pHead1 || !pHead2) { return null; } // 获取链表长度 let length1 = getLength(pHead1); let length2 = getLength(pHead2); // 长链表先行 let lang, short, interval; if (length1 > length2) { lang = pHead1; short = pHead2; interval = length1 - length2; } else { lang = pHead2; short = pHead1; interval = length2 - length1; } while (interval--) { lang = lang.next; } // 找相同节点 while (lang) { if (lang === short) { return lang; } lang = lang.next; short = short.next; } return null; } function getLength(head) { let current = head; let result = 0; while (current) { result++; current = current.next; } return result; }
双向链表
// 链表节点 class Node { constructor(element) { this.element = element this.prev = null this.next = null } } // 双向链表 class DoublyLinkedList { constructor() { this.head = null this.tail = null this.length = 0 } // 任意位置插入元素 insert(position, element) { if (position >= 0 && position <= this.length){ const node = new Node(element) let current = this.head let previous = null let index = 0 // 首位 if (position === 0) { if (!head){ this.head = node this.tail = node } else { node.next = current this.head = node current.prev = node } // 末位 } else if (position === this.length) { current = this.tail current.next = node node.prev = current this.tail = node // 中位 } else { while (index++ < position) { previous = current current = current.next } node.next = current previous.next = node current.prev = node node.prev = previous } this.length++ return true } return false } // 移除指定位置元素 removeAt(position) { if (position > -1 && position < this.length) { let current = this.head let previous = null let index = 0 // 首位 if (position === 0) { this.head = this.head.next this.head.prev = null if (this.length === 1) { this.tail = null } // 末位 } else if (position === this.length - 1) { this.tail = this.tail.prev this.tail.next = null // 中位 } else { while (index++ < position) { previous = current current = current.next } previous.next = current.next current.next.prev = previous } this.length-- return current.element } else { return null } } // 其他方法... }
原文地址:https://www.cnblogs.com/huahongcui/p/11520845.html
时间: 2024-10-18 07:25:53