数据结构(链表实现篇)

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是经过链表中的指针连接次序实现的。链表由一系列结点(链表中每个元素称为结点)组成,结点能够在运行时动态生成。链表的节点由数据和一个或多个指针域组成。链表在插入和删除操做上的算法复杂O(1),而数组的插入和删除的最大复杂度是O(n)。可是数组在查找比链表更优越。node

单链表结构示意图

chain.png

链表结构分析

单链表由一个个数据域和指针域组成的节点组成的链式结构,单链表只有指向下一个节点的指针域;而双向链表由一个指向上一个节点和一个指向下一个节点的指针加数据域组成的链式结构。循环链表就是最后一个节点的指针不是指向null;而是指向head头部虚拟节点。以下图所示:算法

introduce.png

实现单链表结构的功能

  • append(node):append是往链表尾部添加节点操做,其中node是须要加入链表的元素,返回操做成功与否布尔值。

add.png

  • remove(index):delete移除第index个元素操做,返回移除的移除元素。

delete.png

  • size():获取栈中的链表节点数量,返回一个数字。数组

  • isEmpty():判断链表是否为空,返回一个布尔值。bash

  • find(head,currentIndex,index):查找索引为index的节点,返回该节点。数据结构

find.png

ES6 单链表结构代码

class Node {
	constructor(data, next) {
		this.data = data;
		this.next = next;
	}
}

class LinkChain {
	constructor() {
		this.header = new Node(null, null);
		this.size = 0;
	}
	find(header, currentIndex, index) {
		if (currentIndex === index) {
			return header;
		}
		return this.find(header.next, ++currentIndex, index);
	}
	append(data, index) {
		const prevNode = this.find(this.header, 0, index);
		prevNode.next = new Node(data, prevNode.next);
		this.size++;
		return true;
	}
	insert(node, index) {
		return this.append(data, index);
	}
	remove(index) {
		const prevNode = this.find(this.header, 0, index);
		const node = prevNode.next;
		prevNode.next = node.next;
		node.next = null;
		this.size--;
		return node;
	}
	length() {
		return thid.size;
	}
	isEmpty() {
		return this.size === 0;
	}
	toString() {
		console.log(JSON.stringify(this));
	}
}

const chain = new LinkChain();
chain.append('kiwis', 0);
chain.append('kiwis1', 1);
chain.append('kiwis2', 2);
chain.toString();
复制代码

ES5 单链表结构代码

经过ES5把功能函数能够绑定在对象的实例上,也能够把功能函数加在函数的原型链上app

function Node(data,next){
	this.data = data;
	this.next = next;
}
function LinkChain(){
	this.head = new Node(null,null);
	this.length = 0;
}
LinkChain.prototype.append = function(data,index){
	var prevNode = this.find(this.head,0,index);
	prevNode.next = new Node(data,prevNode.next)
	this.length++;
	return true;
}
LinkChain.prototype.remove = function(index){
	var prevNode = this.find(this.head,0,index);
	var Node = prevNode.next;
	prevNode.next = Node.next;
	Node.next = null;
	this.length--;
	return Node;	
}
LinkChain.prototype.size = function(){
	return this.length;
}
LinkChain.prototype.isEmpty = function(){
	return this.length === 0;
}
LinkChain.prototype.insert = function(node,index){
	return this.append(node,index);
}
LinkChain.prototype.find = function(head,currentIndex,index){
	if(currentIndex === index){
		return head;
	}
	return this.find(head.next,++currentIndex,index);
}

复制代码

双向链表

  • remove():移除节点操做,双向链表由于具备一个向上和一个向下的指针域,因此删除的时候须要解除两个指针的指向引用
    delete.png
  • insert(node,index):添加节点,双向链表由于具备一个向上和一个向下的指针域,因此添加的时候须要解除原来两个指针的指向引用,再进行添加指针指向操做。
    insert

双向链表其余操做与单链表操做相相似,下面ES6实现双向链表的实现:函数

class Node{
	constructor(data,next=null,prev=null){
		this.data = data;
		this.next = next;
        this.prev = prev;
	}
}
class LinkChain{
	constructor(){
		this.head = new Node(null,null,null);
		this.tail = new Node(null,null,null);
		this.length = 0;
	}
	find(head,currentIndex,index){
		if(currentIndex === index){
			return head;
		}
		return this.find(head.next,++currentIndex,index);
	}
	append(node,index){
		const prevNode = this.find(this.head,0,index);
		node.next = prevNode .next; 
        prevNode .next.prev  =  node;
		prevNode.next = node;
        node.prev = prevNode;
		this.length++;
		return true;
	}
	insert(node,index){
		return this.append(node,index);
	}
	remove(index){
		const prevNode = this.find(this.head,0,index);
		const Node = prevNode.next;
		prevNode.next = Node.next;
                Node.next.prev = Node.prev;
		Node.next = null;
                Node.prev = null;
		this.length--;
		return Node;	
	}
	size(){
		return this.length;
	}
	isEmpty(){
		return this.length === 0;
	}
}
复制代码

循环链表

introduce.png

循环链表的最后一个节点再也不是指向null,而是指向虚拟的头部head指针,其余的操做相相似与单链表: ES6实现循环链表代码:ui

append(node,index){
  const prevNode = this.find(this.head,0,index);
  const curtNode = prevNode.next;
  if(!curtNode.next.data){
    curtNode.next = node;
    node.next = this.head;
  }else{
    node.next = curtNode.next;
    curtNode.next = node;
  }
   this.length++;
   return true;
}
remove(index){
  const prevNode = this.find(this.head,0,index);
  const curtNode = prevNode.next;
  //若是只有一个虚拟head头部节点或删除的是最后一个节点
  if(!curtNode.next.data){
    prevNode.next = this.head;
  }else{
     prevNode.next = curtNode.next;
     curtNode.next = null;
  }
  this.length --;
   return true;
}
复制代码

完成链表数据结构编码this

相关文章
相关标签/搜索