JS数据结构--双向链表--常见操作

一.单向链表的缺点

在单向链表中,可以轻松的从头遍历到尾部,到达下一个节点,但是想回到前一个节点是很难的

二.双向链表

  • 既可以从头遍历到尾,又可以从尾遍历到头
  • 链表相连的过程是双向的
  • 一个节点既有向前连接的引用,也有一个向后连接的引用
  • 双向链表可以解决单向链表的缺点

三.双向链表的缺点

  • 每次在插入或删除某个节点时,需要处理四个引用,而不是两个,实现起来相对困难
  • 与单向链表相比,占用内存空间更大

四.双向链表的特点

  • 使用一个head和一个tail分别指向头部和尾部节点
  • 每个节点都由三部分组成:前一个节点的指针(prev),保存的元素(item),后一个节点的指针(next)
  • 双向链表的第一个节点的prev为null
  • 双向链表的最后的节点的next为null

五.封装双向链表

function DoublyLinkedList(){
	// 内部类:节点类
	function Node(data){
		this.data = data
		this.prev = null
		this.next = null
	}
	// 属性
	this.head = null
	this.tail = null
	this.height = 0
}

六.双向链表的基本操作

  • append方法:在链表的尾部插入节点
DoublyLinkedList.prototype.append = function(data){
	var newNode = new Node(data)
	if(this.length == 0){
		this.head = newNode
	}else{
		var current = this.head
		while(current.next){
			current = current.next
		}
		current.next = newNode
	}
	this.length += 1
}
  • 链表转换成字符串:forwardString方法和backwardString方法
//forwardString方法
DoublyLinkedList.prototype.forwardString = function(){
	var current = this.head
	var resultString = ''
	// 依次向前遍历,获取每一个节点
	while(current){
		resultString += current.data + ''
		current = current.prev
	}
	return resultString
}

//backwardString方法
DoublyLinkedList.prototype.backwardString = function(){
	var current = this.head
	var resultString = ''
	// 依次向后遍历,获取每一个节点
	while(current){
		resultString += current.data + ''
		current = current.next
	}
	return resultString
}
  • insert方法:给定位置插入节点
DoublyLinkedList.prototype.insert = function(position,data){
	// 越界判断
	if(position < 0 || position > this.length) return false
	// 根据data创建新节点
	var newNode = new Node(data)
	// 判断原来的链表是否为空
	if(this.length == 0){
		this.head = newNode
		this.tail = newNode
	}else{
	// 1.判断position是否为0
	if(position == 0){
		this.head.prev = newNode
		newNode.next = this.head
		this.head = newNode
	}else if(position == this.length){
	// 节点插入在链表尾部
		this.tail.next = newNode 
		newNode.prev = this.tail
		this.tail = newNode
	}else{
	// 节点插入在中间位置
		var current = this.head
		var index = 0
		while(index++ < position){
			current = current.next
		}
		newNode.next = current
		newNode.prev = current.prev
		current.prev.next = newNode
		current.prev = newNode
	}
		this.length += 1
		return true
	}
}
  • get方法:获取给定位置的数据
// 方法1(普通方法)
DoublyLinkedList.prototype.get = function(position){
	// 越界判断
	if(position < 0 || position >= this.length) return false
	// 获取元素
	var current = this.head
	var index = 0
	while(index++ < position){
		current = current.next
	}
	return current.data
}

// 方法2
DoublyLinkedList.prototype.get = function(position){
	 // 越界判断
	 // this.length / 2 > position: 从头向后遍历
	 // this.length / 2 < position: 从后向前遍历
	 // 从后向前遍历的操作:
	 var current = this.tail
	 var index = this.length - 1 // 链表的长度-1
	 while(index-- > position){
	 	current = current.prev
	 }
	 return current.data
}
  • indexOf方法:返回元素在链表中的索引,若链表中没有该元素则返回-1
DoublyLinkedList.prototype.indexOf = function(data){
	// 定义变量
	var current = this.head
	var index = 0
	// 查找和data相同的节点
	while(current){
		if(current.data == data){
			return index
		}else{
			current = current.next
			index++
		}
	}
	return -1
}
  • update方法:修改数据元素
DoublyLinkedList.prototype.update = function(position,newData){
	// 越界判断
	if(position < 0 || position >= this.length) return false
	// 修改元素
	var current = this.head
	var index = 0
	while(index++ < position){
		current = current.next
	}
	current.data = newData
	return true
}
  • removeAt方法:删除链表中的节点
DoublyLinkedList.prototype.removeAt = function(position){
	//越界判断
	if(position < 0 || position >= this.length) return null
	//判断是否只有一个节点
	var current = this.head
	if(this.length == 1){
		this.head = null 
		this.tail = null
	}else{
		// 判断是否删除的是第一个节点
		if(position == 0){
			this.head.next.prev = null
			this.head = this.head.next
		}
	}else if(position == this.length - 1){
	// 删除最后一个节点
		current = this.tail
		this.tail.prev.next = null 
		this.tail = this.tail.prev
	}else{
		var index = 0
		while(index++ < position){
			current = current.next
		}
		current.prev.next = current.next
		current.next.prev = current.prev
	}
	length -= 1
	return current.data
}
  • remove方法:给定具体数据,删除链表中对应的节点
DoublyLinkedList.prototype.remove = function(data){
	// 根据data获取下标值
	var index = this.indexOf(data)
	// 根据index删除对应位置的节点
	return this.removeAt(index)
}
  • isEmpty方法:判断链表是否为空
DoublyLinkedList.prototype.isEmpty = function(){
	return this.length == 0
}
  • size方法
DoublyLinkedList.prototype.size = function(){
	return this.length
}
  • getHead方法:获取链表的第一个元素
DoublyLinkedList.prototype.getHead = function(){
	return this.head.data
}
  • getTail方法:获取链表的最后一个元素
DoublyLinkedList.prototype.getTail = function(){
	return this.tail.data
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值