前言

上一次我们讲到了数据结构:栈和队列,并对他们的运用做了一些介绍和案例实践;我们也讲到了怎么简单的实现一个四则运算、怎么去判断标签是否闭合完全等等,anyway,今天接着和大家介绍一些数据结构:

链表

链表是一种怎么样的结构呢?链表就是一种可以把数据串联起来的结构,每个元素会有指向下一个元素的指针(末尾的没有普通链表),就像现实世界中的火车一样一节一节的串联起来;链表根据自身的指针指向又可以分为:单向链表、双向链表、循环链表;

链表首先会有一个表头,表头作为起始的指针,然后每一个元素我们称作为节点(node);每个节点有一个指向下一个节点的指针(next),直到链表的末尾指针会指向undefined;

链表的实现

1、节点

节点的创建和定义;每个节点会有一个保存自己数据的属性(element),然后有一个指针(next)export class Node {

constructor(element, next = null) {

this.element = element;

this.next = next;

}

}

2、链表的api

getElementAt(position): 获取某个位置的元素

append(element): 向链表末尾中添加元素

removeAt(idx): 移除某个元素

insert(element, position = 0, dir = 'before'): 向指定位置添加元素

insertAfter(element, position): 向指定的位置后面添加元素

size(): 链表的长度

remove(): 删除链表末端元素

removeAll(): 删除整个链表

isEmpty(): 检查链表是否为空import { defaultEquals } from "../util.js";

import { Node } from './Node.js'

export default class LinkedList {

constructor(equalsFn = defaultEquals) {

this.count = 0;

this.head = null;

this.equalsFn = equalsFn;

}

getElementAt(position) {

if(position >= 0 && position <= this.count) {

let node = this.head;

for (let i = 0; i

node = node.next;

}

return node;

}

return undefined;

}

insertAfter(element, position) {

return this.insert(element, position, 'after');

}

size() {

return this.count;

}

remove() {

return this.removeAt(this.size() - 1);

}

removeAll() {

this.count = 0;

this.head = null;

}

isEmpty() {

return this.size() === 0;

}

getHead() {

return this.head;

}

}

3、链表末尾添加一个元素append;append(element) {

const node = new Node(element);

let current = this.head;

if(current == null) {

this.head = node;

} else {

current = this.head;

while (current.next !=  null) {

current = current.next;

}

current.next = node

}

this.count++;

return element;

}

4、插入一个元素insert(element, position = 0, dir = 'before') {

if (element === undefined) {

throw Error('缺少需要插入的元素');

return;

}

if (position >= this.count) {

return this.append(element);

}

const node = new Node(element);

const targetNode = dir === 'before' ? this.getElementAt(position - 1) : this.getElementAt(position);

if (!targetNode) {

let prev = this.head;

this.head = node;

node.next = prev;

} else {

let next;

next = targetNode.next

targetNode.next = node;

node.next = next;

}

this.count++;

return element;

}

5、删除一个元素removeAt(idx) {

if (idx >= 0 && idx

let current = this.head;

if (idx === 0) {

this.head = current.next;

current.next = null;

} else {

let prev = this.getElementAt(idx - 1);

current = prev.next;

prev.next = current.next;

}

this.count--;

return current.element;

}

return undefined;

}

6、双向链表

单向链表元素指向都是一个方向的,也只能被单向递归搜索,而双向链表不仅仅有指向下一个元素的指针同时具有指向上一个元素的指针;

import LinkedList from "./LinkedList";

import {defaultEquals} from "../util";

import { DoubleNode } from "./DoubleNode";

export default class DoubleLinkedList extends LinkedList{

constructor(equalIsFn = defaultEquals){

super(equalIsFn);

this.tail = null;// 队列尾部

}

getElementAt(position) {

if(position >= 0 && position <= this.count) {

if (position > this.count/2) {

let cur = this.tail;

for (let i = this.count - 1; i > position; i--){

cur = cur.prev;

}

return cur;

} else {

return super.getElementAt(position)

}

}

return undefined;

}

removeAll() {

super.removeAll();

this.tail = null;

}

removeAt(position) {

if (position >= 0 && position

let cur = this.getElementAt(position);

if(position === 0) {

this.head = cur.next;

cur.next = null;

this.prev = null;

} else if (position === this.count - 1) {

this.tail = cur.prev;

this.tail.next = null;

cur.prev = null;

} else {

let prev = cur.prev;

let next = cur.next;

prev.next = next;

next.prev = prev;

cur.prev = null;

cur.next = null;

}

this.count--;

return cur.element;

}

return undefined;

}

}

队列末尾插入元素(append)

双向链表插入元素和单向比较类似,不同的是双向不仅要链接他的下级还得关联他的前一级;append(element) {

const node = new DoubleNode(element);

if (!this.tail) {

this.head = node;

this.tail = node;

} else {

let cur = this.tail;

cur.next = node;

node.prev = cur;

this.tail = node;

}

this.count++;

return element;

}

中间某个位置插入元素insert(element, position = 0, dir = 'before'){

if (element === undefined) {

throw Error('缺少需要插入的元素');

return;

}

if (position >= this.count) {

return this.append(element);

}

const node = new DoubleNode(element);

let cur;

const targetNode = dir === 'before' ? this.getElementAt(position - 1) : this.getElementAt(position);

if (!targetNode) {

cur = this.head;

node.next = cur;

cur.prev = node;

this.head = node;

} else {

let next;

next = targetNode.next

targetNode.next = node;

node.prev = targetNode;

node.next = next;

next.prev = node;

}

this.count++;

return element;

}

移除某个元素也是上述相同,修改节点的前后指针就可以了,这里不再赘述,详情看源码

闭环链表

