1.链表的实现:不带哨兵

这篇具有很好参考价值的文章主要介绍了1.链表的实现:不带哨兵。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、链表linked list

1.定义

链表是数据元素的线性集合,其每个元素都指向下一个元素,元素存储上并不连续,链表逻辑连续。

2.分类

①单向链表:每个元素只知道其下一个元素是谁

1.链表的实现:不带哨兵

②双向链表: 每个元素知道其上一个元素和下一个元素

1.链表的实现:不带哨兵

 ③循环链表

1.链表的实现:不带哨兵

3.哨兵节点

不存储数据,用作头尾,用来简化边界判断

1.链表的实现:不带哨兵

4.链表性能

①随机访问(读取)

根据index查找,时间复杂O(n)。

根据索引查找元素的时候,要从头节点挨个查找

②插入或删除

起始位置:O(1)

结束位置:已知尾节点是O(1),不知道尾结点是O(n)

中间位置:根据index查找时间+O(1)

二、单向链表,不带哨兵

1.代码实现

 ①定义节点

public class SinglyLinkedList{

	/**
	 * 节点类
	 * 数据域和地址域
	 */
	private static class Node {
		int value;// 值
		Node next;// 指向下一个节点,因为节点的类型是Node

		public Node() {
		}

		public Node(int value, Node next) {
			this.value = value;
			this.next = next;
		}

	}

	private Node head; //头指针
}

②头部添加:每次是往表头依次添加,把新节点指向此时的head。然后让head再指向新节点。

如果head是null,就是head = new Node(value,null)

1.链表的实现:不带哨兵

	public void addFirst(int value) {
		// 1.链表为空时,head是null 相当于head = new Node(value,null)
		// 2.链表不为空时,new Node(value,head) 然后把新节点当为头结点head = new Node(value,head)
		// 3.优化如下
		head = new Node(value, head);
	}

②尾部添加:先找到最后一个节点的地址 while(p.next != null),如果链表为空,返回null

	public Node findLast() {
		// 判断是否为空
		if (head == null) {
			return null;
		}
		// 链表不为空
		Node p = head;
		while (p.next != null) {
			p = p.next;
		}
		return p;
	}

返回的是最后一个节点地址last.next=new Node(value, null);如果返回的是null,那么就表头添加。

1.链表的实现:不带哨兵

	public void addLast(int value) {
		Node last = findLast();
		if (last == null) {
			addFirst(value);
			return;
		}
		// 找到尾巴节点
		last.next = new Node(value, null);
	}

③遍历节点1:定义一个辅助节点p指向头结点,条件是while(p!=null),一直到链表为空

	/**
	 * 2.遍历节点1
	 */
	public void loop1() {
		Node p = head;
		while (p != null) {
			System.out.println(p.value);
			p = p.next;
		}
	}

	/**
	 * 遍历节点2
	 */
	public void loop2() {
		for (Node p = head; p != null; p = p.next) {
			System.out.println(p.value);
		}
	}

也可以用增强for循环,重写iterator()

public class SinglyLinkedList implements Iterable<Integer> {


....

	@Override
	public Iterator<Integer> iterator() {
		return new Iterator<Integer>() {
			Node p = head;
			// 是否有下一个元素
			@Override
			public boolean hasNext() { 
				return p != null;
			}
			// 返回当前元素,指向下一个元素
			@Override
			public Integer next() { 
				int value = p.value;
				p = p.next;
				return value;
			}
		};
	}
}

测试用这个

Iterator<Integer> iterator = singlyLinkedList.iterator();
		for (Integer integer:singlyLinkedList){
			System.out.println(integer);
		}

④根据索引查找get(i) 0,1,2,3...,先查找这个索引的节点。没有找到返回null,找到的话返回当前节点

	public Node findNode(int index) {
		Node p = head;
		int i = 0;
		while (p != null) {
			// 找到了
			if (index == i) {
				return p;
			}
			i++;
			p = p.next;//指向下一个节点
		}
		// 没找到
		return null;
	}

如果为null,说明此时不合法

	public int get(int index){
		Node node = findNode(index);
		if (node == null){
			throw new IllegalArgumentException(
					String.format("inndex[%d]不合法%n",index)
			);
		}
		return node.value;
	}

⑤插入到索引位置,先定义辅助节点p指向索引的前一个地址,先让新节点的地址指向p的地址,再让p节点指向新节点的地址。如果p为空,插入失败。如果索引为0,那么调用头部添加的方法

1.链表的实现:不带哨兵

	/**
	 * 4.insert(int index)
	 * 根据索引插入,插在索引的位置,所以找索引前面的节点
	 */
	public void insert(int index,int value){
		if (index == 0){
			// 插入头位置
			addFirst(value);
			System.out.println("插入成功");
			return;
		}

		Node p = findNode(index-1); // 找到索引的前一个节点
		if (p == null){
			// 链表为空,或者索引超出了范围
			System.out.println("插入失败");
			return;
		}
		// 找到索引的前一个节点
		Node newNode = new Node(value,p.next);
		p.next = newNode;
		System.out.println("插入成功");
	}

⑥:按照索引删除节点,先实现删除头结点,让head指向head.next

