java 算法结构----单链表

2023-11-06

相关基础知识补充

指针:表示一个数据元素逻辑意义上的存储位置。

Java语言用通过对象的引用来表示指针。通过把新创建对象赋值给一个对象引用,即是让该对象引用表示(或指向)了所创建的对象。

链式存储结构是基于指针实现的。我们把一个数据元素和一个指针称为一个结点。链式存储结构是用指针把相互直接关联的结点(即直接前驱结点和直接后继结点)链接起来。链式存储结构的特点是数据元素之间的逻辑关系表现在结点的链接关系上。链式存储结构的线性表为链表。

根据结点构造链的方法不同,链表主要有单链表、单循环链表和双循环链表。

 

单链表的结构:

单链表中,构成链表的每个结点只有一个指向后继结点的指针。

 

单链表有带头结点结构和不带头结点结构两种:

我们把指向单链表的指针称为单链表的头指针。头指针所指的是不存放数据元素的第一个结点称为头结点。存放第一个数据元素的结点称为第一个数据元素结点,或称为首元结点。

 

顺序存储结构与链式存储结构的差别?

             在顺序存储结构中,用户向系统申请一块地址连续的有限空间用于数据存储数据元素序列,这样任意逻辑上相邻的数据元素在物理存储位置上也必然相邻。

             在链式存储结构中,由于链式存储结构在初始化时为空,每当有新数据元素需要存储时,用户才向系统动态申请的结点插入链表中,而这些在不同时刻向系统申请的结点,一般情况下其存储位置并不连续。因此,在链式存储结构中,任意两个逻辑上相邻的数据元素在物理上不一定相邻,数据元素的逻辑关系是通过指针链接实现的。

 

源代码:

package com.algorithm;

//单链表实列化
public class SingleLinkedList<T> {
	/*
	 * 结点类
	 */
	private static class Node<T> {
		T nodeValue; // 数据域
		Node<T> next; // 指针域保存着下一节点的引用

		Node(T nodeValue, Node<T> next) {
			this.nodeValue = nodeValue;
			this.next = next;
		}

		Node(T nodeValue) {
			this(nodeValue, null);
		}
	}

	// 单链表相关属性和方法
	private Node<T> head, tail;

	// 构造函数
	public SingleLinkedList() {
		head = tail = null;
	}

	// 判断单链表是否为空
	public boolean isEmpty() {
		return head == null;
	}

	/**
	 * 创建头指针,该方法只用一次!
	 */
	public void addToHead(T item) {
		head = new Node<T>(item);
		if (tail == null)
			tail = head;
	}

	/**
	 * 添加尾指针,该方法使用多次
	 */
	public void addToTail(T item) {
		if (!isEmpty()) { // 若链表非空那么将尾指针的next初使化为一个新的元素
			tail.next = new Node<T>(item); // 然后将尾指针指向现在它自己的下一个元素
			tail = tail.next;
		} else { // 如果为空则创建一个新的!并将头尾同时指向它
			head = tail = new Node<T>(item);
		}
	}

	/**
	 * 打印列表
	 */
	public void printList() {
		if (isEmpty()) {
			System.out.println("null");
		} else {
			for (Node<T> p = head; p != null; p = p.next)
				System.out.println(p.nodeValue);
		}
	}

	/**
	 * 在表头插入结点,效率非常高
	 */
	public void addFirst(T item) {
		Node<T> newNode = new Node<T>(item);
		newNode.next = head;
		head = newNode;
	}

	/**
	 * 在表尾插入结点,效率很低
	 */
	public void addLast(T item) {
		Node<T> newNode = new Node<T>(item);
		Node<T> p = head;
		while (p.next != null)
			p = p.next;
		p.next = newNode;
		newNode.next = null;
	}

	/**
	 * 在表头删除结点,效率非常高
	 */
	public void removeFirst() {
		if (!isEmpty())
			head = head.next;
		else
			System.out.println("The list have been emptied!");
	}

	/**
	 * 在表尾删除结点,效率很低
	 */
	public void removeLast() {
		Node<T> prev = null, curr = head;
		while (curr.next != null) {
			prev = curr;
			curr = curr.next;
			if (curr.next == null)
				prev.next = null;
		}
	}

