前言:今天看了一手数据结构的双链表, 双链表的定义呢,就是说节点有两个指针,即一个pre,一个next。pre指向其前驱,next指向其后续,所以叫做双链表呐(这名字多么科学^_^)
正文:说正事,实现在双链表中将当前节点【叫他原节点】元素向前、向后移动n位。
思路:
向前移动n位:找到当前元素的节点,然后在找到向前移动n+1位后的节点【叫他q节点】,剩下的就是将原节点的从原来的位置移出,然后将它加入到q节点的下一位即可。(向后移动n位也是同样的思想,看下边code可否?)
直接上代码
function Node(element) {
this.element = element
this.next = null //指向后继节点
this.previous = null //指向前驱节点
}
// DoubleList提供对链表进行操作的方法,他的唯一属性就是使用Node对象来保存该链表的头结点
function DoubleList() {
this.head = new Node('head')
// head节点的next属性初始化为null,当有新元素插入时,next会指向新的元素
this.find = find
this.insert = insert
this.display = display
this.advance = advance //advance(ele,n),将目标元素对应的节点向前移动n个位
this.back = back //back(ele,n),将目标元素对应的节点向前移动n个位
}
function find(ele) {
// 遍历链表,查找给定的数据后返回包含给定数据的节点
var currNode = this.head //从头结点查找起
while (currNode.element != ele) {
currNode = currNode.next
}
return currNode
}
// 在ele元素对应的节点后插入newEle对应的节点
function insert(newEle, ele) {
var newNode = new Node(newEle)
var current = this.find(ele) //找到插入节点的位置
newNode.next = current.next //新节点指向插入位置的后一个
newNode.previous = current
current.next = newNode //插入位置的前一个节点的next指向当前位置节点
}
function display() {
const res = []
var current = this.head.next
while (current !== null) {
res.push(current.element)
current = current.next
}
console.log(res.toString())
}
// 当前元素向前移动n个位置
function advance(ele, n) {
// 实现思路:1. 找到当前的节点current,
const current = this.find(ele)
if (n <= 0 || isNaN(n)) {
console.log('传入数字不合法')
return false //传入位置不合法
}
if (!current || !current.previous) {
console.log('你这个元素根本没有或者处在第一个位置,你还想向前移动,老哥!')
return false //操作当然不成功拉
}
let pn = current //暂存当前节点
// 2. 然后在依次遍历到要移动到的节点位置前一个节点pn
while (pn.previous && n + 1 > 0) {
pn = pn.previous
n--
}
if (!current.next) {
// 如果当前的下一个节点为空,则直接将前一个节点指向null
current.previous.next = null
} else {
// 3. 然后将current.next.previous = current.previous //将当前节点的下一个节点指向当前节点的前一个节点
current.next.previous = current.previous
current.previous.next = current.next
}
// 再current.previous.next = current.next //将当前节点的上一个节点指向当前节点的下一个节点
// (这两步类似于删除当前节点,但是是‘类似’)因为我并没有释放当前节点
// 4. 将pn.next.previous = current //将插入位置的previous指向当前节点
// 再current.next = pn.next,current.previous=pn,pn.next = current
current.next = pn.next
pn.next.previous = current
current.previous = pn
pn.next = current
return true
}
// 当前元素向后移动n个位置
function back(ele, n) {
// 思路:
//1.找到元素为ele的节点current
const current = this.find(ele)
let temp = current //便于遍历
if (n <= 0 || isNaN(n)) {
console.log('传入数字不合法')
return false //传入位置不合法
}
if (!current || !current.next) {
console.log(
'你要移动的元素根本不存在或处于最后一个了,还怎么向后移动,老兄'
)
return false //so fail
}
// 2.找到移动向后移动n个的位置的节点
while (temp.next && n > 0) {
temp = temp.next
n--
}
// 将current的上一个节点指向current的下一个节点,
// 将current的下一个节点的previous指向current的上一个节点(这两步是为了以移出当前节点的位置)
current.previous.next = current.next
current.next.previous = current.previous
// 找到后呢,看下找到的节点.next是不是为null
if (!temp.next) {
//如果找到的下一个节点为空,则直接将当前节点插入都尾部即可
current.next = null
temp.next = current
current.previous = temp
} else {
current.next = temp.next
temp.next.previouse = current
temp.next = current
current.previous = temp
}
return true
}
var dlist = new DoubleList()
// insert(x2,x1)在元素为x1对应的节点后插入元素为x2的对应节点
dlist.insert('jake1', 'head')
dlist.insert('jake2', 'jake1')
dlist.insert('jake3', 'jake2')
dlist.insert('jake4', 'jake3')
dlist.display() //jake1,jake2,jake3,jake4
// 将jake4向前移动1个位置
dlist.advance('jake4', 1)
dlist.display() //jake1,jake2,jake4,jake3
// 然后将jake4向后移动1个位置,回到原来位置
dlist.back('jake4', 1)
dlist.display() //jake1,jake2,jake3,jake4