目录
链表
链表是一种物理存储单元上非连续、非顺序的存储结构。链表由一系列结点组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
链表的基本特征
- 每个元素除了存储数据,需要有额外的内存存储一个引用(地址),来指向下一个元素;
- 每个元素占用的内存空间并不要求是连续的;
- 往往使用链表的第一个节点(根节点)来代表整个链表;
- 长度是可变的,随时可以增加和删除元素;
- 插入和删除元素的效率极高;
- 由于要存储下一个元素的地址,会增加额外的内存开销;
- 通过下标查询链表中的某个节点,效率很低,因此链表的下标遍历效率低。
手动实现链表功能
构造链表
/**
* 构造函数 表示链表的一个节点
*
*/
function Node(value){
this.value = value; //节点的数据
this.next = null; //下一个节点的地址
}
遍历链表打印节点
/* 遍历一个链表打印每个节点的数据
*@param root 链表的根节点
*/
function print(root){
/*
第一种:
// var node = root;
while(node){
//如果node有值。打印
console.log(node.value);
node = node.next;
}
*/
//分治法
// var node = root;
if(root){
console.log(root.value); //打印自己
print(root.next);
}
}
计算链表的长度
/***
*计算链表的长度
*/
function count(root){
/**
var count = 0;
var node = root;
while(node){
count ++;
node = node.next;
}
return count;*/
if(!root) return 0; //链表没有节点
return 1 + count(root.next); //1表示根节点占用一个数量
}
通过下标获取链表中的某个数据
/**
* 得到链表某个下标的数据
* @param{*} root
* @param{*} index
*/
function getValue(root,index){
/**
* 判断某个节点是否是我要查找的节点
* @param {*} node 表示某个节点
* @param {*} i 该节点是第几个节点
*/
function _getValue(node,i){
if(!node) return null;
if(i == index) return node;
return _getValue(node.next,i+1);
}
return _getValue(root,0);
}
通过下标设置链表中的某个数据
/**
* 设置链表某个位置的数据
* @param {*} root
* @param {*} index
* @param {*} value
*/
function setValue(root,index,value){
function _setValue(node,i){
if(!node) return ;
if(i == index){
node.value = value;
}else{
_setValue(node.next,i+1);
}
}
_setValue(root,0);
}
在链表某一个节点之后加入一个新节点
/**
* 在链表的某个节点之后加入一个新的节点
* @param {*} node
* @param {*} index
* @param {*} newValue
*/
function insertAfter(node,newValue){
var newNode = new Node(newValue);
newNode.next = node.next;
node.next = newNode;
}
在链表末尾加入一个新节点
/**
* 在链表的末尾加入一个新的节点
* @param {*} node
* @param {*} newValue
*/
function push(root,newValue){
if(!root.next){
var newNode = new Node(newValue);
root.next = newNode;
}else{
push(root.next,newValue);
}
}
删除一个节点
方法1:
/**
* 通过下标删除某一个节点
* @param {*} root
* @param {*} index
*/
function removeNode(root,index){
function _remove(root,i){
if(!root || root.next == null) return null;
if(i == index-1){
root.next = root.next.next;
}else{
_remove(root.next,i+1);
}
}
return _remove(root,0);
}
方法2:
/**
* 通过值删除一个节点
* @param {*} root
* @param {*} nodeValue
*/
function removeNode(root,nodeValue){
if(!root || root.next == null) return;
if(root.next.value == nodeValue){
root.next = root.next.next;
}else{
removeNode(root.next,nodeValue);
}
}
链表倒序
/**链表倒叙
* 给定一个链表,返回一个倒序后的链表
* @param {*} root
*/
function reverse(root){
if(root.next == null) return;
if(root.next.next == null){
var temp = root.next;
root.next.next = root;
root.next = null;
return temp;
}else{
var temp = reverse(root.next);
root.next.next = root;
root.next = null;
return temp;
}
}