	/**
	 * <p>
	 * 插入一个新结点
	 * </p>
	 * <ul>
	 * 插入操作可能有四种情况:
	 * <li>①表为空, 返回false</li>
	 * <li>②表非空,指定的数据不存在</li>
	 * <li>③指定的数据是表的第一个元素</li>
	 * <li>④指定的数据在表的中间</li>
	 * </ul>
	 * 
	 * @param appointedItem
	 *            指定的nodeValue
	 * @param item
	 *            要插入的结点
	 * @return 成功插入返回true;
	 */
	public boolean insert(T appointedItem, T item) {
		Node<T> prev = head, curr = head.next, newNode;
		newNode = new Node<T>(item);
		if (!isEmpty()) {
			while ((curr != null) && (!appointedItem.equals(curr.nodeValue))) { // 两个判断条件不能换
				prev = curr;
				curr = curr.next;
			}
			newNode.next = curr; // ②③④
			prev.next = newNode;
			return true;
		}
		return false; // ①
	}

	/**
	 * <p>
	 * 移除此列表中首次出现的指定元素
	 * </p>
	 * <ul>
	 * 删除操作可能出现的情况:
	 * <li>①prev为空,这意味着curr为head. head = curr.next; --> removeFirst();</li>
	 * <li>②匹配出现在列表中的某个中间位置,此时执行的操作是 --> prev.next = curr.next;,</li>
	 * </ul>
	 * <p>
	 * 在列表中定位某个结点需要两个引用:一个对前一结点(prev左)的引用以及一个对当前结点(curr右)的引用.
	 * </p>
	 * prev = curr; curr = curr.next;
	 */
	public void remove(T item) {
		Node<T> curr = head, prev = null;
		boolean found = false;
		while (curr != null && !found) {
			if (item.equals(curr.nodeValue)) {
				if (prev == null)
					removeFirst();
				else
					prev.next = curr.next;
				found = true;
			} else {
				prev = curr;
				curr = curr.next;
			}
		}
	}

	/**
	 * 返回此列表中首次出现的指定元素的索引,如果列表中不包含此元素,则返回 -1.
	 */
	public int indexOf(T item) {
		int index = 0;
		Node<T> p;
		for (p = head; p != null; p = p.next) {
			if (item.equals(p.nodeValue))
				return index;
			index++;

		}
		return -1;
	}

	/**
	 * 如果此列表包含指定元素,则返回 true。
	 */
	public boolean contains(T item) {
		return indexOf(item) != -1;
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SingleLinkedList<String> t = new SingleLinkedList<String>();
		  //单链表添加头指针
		  t.addFirst("A");
		  //单链表添加相关数据
		  t.insert("B", "c");
		  t.insert("c", "c++");
		  t.insert("d", "java");
		  t.insert("e", "c#");
		  t.insert("f", "php");
		  //单链表添加尾指针
		  t.addLast("G");
		  //单链表移除
		  // t.remove("c");
		  //移除尾结点
		  t.removeLast();
            //移除头结点
		  t.removeFirst();
		  
		  boolean target=t.contains("ruby");
		  System.out.println("是否存在指定元素:"+target);		          
	 
		  t.printList(); // A B C     
	}

}


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 算法结构----单链表 的相关文章

