有了单向链表的基础,双向链表的实现就容易多了。

双向链表的一般情况:

增加节点:

删除节点:

双向链表的Java实现:

package com.liuhao.algorithm;  public class DuLinkList<T> {  /** * 内部类:链表中的一个节点 *  * @author liuhao data 节点中的数据 prev 指向前一个节点的引用 next 指向下一个节点的引用 */  private class Node {  private T data;// 保存的数据元素  private Node prev;// 指向上一个节点  private Node next;// 指向下一个节点  public Node() {  }  public Node(T data, Node prev, Node next) {  super();  this.data = data;  this.prev = prev;  this.next = next;  }  }  private Node header;// 头结点  private Node tail;// 尾节点  private int size;// 链表中元素个数  // 创建空链表  public DuLinkList() {  header = null;  tail = null;  }  // 已指定数据元素创建链表,只有一个元素  public DuLinkList(T element) {  header = new Node(element, null, null);  // 只有一个节点,header,tail都指向该节点  tail = header;  size++;  }  // 返回链表长度  public int length() {  return size;  }  // 获取指定位置的数据元素  public T get(int index) {  return this.getNodeByIndex(index).data;  }  // 获取指定位置的节点  private Node getNodeByIndex(int index) {  if (index < 0 || index > size - 1) {  throw new IndexOutOfBoundsException("索引超出线性表范围");  }  if (index < size / 2) {  Node current = header;  for (int i = 0; i < size / 2 && current != null; i++, current = current.next) {  if (i == index) {  return current;  }  }  } else {  Node current = tail;  for (int i = size - 1; i >= size / 2 && current != null; i--, current = current.prev) {  if (i == index) {  return current;  }  }  }  return null;  }  // 按值查询所在的位置  public int locate(T element) {  Node current = header;  for (int i = 0; i < size - 1 && current != null; i++, current = current.next) {  if (element.equals(current.data)) {  return i;  }  }  return -1;  }  // 向指定位置插入元素  public void insert(T element, int index) {  if (index < 0 || index > size) {  throw new IndexOutOfBoundsException("索引超出线性表范围");  }  if (header == null) {  this.add(element);  } else {  if (0 == index) {  this.addAtHead(element);  } else {  Node prev = this.getNodeByIndex(index - 1);// 获取插入节点的前一个节点  Node next = prev.next;// 待插索引处的节点  Node newNode = new Node(element, prev, next);// 新增节点,让它的prev指向之前的节点。next指向之后的节点  prev.next = newNode;// 之前的节点的next指向当前节点  next.prev = newNode;// 之后节点的prev指向当前节点  size++;  }  }  }  // 采用尾插法添加新节点  public void add(T element) {  // 若还是空表,则将header和tail都指向该元素即可  if (header == null) {  header = new Node(element, null, null);  tail = header;  } else {  // 创建信节点,prev指向tail  Node newNode = new Node(element, tail, null);  // 令tail的next指向新节点  tail.next = newNode;  tail = newNode;// 把新节点设为尾节点  }  size++;  }  // 采用头插发添加新节点  public void addAtHead(T element) {  Node newNode = new Node(element, null, header);  header.prev = newNode;  header = newNode;  // 如果插入之前是空表  if (tail == null) {  tail = header;  }  size++;  }  // 删除指定索引处的元素  public T delete(int index) {  if (index < 0 || index > size - 1) {  throw new IndexOutOfBoundsException("索引超出线性表范围");  }  Node del = null;  if (index == 0) {  del = header;  header = header.next;  header.prev = null;  } else {  Node prev = this.getNodeByIndex(index - 1);// 获取索引处之前的节点  del = prev.next;// 获取索引处的节点  // 让之前的节点的next指向下一个节点  prev.next = del.next;  // 有可能删除的是最后一个元素,若直接调用next.prev可能会出错  if (del.next != null) {  del.next.prev = prev;  }  //若删除的是最后一个元素,那么就要重置tail;  tail = prev;  del.prev = null;  del.next = null;  }  size--;  return del.data;  }  // 删除最后一个元素  public T remove() {  return this.delete(size - 1);  }  // 判断是否为空  public boolean isEmpty() {  return size == 0;  }  // 清空线性表  public void clear() {  header = null;  tail = null;  size = 0;  }  public String toString() {  if (size == 0) {  return "[]";  } else {  StringBuilder sb = new StringBuilder("[");  for (Node current = header; current != null; current = current.next) {  sb.append(current.data.toString() + ", ");  }  sb.append("]");  int len = sb.length();  // 删除多余的“,”和空格  return sb.delete(len - 3, len - 2).toString();  }  }
}

测试代码:

package com.liuhao.test;import org.junit.Test;import com.liuhao.algorithm.DuLinkList;public class DuLinkListTest {@Testpublic void test() {//测试构造函数DuLinkList<String> duList = new DuLinkList("好");System.out.println(duList);//测试添加元素duList.add("ni");duList.add("没");System.out.println(duList);//在头部添加duList.addAtHead("五月");System.out.println(duList);//在指定位置添加duList.insert("摩卡", 2);System.out.println(duList);//获取指定位置处的元素System.out.println("第2个元素是(从0开始计数):" + duList.get(2));//返回元素索引System.out.println("摩卡在的位置是:" + duList.locate("摩卡"));System.out.println("moka所在的位置:" + duList.locate("moka"));//获取长度System.out.println("当前线性表的长度:" + duList.length());//判断是否为空System.out.println(duList.isEmpty());//删除最后一个元素duList.remove();System.out.println("调用remove()后:" + duList);//获取长度System.out.println("当前线性表的长度:" + duList.length());//删除指定位置处元素duList.delete(3);System.out.println("删除第4个元素后:" + duList);//获取长度System.out.println("当前线性表的长度:" + duList.length());//清空duList.clear();System.out.println(duList);//判断是否为空System.out.println(duList.isEmpty());}}

  

转载于:https://www.cnblogs.com/ganchuanpu/p/7468565.html

线性表的Java实现--链式存储(双向链表)相关推荐

  1. 线性链表java实现_线性表的Java实现--链式存储(双向链表)

    线性表的Java实现--链式存储(双向链表) 有了单向链表的基础,双向链表的实现就容易多了. ? 双向链表的一般情况: ? ? class="decoded" alt=" ...

  2. 数据结构之线性表——(二、链式存储结构)[c语言]

    数据结构之线性表--(二.链式存储结构-单链表) 链式存储结构以及基本运算的实现 背景:由于线性表的存储特点是用物理上的相邻实现逻辑上的相邻,他要求用连续的存储单元顺序存储线性表中的各个元素,所以,对 ...

  3. 数据结构(二)----线性表(List)链式存储结构(1)

    线性表List---链式存储结构 相关概念 链式存储结构/链式表 定义 链式存储特点 单链表 单链表读取 单链表插入 单链表删除 时间复杂度 单链表整表创建 单链表整表删除 顺序存储与链式存储差异 P ...

  4. 什么是线性表?线性表的特点,线性表的顺序存储和链式存储

    线性表的表示 线性表的特点 ai的数据类型相同 位置序列从1开始 除去表头和表位,所有元素有且仅有唯一的直接前驱和后继 线性表的存储结构 顺序存储 可以随机的读取数据,读取方法 loc(a1)是基地址 ...

  5. 数据结构与算法2:线性表的顺序存储与链式存储

    文章目录 线性表 定义 线性表的抽象数据类型(Abstract Data Type) 线性表的顺序存储结构 线性表的链式存储结构 单链表(single linked list) 静态链表 (stati ...

  6. 线性表之顺序存储和链式存储结构

    线性表:由零个或多个数据元素组成的有限序列 线性表有两种物理存储结构:顺序存储结构和链式存储结构 一.顺序存储结构 顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的结点存储在物理位置上相邻的 ...

  7. 线性表的顺序、链式存储结构基本操作

    线性表的抽象数据类型 operation InitList(&L):初始化操作,建立一个空的线性表L ListEmpty(L):若线性表为空,返回true,否则返回false ClearLis ...

  8. 链表list(链式存储结构实现)_数据结构知否知否系列之 — 线性表的顺序与链式存储篇(8000 多字长文)...

    从不浪费时间的人,没有工夫抱怨时间不够. -- 杰弗逊 线性表是由 n 个数据元素组成的有限序列,也是最基本.最简单.最常用的一种数据结构. 作者简介:五月君,Nodejs Developer,热爱技 ...

  9. 数据结构-线性表的顺序、链式存储结构

最新文章

  1. Selenium高亮页面对象
  2. 物联网技术在智能医疗的应用
  3. 开课吧python课程-明星为开课吧直播带货:人人都要学,人人都可以学的Python
  4. 服务器怎么导出数据库文件,怎么导出服务器数据库文件
  5. python爬取小说代码bs4和_使用python爬虫,requests(夹带BeautifulSoup的使用)爬取网络小说...
  6. 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 1
  7. pin controller driver代码分析
  8. 快速排序quicksort算法细节优化(一次申请内存/无额外内存排序)
  9. CentOS下yum安装mcrypt错误:No package php-mcrypt available.解决方法
  10. “乘风破浪”的中国SaaS :风浪越大,机会越大?
  11. python语法简洁清晰特色之一是强制用什么作为语句缩进_Python解决矩阵问题
  12. java 内省 反射_理解Java的反射与内省及其区别
  13. (译)响应式图片— srcset 和 sizes 属性
  14. 两级联动mysql怎样查询_我的二级联动下拉框(方便以后查询)
  15. 小福利,通过python利用百度ai实现图片识别
  16. PDF在线压缩、转换工具
  17. 清理zabbix监控中磁盘空间不足
  18. 套接字I/O模型-WSAEventSelect(转载)
  19. MEMS--微机电系统
  20. Kafka批量消费模式

热门文章

  1. kali系统apt设置代理
  2. python调用sklearn中朴素贝叶斯踩坑
  3. Android WebView注入js文件,判断当前HTML有没有某个js然后再注入
  4. Web API 接口
  5. 错误记录,找不到sqlite dll
  6. YEAH!!距离拿回touch4倒计时:7days
  7. c# 简单的科学计算
  8. oracle与raw device
  9. Traceroute程序
  10. python中loop的用法_python-在Tensorflow中使用tf.while_loop更新变量