<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style></style>
</head>
<body>
<script>
// 封装双向链表类
function DoublyLinkedList() {
// 内部类:用来创建链表节点
function Node(data) {
this.data = data
this.prev = null //上指针 指向上一个节点
this.next = null //下指针 指向下一个节点
}
// 定义属性
this.length = 0
this.head = null //头结点
this.tail = null //尾结点
// 定义相关方法
// 1.在尾部追加数据
DoublyLinkedList.prototype.append = function (data) {
// 1.创建新的节点
var newNode = new Node(data)
// 2.判断是否为空链表
if (this.head == null) {
this.head = newNode
this.tail = newNode
} else {
this.tail.next = newNode
newNode.prev = this.tail
this.tail = newNode
}
// 3.length+1
this.length += 1
}
// 2.转为字符串的方法 方便我们调试alert输出 否则会显示undefined
// 2.1从前往后转为字符串
DoublyLinkedList.prototype.forwardString = function () {
var current = this.head
var forwardStr = ""
while (current) {
forwardStr += "," + current.data
current = current.next
}
return forwardStr.slice(1)
}
// 2.2反向遍历的方法 从后往前
DoublyLinkedList.prototype.reverseString = function () {
var current = this.tail
var reverseStr = ""
while (current) {
reverseStr += "," + current.data
current = current.prev
}
return reverseStr.slice(1)
}
// 2.3实现toString方法
DoublyLinkedList.prototype.toString = function () {
return this.forwardString()
}
// 3.根据索引插入元素的方法
DoublyLinkedList.prototype.insert = function (position, data) {
// 1.判断是否越界
if (position < 0 || position > this.length) {
return false
}
// 2.创建新的节点
var newNode = new Node(data)
// 3.判断原来的链表是否为空链表
if (this.length == 0) {
this.head = newNode //头指针指向新的节点
this.tail = newNode //尾指针指向新的节点
} else {
if (position == 0) { //3.1判断插入位置是否为第一个
this.head.prev = newNode //原来头节点的上一个节点为新节点
newNode.next = this.head //新节点的下一个节点为原来的头结点
this.head = newNode //头结点为新的节点
} else if (position == this.length) { //3.2判断插入位置是否为最后一个
newNode.prev = this.tail //新节点的上节点为之前的尾结点
this.tail.next = newNode //之前尾结点的下节点为新节点
this.tail = newNode //新节点成为尾结点
} else { //3.3插入位置在中间
var current = this.head
var index = 0
while (index++ < position) {
current = current.next
}
//当循环终止时就找到了目标节点位置(position索引处的节点)
newNode.next = current //新节点的下节点为目标节点
newNode.prev = current.prev //新节点的上节点为目标节点的上节点
current.prev.next = newNode //目标节点的上节点的下节点为新节点
current.prev = newNode //目标节点的上节点为新节点
}
}
// 4.长度+1
this.length += 1
}
// 4.根据索引获取元素的方法
DoublyLinkedList.prototype.get = function (position) {
// 1.判断是否越界
if (position < 0 || position >= this.length) {
return null
}
if (this.length / 2 >= position) { //2.从前往后查找
var current = this.head
var index = 0
while (index++ < position) {
current = current.next
}
// 循环结束时已找到目标索引
return current.data
} else { //3.从后往前查找
var current = this.tail
var index = this.length - 1
while (index-- > position) {
current = current.prev
}
// 循环结束时已找到目标索引
return current.data
}
}
// 5.根据元素返回索引的方法
DoublyLinkedList.prototype.indexOf = function (data) {
// 1.定义变量
var current = this.head
var index = 0
// 2.循环查找和data相同的节点
while (current) {
if (current.data == data) {
return index
}
current = current.next
index += 1
}
return -1 //循环结束说明没有找到和data相同的节点 返回-1
}
// 6.根据索引修改元素的方法
DoublyLinkedList.prototype.update = function (position, newData) {
// 1.判断是否越界
if (position < 0 || position >= this.length) return false
if (this.length / 2 >= position) { //2.从前往后查找
var current = this.head
var index = 0
while (index++ < position) {
current = current.next
}
// 循环结束时已找到目标索引
current.data = newData
} else { //3.从后往前查找
var current = this.tail
var index = this.length - 1
while (index-- > position) {
current = current.prev
}
// 循环结束时已找到目标索引
current.data = newData
}
}
// 7.根据索引删除元素的方法
DoublyLinkedList.prototype.removeAt = function (position) {
// 1.判断是否越界
if (position < 0 || position >= this.length) return null
// 2.判断是否只有一个节点
var current = this.head
if (this.length == 1) {
this.head = null
this.tail = null
} else {
if (position == 0) { //判断是否删除第一个节点
this.head.next.prev = null //头结点的下节点的上节点为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 //目标节点的下节点 的上节点 为目标节点的上节点
}
}
// 3.长度-1
this.length -= 1
return current.data
}
// 8.根据元素删除元素的方法
DoublyLinkedList.prototype.remove = function (data) {
// 1.根据data获取索引值
var index = this.indexOf(data)
// 2.根据index删除对应的节点
return this.removeAt(index)
}
// 9.判断链表是否为空
DoublyLinkedList.prototype.isEmpty = function () {
return this.length == 0
}
// 10获取链表长度
DoublyLinkedList.prototype.size=function (){
return this.length
}
// 11.获取链表的第一个元素
DoublyLinkedList.prototype.getHead=function (){
return this.head.data
}
// 12.获取链表的最后一个元素
DoublyLinkedList.prototype.getTail=function(){
return this.tail.data
}
}
// 方法测试
var list = new DoublyLinkedList()
// 1.测试末尾追加方法
list.append(10)
list.append(20)
list.append(30)
alert(list)
// 2.测试转字符串的方法
// alert(list.forwardString())
// alert(list.reverseString())
// 3.测试根据索引插入元素的方法
// list.insert(0, 00)
// list.insert(1, 11)
// list.insert(2, 22)
// alert(list)
// 4.测试获取目标索引的元素
// alert(list.get(0))
// alert(list.get(4))
// 5.测试根据元素获取索引的方法
// alert(list.indexOf(10))
// alert(list.indexOf(30))
// 6.测试根据索引修改元素的方法
// list.update(0,'000')
// list.update(1,'111')
// list.update(2,'222')
// alert(list)
// 7.测试根据索引删除元素的方法
// list.removeAt(0)
// list.removeAt(0)
// alert(list)
// 8.测试根据元素删除元素的方法
// list.remove('10')
// list.remove('20')
// alert(list)
// 9.测试链表是否为空的方法
// alert(list.isEmpty())
// 10.测试获取链表长度的方法
// alert(list.size())
// 11.测试获取链表第一个元素的方法
// alert(list.getHead())
// 12.测试获取链表最后一个元素的方法
// alert(list.getTail())
</script>
</body>
</html>
JavaScript 数据结构-双向链表
最新推荐文章于 2024-10-12 16:35:22 发布