闭环链表也称环,是一个闭合的结构,尾部会指向头部

有序链表

有序链表就是在append元素的时候进行排序加入从而得到一个有顺序的链表,比较函数可以根据实例化的时候传入比较函数equalIsFn;

java算法判断链表有没有闭环_前端算法系列之二:数据结构链表、双向链表、闭环链表、有序链表...相关推荐

  1. 两个有序链表序列的交集_剑指offer第21天:合并两个有序链表

    我准备了 1000 本电子书和计算机各领域高清思维导图 100 张,关注后回复[资源],即可获取!更可回复[内推]加入 BAT 内推群! 01.题目分析 第21题:合并两个有序链表 将两个有序链表合并 ...

  2. c++编写算法判断二叉树是否为完全二叉树_[校招-算法题] 二叉树基础算法1

    二叉树是面试中常考的数据结构,因为涉及大量指针操作,因此可以考察思维的严谨性和灵活性.但是校招中的二叉树题规律性很强,因此需要总结一下. 各种常见的二叉树概念 二叉树:每个结点最多有两个子树(左子树和 ...

  3. fastreport 打印两个list_Smaller And Smarter Python数据结构:合并两个有序链表

    原创: 老表 简说Python 今日问题 :翻转链表k个相邻结点 """目标:写一段程序,合并两个有序链表例如:输入-> 1->2->3输入-> ...

  4. c++编写算法判断二叉树是否为完全二叉树_字节面试官:连这90道LeetCode算法题都不会也来面试?...

    面试大厂必刷:LeetCode算法90题 1. 买股票的最佳时机 难度级别:简单 题目: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一 ...

  5. 算法导论吃透后的水平_初学算法,你应该这么玩

    很多前端童鞋对算法都有莫名的恐惧,究其原因无非两点:其一,对算法不了解:其二,没有找到实际应用场景. 一.为什么学习算法? 这是个很有意思的问题,对算法感兴趣的人,不需要问为什么,算法对他们可能是一种 ...

  6. gif透明背景动画_前端基础系列之bmp、jpg、png、gif、svg常用图片格式浅谈(二)...

    IT客栈 作者:大腰子 bmp.jpg.png.gif.svg常用图片格式 之前为大家介绍了几种WEB前端常用的图片格式,对比了它们的特点,参见<前端基础系列之bmp.jpg.png.gif.s ...

  7. access中判断回文的代码_前端也来点算法(TypeScript版) | 2 - 回文数和回文链表

    算法采用 TS 进行编写.  回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数.回文链表是链表节点的值和回文数有相同规律的链表. " 回文数 这个数字可以看成是以中心对称分布的 ...

  8. java判断扑克牌是否为顺子_程序算法设计题,判断扑克牌中的顺子

    相信很多人都玩过扑克牌.在扑克牌中,有许许多多的算法供我们学习.仅仅一个斗地主游戏,就可以学习很多的算法.今天和大家分享一个判断扑克牌中的顺子的问题. 题目: 从扑克牌中随机抽取五张牌,判断是不是一个 ...

  9. Java中对查出的数据计数_基础算法7:从数据库某个字段中取出现次数最多的几条数据形成“热门xxx”...

    在这里,我们需要查出所有的"出发城市"和"到达城市",并对每个城市进行计数根据其出现次数来取出几个出现次数最多的城市为热门城市 注:将多个字段的数据合并在一起并 ...

最新文章

  1. 解题报告(八) prufer 序列与 Cayley 公式(ACM / OI)超高质量题解
  2. How to protect video content (Flash Media Server)
  3. 【Python】学习笔记总结2(Python面向对象)
  4. linux 多线程实现倒计时,Linux用脚本实现“时分秒“倒计时功能
  5. 用计算机绘画教学反思,《电脑绘画》教学反思2篇
  6. 现在小餐厅的推广视频
  7. winform利用html开发,.NET使用Cefsharp开发winform项目入门示例
  8. python自动化办公教程-python办公自动化:Excel操作入门
  9. GridView 设置背景透明以及Item的点击动画
  10. [转]window.location方法获取URL及window.location.assign(url)和replace(url)区别
  11. linux 程序员字体下载,编程字体Monaco字体 For Linux版
  12. 主流PC常用总线总结
  13. 旅游网页设计 web前端大作业 全球旅游私人订制 旅游公司网站模板(HTML+CSS+JavaScript)
  14. 【iOS取证篇】iOS设备去除备份密码提取数据
  15. 设计模式-工厂方法的应用场景及Java中对工厂方法的应用
  16. Python极简实现IoU
  17. es6 符号 双问号
  18. 计算机软件系统技术,信息技术《计算机软件系统》教学设计
  19. asp毕业设计——基于vb+VB.NET+SQL Server的图书馆管理信息系统设计与实现(毕业论文+程序源码)——图书馆管理信息系统
  20. python中哪些是无序_关于无序集合:无序集合 – 在python中设置

热门文章

  1. 在阿里淘系6个月能有哪些收获成长?
  2. 云栖专辑 | 阿里开发者们的第19个感悟:Simple is better.
  3. 迁移学习让深度学习更容易
  4. 苹果将于 2025 年推出的 Apple Car 长什么样?
  5. Gartner发布2021年数字商务技术成熟度曲线,重点关注四项技术
  6. Fortinet再获Gartner 2021广域网边缘基础设施魔力象限领导者
  7. Redis 6.0 的客户端缓存是怎么肥事?一文带你了解!
  8. 2020 年,云游戏将爆发?各大科技公司云游戏布局大曝光!
  9. 开发者在行动!中国防疫开源项目登上 GitHub TOP 榜
  10. 重磅!Python又第一了!网友:为什么找不到好工作?真相让人脸红…