1.链表的实现:不带哨兵

	public void removeFirst(){
		if (head == null){
			System.out.println("链表为空,删除失败");
			return;
		}
		head = head.next; //
	}

 // 删除节点文章来源地址https://www.toymoban.com/news/detail-472729.html

	/**
	 * 删除节点:按照索引
	 */
	public void removeIndex(int index){
		if (index == 0){
			// 删除头结点
			removeFirst();
			return;
		}
		Node prev= findNode(index - 1);
		// 如果为空
		if (prev == null){
			// 链表为空或者超过了索引范围
			System.out.println("删除失败");
			return;
		}
		// 此时node是删除索引的前一个节点
        Node removed = prev.next;
        if (removed == null ){
            System.out.println("删除失败");
        }
		prev.next=removed.next;// 索引的前一个节点,指向索引的后一个节点
		System.out.println("删除成功");
	}

到了这里,关于1.链表的实现:不带哨兵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】双向链表的实现

    我要扼住命运的咽喉,他却不能使我完全屈服。                      --贝多芬 目录 一.带头循环的双向链表的特点 二.不带头不循环单向链表和带头循环的双向链表的对比 三.初始化链表,创建哨兵结点 四.双向链表的各种功能的实现 1.双向链表的尾插 2.双向链表的打印 

    2023年04月10日
    浏览(29)
  • 【(数据结构)— 双向链表的实现】

    注意: 这里的 “带头” 跟前面我们说的 “头节点” 是两个概念,实际前面的在单链表阶段称呼不严 谨,但是为了同学们更好的理解就直接称为单链表的头节点。 带头链表里的头节点,实际为 “哨兵位” ,哨兵位节点不存储任何有效元素,只是站在这里“放哨 的” “哨

    2024年02月06日
    浏览(35)
  • 数据结构——双向链表的实现

    注意: 双向链表又称带头双向循环链表 这⾥的“带头”跟前⾯我们说的“头节点”是两个概念,实际前⾯的在单链表阶段称呼不严 谨,但是为了同学们更好的理解就直接称为单链表的头节点。 带头链表⾥的头节点,实际为“ 哨兵位 ”,哨兵位节点不存储任何有效元素,只

    2024年02月06日
    浏览(35)
  • 数据结构:双向链表的实现(C实现)

    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 本篇博客,将要实现的是 带头双向循环链表 ,该结构实现尾插,尾删只需要O(1)的时间复杂度。 其结构如下所示: 既然要实现的链表是双向循环的,那么对于指针域,我们就需要 指向节点上一个的指针 和 指向节点

    2024年02月14日
    浏览(35)
  • 数据结构——链表的实现(Java版)

    目录 一、链表 二、代码实现 1.创建结点 2.构造函数 3.链表的相关属性 4.添加虚拟节点 5.判断链表是否为空 6.添加方法 (1)在头部添加 (2)在尾部添加 (3)在索引位置添加 (4)对头插法和尾插法代码进行简化(调用任意位置添加的方法) 7.打印链表(遍历,重写toString方

    2024年01月23日
    浏览(39)
  • 数据结构中链表的实现以及排序

    本期和大家主要分享的是关于数据结构中双向链表的实现过程,那么话不多说,来具体看看吧! 来分析一下,这里呢定义了一个int的数据类型,表明整个链表存放的是整形的数据;其次定义了链表节点的数据类型,其中包括了此节点存放的数据以及链接向下一个节点的地址;

    2024年02月02日
    浏览(31)
  • 数据结构-二叉链表的结构与实现

    目录 一、引言 二、什么是二叉链表 三、二叉链表的结构 四、二叉链表的实现 1. 创建二叉链表 2. 遍历二叉链表 3. 插入节点 4. 删除节点 五、应用场景 六、总结 七、代码示例 数据结构是计算机科学中的重要概念,它是计算机程序设计的基础。二叉链表是一种常见的数据结构

    2024年02月08日
    浏览(35)
  • 【数据结构】 链表简介与单链表的实现

    在【数据结构】 ArrayList简介与实战中我们已经熟悉了ArrayList的使用,并且进行了简单模拟实现。通过源码知道,ArrayList底层使用数组来存储元素 由于其底层是一段连续空间, 当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为

    2024年02月12日
    浏览(37)
  • 一起学数据结构(3)——万字解析:链表的概念及单链表的实现

    上篇文章介绍了数据结构的一些基本概念,以及顺序表的概念和实现,本文来介绍链表的概念和单链表的实现,在此之前,首先来回顾以下顺序表的特点: 1. 顺序表是一组地址连续的存储单元依次存储的线性表的数据结构,逻辑上:顺序表中相邻的数据元素,其物理次序也是

    2024年02月13日
    浏览(30)
  • 【数据结构】—带头双向循环链表的实现(完美链表)

    链表结构一共有八种形式,在前面的文章里已经讲完了不带头单向非循环链表的实现,但是我们发现该链表实现尾插与尾删时比较麻烦,要先从头节点进行遍历,找到尾节点,时间复杂度为O(N),而本次所讲的带头双向循环单链表,则可以直接找到尾节点。 虽然该链表看起来

    2024年01月25日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包