链表

链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

  • 创建链表
//有头链表   第一个节点只有指针域
//无头链表   第一个节点既有数据域又有指针域
//实现一个无头链表
function LinkList() {
  let Node = function(data) {
    this.next = null //指针
    this.data = data //数据
  }
  let length = 0 //长度
  let head = null //头节点
  let tail = null //尾节点
  //添加
  this.append = function(data) {
    const node = new Node(data)
    //如果链表为空
    if (head === null) {
      head = node
      tail = head //是第一个又是最后一个
    } else {
      tail.next = node //尾节点指向新创建的节点
      tail = node //tail指向最后一个节点
    }
    length++
    return true
  }
  //打印
  this.print = function() {
    let current_node = head
    let printText = ''
    while (current_node) {
      printText += current_node.data.toString() + '-->'
      current_node = current_node.next
    }
    printText += 'null'
    return printText
  }
  //插入
  this.insert = function(index, data) {
    if (index < 0 || index > length) return false
    let insert_node = new Node(data)
    if (head === null) {
      head = insert_node
      tail = insert_node
      length++
      return true
    }
    //index为0 是首节点
    if (index === 0) {
      insert_node.next = head
      head = insert_node
    } else if (index === length) {
      tail.next = insert_node
      tail = insert_node
    } else {
      let current_node = head
      let current_index = 1
      while (current_index < index) {
        current_node = current_node.next
        current_index++
      }
      insert_node.next = current_node.next
      current_node.next = insert_node
      if (insert_node.next === null) {
        tail = insert_node
      }
    }
    length++
    return true
  }
  //移除
  this.remove = function(index) {
    if (index < 0 || index >= length) return false
    let remove_node = null
    if (index === 0) {
      remove_node = head
      head = head.next
    } else {
      let current_index = 0
      let current_node = head //当前节点  要被删除的节点
      let prev_node = head //上一个节点
      while (current_index < index) {
        prev_node = current_node
        current_node = current_node.next
        current_index++
      }
      remove_node = current_node
      prev_node.next = current_node.next
      if (current_node.next === null) {
        tail = prev_node
      }
    }
    length--
    return remove_node.data
  }
  //删除首节点
  this.remove_head = function() {
    return this.remove(0)
  }
  //删除尾节点
  this.remove_tail = function() {
    return this.remove(length - 1)
  }
  // 获取指定索引的内容
  this.get = function(index) {
    if (index < 0 || index >= length) return false
    let current_index = 0
    let current_node = head
    while (current_index < index) {
      current_node = current_node.next
      current_index++
    }
    return current_node.data
  }
  //根据数据获取指定索引,多个相同数据只返回第一个的索引
  this.indexOf = function(data) {
    if (!data) return -1
    let index = -1
    let current_node = head
    while (index < length - 1) {
      index++
      if (current_node.data === data) {
        return index
      }
      current_node = current_node.next
    }
    return -1
  }
  //返回首节点
  this.head = function() {
    return head.data
  }
  //返回尾节点
  this.tail = function() {
    return tail.data
  }
  //返回链表长度
  this.length = function() {
    return length
  }
  //链表是否为空
  this.isEmpty = function() {
    return head === null
  }
  //清空链表
  this.clear = function() {
    head = null
    tail = null
    length = 0
  }
}
const link = new LinkList()
link.append(1)
link.append(6)
link.append(3)
link.insert(2, 8)
link.print()
link.insert(1, 5)
link.print()
link.insert(5, 9)
link.print()
link.insert(0, 0)
link.print()
link.remove(3)
link.print()
link.remove(5)
link.print()
//console.log(link.get(3))  //8
console.log(link.indexOf(5))
  • 用链表实现栈
function Stack() {
  const link = new LinkList()
  //压入栈中
  this.push = function(item) {
    link.append(item)
  }
  //弹出栈顶元素
  this.pop = function() {
    return link.remove_tail()
  }
  //获取栈的长度
  this.size = function() {
    return link.length()
  }
  //获取栈顶元素
  this.top = function() {
    return link.tail()
  }
  //清空栈
  this.clear = function() {
    return link.clear()
  }
  //栈是否为空
  this.isEmpty = function() {
    return link.isEmpty()
  }
}

  • 用链表实现队列
function Queue() {
  const link = new LinkList()
  //加入队列
  this.enqueue = function(item) {
    link.append(item)
  }
  //移除队列
  this.dequeue = function() {
    return link.remove_head()
  }
  //获取队首
  this.head = function() {
    return link.head()
  }
  //获取队尾
  this.tail = function() {
    return link.tail()
  }
  //获取队列长度
  this.size = function() {
    return link.length()
  }
  //获取队列是否为空
  this.isEmpty = function() {
    return link.isEmpty()
  }
  //清空队列
  this.clear = function() {
    return link.clear()
  }
}

  • 翻转链表
// 迭代翻转
function reverse_iter(head) {
  let current_node = head
  let prev_node = null
  while (current_node) {
    let next_node = current_node.next
    current_node.next = prev_node
    prev_node = current_node
    current_node = next_node
  }
}
// 递归翻转
function reverse_digui(head) {
  if (!head) {
    return null
  }
  if (head.next === null) {
    return head
  }
  let new_head = reverse_digui(head.next)
  head.next.next = head
  head.next = null
  return new_head
}

  • 合并两个有序链表
var Node = function(data) {
  this.data = data
  this.next = null
}
var node1 = new Node(1)
var node2 = new Node(4)
var node3 = new Node(9)
var node4 = new Node(2)
var node5 = new Node(5)
var node6 = new Node(6)
var node7 = new Node(10)
node1.next = node2
node2.next = node3

node4.next = node5
node5.next = node6
node6.next = node7

function merge_link(head1, head2) {
  if (head1 === null) {
    return head2
  } else if (head2 === null) {
    return head1
  }
  let cur1 = head1
  let cur2 = head2
  let merge_head = null
  let merge_tail = null
  while (cur1 && cur2) {
    //数据进行比较取得最小值
    let min_data = null
    if (cur1.data <= cur2.data) {
      min_data = cur1.data
      cur1 = cur1.next
    } else {
      min_data = cur2.data
      cur2 = cur2.next
    }
    if (merge_head == null) {
      merge_head = new Node(min_data)
      merge_tail = merge_head
    } else {
      let new_node = new Node(min_data)
      merge_tail.next = new_node
      merge_tail = new_node
    }
  }
  //可能其中一个链表还有剩下的值
  let result_node = null
  if (cur1) {
    result_node = cur1
  }
  if (cur2) {
    result_node = cur2
  }
  while (result_node) {
    let n_node = new Node(result_node.data)
    merge_tail.next = result_node
    merge_tail = result_node
    result_node = result_node.next
  }
  return merge_head
}
print(merge_link(node1, node4))

function print (node) {
  var curr_node = node
  while (curr_node) {
    console.log(curr_node.data, 33)
    curr_node = curr_node.next
  }
}
//查找链表中指定位置的值
function link_find(index, head) {
  let curr_node = head
  let current_index = 0
  while (current_index < index) {
    curr_node = curr_node.next
    current_index++
  }
  return curr_node.data
}
//查找链表的中值
function link_middle(head) {
  let current_node = head
  let current_index = 0
  while (current_node) {
    current_node = current_node.next
    current_index++
  }
  console.log(current_index, link_find(Math.floor(current_index / 2), head))
}
link_middle(node1)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容