随机推荐

  • 个人wiki搭建资料整理

    个人wiki搭建 一 大型企业级wiki Confluence Confluence是一个专业的企业知识管理与协同软件 也可以用于构建企业wiki 使用简单 但它强大的编辑和站点管理特征能够帮助团队成员之间共享信息 文档协作 集体讨论 信息
  • Java中NIO和IO的比较

    NIO是为了弥补IO操作的不足而诞生的 NIO的一些新特性有 非阻塞I O 选择器 缓冲以及管道 管道 Channel 缓冲 Buffer 选择器 Selector 是其主要特征 概念解释 Channel 管道实际上就像传统IO中的流 到任
  • m3u8格式的视频链接怎么在自己电脑上播放

    本文接上篇文章 网页播放器 CKplayer 的视频怎么下载 m3u8简单探索 上篇文章提到 怎么到视频网站通过浏览器抓包分析 得到视频的源地址 看这篇文章之前 最好可以去先看一看上篇博文的介绍 上篇文章我们介绍到我们能够得到视频的源地址
  • SpringBoot 之数据源配置

    文章目录 市面上的几种数据源比对 SpringBoot自动装配DataSource原理 HiKariCP 数据源配置 Druid 数据源配置 SpringBoot集成Druid连接池 Druid 多数据源配置 不同Mapper操作不同数据源
  • 初等模型---光盘的数据容量

    问题分析 光盘的外观尺寸是由些大公司成立的联盟决定的 如CD DVD等盘片的外径为120mm 并且沿外边缘留有2mm宽的环形区域不存储信息 CLV光盘存储信息的内圈直径为45mm 在内外圈之间的环形区域 经过编码的数字信息 以一定深度和宽度
  • MySQL 8用户及权限管理

    文章目录 参考文档 查看权限 安装后 登录测试 添加帐户 分配特权和删除帐户 扩展 创建远程访问新用户并授权 参考文档 官方链接 https dev mysql com doc refman 8 0 en create user html
  • 简单的扫雷程序的实现

    define CRT SECURE NO WARNINGS include
  • js操作时间过当天晚上00:00清除本地存储

    const end new Date new Date new Date toLocaleDateString getTime 24 60 60 1000 1 getTime 当天23 59 59秒 转换成的毫秒数 const start
  • banner切换

    html代码 div div a img src imgs p1 png alt a a img src imgs p2 jpg alt a a img src imgs p3 jpg alt a a img src imgs p4 jpg
  • 【javascript】导航栏

    要实现这样的效果主要有两点 第一 当鼠标经过主导航栏里面的内容就会被放大 鼠标离开后就会恢复原来的样子 第二 当鼠标经过主导航时对应的副导航的内容就会呈现
  • 一个完美的自动化测试框架应该怎么写?

    一 什么是自动化测试框架 自动化测试框架是为自动化测试用例或者脚本提供执行环境而搭建的基础设施 自动化测试框架有助于有效地开发 执行和报告自动化测试用例 优点 代码复用 提高测试效率 更高的测试覆盖率 维护成本低 更早发现和记录bug 二
  • Oracle RAC 更改网卡名称

    如 原网卡eth1 为增加网卡可靠性 把eth1和eth3绑定为bond0 主备模式提供服务 更改名称后RAC会无法启动网络服务 还需要更改的操作如下 u01 app 11 2 0 grid bin oifcfg getif u01 app
  • C#中的this

    一 C 中的this C 中的保留字this仅限于在构造函数 类的方法和类的实例中使用 在类的构造函数中出现的this作为一个值类型 它表示对正在构造的对象本身的引用 在类的方法中出现的this作为一个值类型 表示对调用该方法的对象的引用
  • WSDL(Web服务描述语言)详细解析

    WSDL Web Services Description Language Web服务描述语言 是一种XML Application 他将Web服务描述定义为一组服务访问点 客户端可以通过这些服务访问点对包含面向文档信息或面向过程调用的服
  • Java:珠穆朗玛峰

    需求 世界最高山峰是珠穆朗玛峰 8844 43米 8844430毫米 假如我有一张足够大的纸 它的厚度是0 1毫米 请问 我折叠多少次 可以折成珠穆朗玛峰的高度 分析 1 因为要反复折叠 所以要使用循环 但是不知道要折叠多少次 这种情况更适
  • 记一次spring循环依赖

    问题 spring循环依赖 场景 A注入B B注入A 按理来说spring是支持的处理 不会出现循环依赖的问题 但是 除了相互注入外 项目还是使用的AOP切面打印日志 使用了代理 问题就是出现在这里 源码 Whether to resort
  • 简单的整理一下Vue3的组合API

    1 Vue3的生态和优势 社区生态 逐步完善 整体优化 性能优化 TS支持优化 组合式API加持 市场使用 部分技术选型激进的公司已经在生产环境使用了vue3 社区生态 组件 插件 名称 官方地址 简介 ant design vue Ant
  • Eclipse远程调式

    JVM调式选项 Xdebug Xrunjdwp transport dt socket address 8000 server y suspend y 请务必写在一行
  • matplotlib画图

    画出第一个基本图像 import matplotlib pyplot as plt import numpy as np x np linspace 1 1 50 y x 2 1 plt plot x y plt show 用两个窗口画出两
  • java 算法结构----单链表

    相关基础知识补充 指针 表示一个数据元素逻辑意义上的存储位置 Java语言用通过对象的引用来表示指针 通过把新创建对象赋值给一个对象引用 即是让该对象引用表示 或指向 了所创建的对象 链式存储结构是基于指针实现的 我们把一个数据元素和一个指