# 链表
## LinkedList
#### 查找节点操作
~~~
function find ( item ) {
var currNode = this.head;
while ( currNode.element != item ){
currNode = currNode.next;
}
return currNode;
}
~~~
#### 插入节点操作
> 将新节点的 next 属性设置为后面节点的 next 属性对应的值,然后设置后面节点的 next 属性指向新的节点
>
~~~
function insert ( newElement , item ) {
var newNode = new Node( newElement );
var currNode = this.find( item );
newNode.next = currNode.next;
currNode.next = newNode;
}
~~~
#### 删除节点操作
首先需要两步,查找待删除节点的前一个节点,找到后将前一个节点的next指向待删除节点的next指向。
首先,查找待删除的前一个节点。
~~~
function findPrev( item ) {
var currNode = this.head;
while ( !( currNode.next == null) && ( currNode.next.element != item )){
currNode = currNode.next;
}
return currNode;
}
~~~
接下来删除节点。
~~~
function remove ( item ) {
var prevNode = this.findPrev( item );
if( !( prevNode.next == null ) ){
prevNode.next = prevNode.next.next;
}
}
~~~
## 双向列表
相比于单向列表,双向列表增加previous属性。
#### 双向列表插入节点
~~~
function insert ( newElement , item ) {
var newNode = new Node( newElement );
var currNode = this.find( item );
newNode.next = currNode.next;
newNode.previous = currNode;
currNode.next = newNode;
}
~~~
#### 双向列表删除节点
~~~
function remove ( item ) {
var currNode = this.find ( item );
if( !( currNode.next == null ) ){
currNode.previous.next = currNode.next;
currNode.next.previous = currNode.previous;
currNode.next = null;
currNode.previous = null;
}
}
~~~
## 循环链表
> 循环链表和单链表相似,节点类型都是一样,唯一的区别是,在创建循环链表的时候,让其头节点的 next 属性执行它本身,即
`head.next = head;`
## 相关题
#### 链表的第k个节点
~~~
function FindKthToTail(head, k) {
// write code here
if (head == null || k <= 0) return null;
var prev = head;
var tail = head;
for (var index = 0; index < k - 1; index++) { //截取长度为k的一段,prev到tail长度为k
if (tail.next != null) {
tail = tail.next;
} else {
return null;
}
}
while (tail.next != null) { //向后移动,直到tail指向链表最后一个 prev就是倒数k个
prev = prev.next;
tail = tail.next;
}
return prev;
}
~~~
#### 逆转链表
~~~
function ReverseList(pHead) { //a->b->c->null
// write code here
let current = null;
let second = null;
if (pHead === null || pHead.next === null) { return pHead }
while (pHead !== null) {
second = pHead.next; //second = a.next = b; second = b.next = c;
pHead.next = current; //a.next = null; b.next = a;
current = pHead; // current = a; current = b;
pHead = second; //pHead = b; pHead = c;
}
return current;
}
~~~
- html
- 冒泡/捕获/委托
- 前端路由
- Dom
- 创建节点API
- 页面修改型API
- 节点查询型API
- 节点关系型API
- 元素属性API
- DOM事件
- classList
- 性能优化
- 节流防抖
- localStorage sessionStorage
- BOM
- meta
- data属性
- js实现拖拽
- html5
- 关于meta
- 轮播图
- js实现拖放
- 电话号inputFormater
- js
- es6
- promise
- iterator
- generator
- async
- proxy
- Set
- Map
- Object的扩展
- String
- Iterator
- Symbol
- 解构赋值
- 函数式编程
- module
- 基本数据类型
- 数组相关codings
- for of/for in
- this
- call bind apply
- 闭包
- 作用域
- prototype与继承
- 深浅拷贝
- setTimeOut/setInterval
- 垃圾处理机制
- 设计模式
- 观察者模式
- 单例模式
- 策略模式
- RegExp
- with
- 其他玩意
- Error/Stack Trace
- 面向对象
- css
- 回流重绘
- %取值
- 属性继承/属性优先级
- flex
- BFC
- 盒模型
- 设置css的方法
- 定位机制
- 块级/行内元素
- hack和一些别的玩意
- css动画
- 几个布局
- 画图形
- css3
- animation对比transform
- 点击不同图片区域跳转不同
- css选择器性能问题
- vh rem em
- css选择器
- 伪类伪元素
- css匹配原理
- 数据结构与算法
- 数据结构
- 树
- 链表
- 栈和队列
- 排序
- 归并排序
- 插入排序
- 选择排序
- 冒泡排序
- 快速排序
- 递归
- 回溯法
- 搜索算法
- 动态规划
- http
- 跨域问题
- CORS
- GET/POST
- ajax
- ajax上传文件
- http缓存
- https
- TCP/UDP
- cookie/session
- http2.0
- spdy
- websocket
- React
- redux
- 生命周期
- 虚拟dom与diff
- 双向数据绑定
- mvvm
- setState
- contextApi props reudx
- 高阶组件
- react-redux
- Fiber
- react-router
- 受控/非受控组件
- 待整理
- webpack
- loader实现
- 前端安全
- 移动端适配
- Vue
- 传值
- 其他