We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
可以看:https://www.zhihu.com/topic/19649942/intro
链表(Linked list)是一种常见的基础数据结构,是一种线性表,是一种物理存储单元上非连续、非顺序的存储结构。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括存储数据元素的数据域和存储下一个结点地址的指针域两个部分。 相比于线性表顺序结构,操作复杂。数据元素的逻辑顺序也是通过链表中的指针链接次序实现的。
链表分为:单(向)链表、循环链表、双向链表。虽然有三种不同的链表,但是其中心思想(存储的逻辑结构)是一样的。
从网上盗三张图来分别展示下
单向链表:
双向链表:
循环链表:
以单向链表为例:
如此,我可以先实现一个节点类:
function Node (ele) { this.data = ele; this.next = null; }
如何将节点连接起来构成链表呢? 这时候我需要有一个类,用于维护链表的插入、删除等方法。当然,需要先给它一个头节点。
function LinkedList () { this.head = new Node('head'); }
头节点有了,接下来如何去插入新节点使其连接呢? 这时候的头节点的next指向的是null,我需要在插入方法中去改变next指向。 我肯定是要插入Node节点对象的,同时头节点的next要指向这个新节点,那么初步实现下:
null
Node
LinkedList.prototype.insert = function (ele) { this.head.next = new Node(ele) }
但是,问题来了! 我这个insert里面只改变了头节点next指向,如果我想插入第二个甚至更多节点,目前的方法根本不满足!!!所以,我需要记住每个插入的节点。 并且,链表是可以不按顺序插入的,那我必须得知道新节点要插到哪个位置(哪个节点后面),所以我必须找到该节点。 那么插入新节点时,不仅要将新节点数据传入,同时也要将需要插入新节点的前一个节点数据传入才行。
insert
改写下insert:
LinkedList.prototype.insert = function (ele, prev) { var curr = this.head while (curr.next && curr.data !== prev) { curr = curr.next } if (curr.data !== prev) { throw new Error('请在已有节点后插入') } var newNode = new Node(ele) newNode.next = curr.next curr.next = newNode } // 测试下 var l = new LinkedList() l // LinkedList{head: {data: 'head', next: null}} l.insert(1, 1) // Error l.insert('first', 'head')
接下来,需要实现删除操作。删除的话需要知道被删除节点的前后节点才行,那么首先需要去找前一个节点,附上代码:
LinkedList.prototype.remove = function (item) { var curr = this.head while (curr.next && curr.next.data !== item) { curr = curr.next } if (!curr.next && curr.data !== item) { throw new Error('请删除已有节点') } var removeNode = curr.next curr.next = removeNode.next } // 测试下 var l = new LinkedList() l // LinkedList{head: {data: 'head', next: null}} l.insert('first', 'head') l.remove('first') l.remove('first') // Error
基本上单向链表算是实现了,最终代码:
function Node (ele) { this.data = ele; this.next = null; } function LinkedList () { this.head = new Node('head'); } LinkedList.prototype.insert = function (ele, prev) { var curr = this.head while (curr.next && curr.data !== prev) { curr = curr.next } if (curr.data !== prev) { throw new Error('请在已有节点后插入') } var newNode = new Node(ele) newNode.next = curr.next curr.next = newNode } LinkedList.prototype.remove = function (item) { var curr = this.head while (curr.next && curr.next.data !== item) { curr = curr.next } if (!curr.next && curr.data !== item) { throw new Error('请删除已有节点') } var removeNode = curr.next curr.next = removeNode.next }
双向链表其实就是在单向链表基础上加一个指向前节点的链接,直接放书上的代码吧:
function Node (element) { this.element = element this.next = null this.previous = null } function LList () { this.head = new Node('head') this.find = find this.insert = insert this.display = dispay this.remove = remove this.findLast = findLast this.dispReverse = dispReverse } function dispReverse () { var cuuNode = this.head currNode = this.findLast() while (!(currNode.previous === null)) { currNode = currNode.previous } } function findLast () { var currNode = this.head while (!(currNode.next === null)) { currNode = currNode.next } return currNode } function remove () { var currNode = this.head if (!(currNode.next === null)) { currNode.previous.next = currNode.next currNode.next.previous = currNode.previous currNode.next = null currNode.previous = null } } function display () { var currNode = this.head while (!(currNode.next === null)) { currNode = currNode.next } } function find (item) { var currNode = this.head while (currNode.element !== item) { currNode = currNode.next } return currNode } function insert (newElement, item) { var newNode = new Node(newElement) var current = this.find(item) newNode.next = current.next newNode.previous = current current.next = newNode }
循环链表和单向链表相似,节点类型都是一样的。唯一的区别是,在创建循环链表时,让其头节点的next属性指向它本身,即:
head.next = head
这种行为会传导至链表的每个节点,使得每个节点的next属性都指向链表的头节点。换句话说,链表的尾节点指向头节点,形成一个循环链表。
https://zhuanlan.zhihu.com/p/29627391 http://c.biancheng.net/view/3336.html
The text was updated successfully, but these errors were encountered:
No branches or pull requests
什么是链表?
可以看:https://www.zhihu.com/topic/19649942/intro
链表(Linked list)是一种常见的基础数据结构,是一种线性表,是一种物理存储单元上非连续、非顺序的存储结构。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括存储数据元素的数据域和存储下一个结点地址的指针域两个部分。 相比于线性表顺序结构,操作复杂。数据元素的逻辑顺序也是通过链表中的指针链接次序实现的。
链表分为:单(向)链表、循环链表、双向链表。虽然有三种不同的链表,但是其中心思想(存储的逻辑结构)是一样的。
从网上盗三张图来分别展示下
单向链表:
![](https://camo.githubusercontent.com/5b20dc9dd764cebaf69516c0b8864a30c47a447d81b327cbfbd8253e73802f12/68747470733a2f2f706963342e7a68696d672e636f6d2f76322d36363663316538343431396138306531303733353637663261353032656266665f622e706e67)
双向链表:
![](https://camo.githubusercontent.com/6de5bd89fbc6288d907e052fd1c242b4fd71cea84aafc147b4c771c0d1aba440/68747470733a2f2f706963312e7a68696d672e636f6d2f76322d61623966363434666535376562633635616532323236333139356639393732385f622e706e67)
循环链表:
![](https://camo.githubusercontent.com/a0f704e09cb4cc879a4cd3935637c603baaeee1b2425ca6dcfb7caafb38c7f61/68747470733a2f2f706963322e7a68696d672e636f6d2f76322d34613438633439636262626261613639616530313435616330653238313735315f622e6a7067)
如何实现?
以单向链表为例:
如此,我可以先实现一个节点类:
如何将节点连接起来构成链表呢?
这时候我需要有一个类,用于维护链表的插入、删除等方法。当然,需要先给它一个头节点。
头节点有了,接下来如何去插入新节点使其连接呢?
这时候的头节点的next指向的是
null
,我需要在插入方法中去改变next指向。我肯定是要插入
Node
节点对象的,同时头节点的next要指向这个新节点,那么初步实现下:但是,问题来了!
我这个
insert
里面只改变了头节点next指向,如果我想插入第二个甚至更多节点,目前的方法根本不满足!!!所以,我需要记住每个插入的节点。并且,链表是可以不按顺序插入的,那我必须得知道新节点要插到哪个位置(哪个节点后面),所以我必须找到该节点。
那么插入新节点时,不仅要将新节点数据传入,同时也要将需要插入新节点的前一个节点数据传入才行。
改写下insert:
接下来,需要实现删除操作。删除的话需要知道被删除节点的前后节点才行,那么首先需要去找前一个节点,附上代码:
基本上单向链表算是实现了,最终代码:
双向链表其实就是在单向链表基础上加一个指向前节点的链接,直接放书上的代码吧:
循环链表和单向链表相似,节点类型都是一样的。唯一的区别是,在创建循环链表时,让其头节点的next属性指向它本身,即:
这种行为会传导至链表的每个节点,使得每个节点的next属性都指向链表的头节点。换句话说,链表的尾节点指向头节点,形成一个循环链表。
参考
https://zhuanlan.zhihu.com/p/29627391
http://c.biancheng.net/view/3336.html
The text was updated successfully, but these errors were encountered: