IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构与算法---单链表 -> 正文阅读

[数据结构与算法]数据结构与算法---单链表

单链表

  • 单链表的逻辑结构:
    在这里插入图片描述

  • 单链表在内存中的存储:
    在这里插入图片描述
    小结:
    1)链表是以结点的方式来存储,是链式存储
    2)每个结点包括data域和next域(指向下一个结点)
    3)链表的各个结点不一定是链式存储,逻辑结构上连续,物理结构上不一定连续
    4)根据实际需求来确定链表是否需要头结点

  • 单链表的创建和遍历

添加操作:

//	 添加结点到链表(直接添加到链表的最后)
	public void add(HeroNode heronode) {
//	 	因为头结点不能动,辅助指针帮忙遍历
		HeroNode temp = firstnode;
		while (true) {
			// 找到链表的最后
			if (temp.next == null) {
				break;
			}
			temp = temp.next;
		}
//		当退出while循环时,就找到了链表的最后
//		将最后这个结点的next指向新结点
		temp.next = heronode;
	}

遍历:

//	显示链表
	public void list() {
//		判断链表是否为空
		if (firstnode.next == null) {
			System.out.println("链表为空");
			return;
		}
//		因为头结点不能动,所以需要一个辅助指针
		HeroNode temp = firstnode.next;
		while (true) {
//			判断链表是否到最后
			if (temp == null) {
				break;
			}
//			输出结点的信息
			System.out.println(temp);
			temp = temp.next;
		}
	}

对添加的优化(根据no添加到指定位置):

//  首先找到新添加的结点的位置(通过辅助指针),通过遍历
//	将辅助指针.next赋值给新添加的结点 新结点.next = temp.next
//	把新添加结点的地址赋值给辅助指针.next temp.next = 新结点
	public void addByOrder(HeroNode heronode) {
		HeroNode temp = firstnode;
		boolean flag = false;
//		头结点不能动,通过辅助指针找到添加的位置
//		因为单链表,因为我们找的temp是位于添加位置的前一个结点,否则插入不了
		while (true) {
//		 	说明temp已经在链表最后
			if (temp.next == null) {
				break;
			}
//			位置找到
			if (temp.next.number > heronode.number) {
				break;
//				新添加结点的编号已存在
			} else if (temp.next.number == heronode.number) {
				flag = true;
				break;
			}
//			后移遍历当前链表
			temp = temp.next;
		}
//		判断flag的值,flag为true即编号已存在,不能添加
		if (flag) {
			System.out.println("准备插入的编号:" + heronode.number + "\n" + "已存在");
		} else {
//			插入到链表
			heronode.next = temp.next;
			temp.next = heronode;
		}
	}

单链表结点的修改:

//	单链表结点的修改
//	1.根据newheronode的编号number来修改
	public void update(HeroNode newheronode) {
		if (firstnode.next == null) {
			System.out.println("链表为空");
		}
//		链表不为空,根据编号找到需要修改的结点,通过辅助指针
		HeroNode temp = firstnode.next;
		boolean flag = false;// 表示是否找到
		while (true) {
//			已经遍历完链表
			if (temp == null) {
				break;
			}
//			找到需要修改的结点
			if (temp.number == newheronode.number) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
//		根据flag判断是否找到需要修改的结点
		if (flag) {
			temp.name = newheronode.name;
			temp.nickname = newheronode.nickname;
		} else {
			System.out.println("没有找到编号为 " + newheronode.number + "的结点" + "\t" + "不能修改");
		}
	}

删除:
注意:因为此时是单链表,必须找到待删除结点的前一个结点,否则删除不了。

	public void dellist(HeroNode heronode) {
		HeroNode temp = firstnode;
//		HeroNode temp = firstnode.next
//		这样写会导致当要删除的结点为第一个的时候,遍历不到
		boolean flag = false;
		while (true) {
//			链表已经到最后
			if (temp.next == null) {
				break;
			}
//			找到待删除结点的前一个结点
			if (temp.next.number == heronode.number) {
				flag = true; // 将指向需要删除的结点再往后移,此时需要删除的结
				break; // 点无指向,所以遍历不到,即删除
			}
//			后移
			temp = temp.next;
		}
//		flag为true即找到
		if (flag) {
			temp.next = temp.next.next;
//			temp.next = heronode.next;
		} else {
			System.out.println("要删除的结点:" + heronode.number + "\t" + "不存在");
		}
	}
  • 求单链表有效结点的个数
//	不包含头结点
	public static int count(HeroNode head) {
		HeroNode temp = head.next;
		int count = 0;
		while (true) {
			if (temp == null) {
				break;
			}
			temp = temp.next;
			count++;
		}
		return count;
	}
  • 查找单链表中倒数第k个结点
    核心:通过[ 链表的大小(有效结点)-k = 移动的次数 ] 定位到查找的结点。
//  查找单链表中倒数第k个结点
	public static HeroNode getLastNode(HeroNode head, int index) {
		HeroNode temp = head.next;
		int size = getLength(head);
		if (head.next == null) {
			return null;
		}
		if (index <= 0 || index > size) {
			return null;
		}
//		for循环定位到倒数的index
		for (int i = 0; i < size - index; i++) {
			temp = temp.next;
		}
		return temp;
	}
  • 单链表的反转
    头插法:
    核心:将新链表的next域赋值给要插入结点的next域 —> node.next = reverse.next
    将要插入的结点赋值给新链表的next域 —>reverse.next = node
	public static void reverseList(HeroNode head) {
//		判断当前链表是否为空或者只有一个结点,是则无需反转
		if (head.next == null || head.next.next == null) {
			return;
		}
		HeroNode newNode = new HeroNode(0, "", "");
		HeroNode temp = null;
//		HeroNode temp = head.next;
		HeroNode cur = head.next;
		while (cur != null) {
			temp = cur.next;
//			temp = temp.next;
//			这一步解释了为什么需要temp指针
//			如果没有temp指针,那么原先链表后面的结点遍历不到了
			cur.next = newNode.next;
			newNode.next = cur;
			cur = temp;
		}
		head.next = newNode.next;
	}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:38:39  更:2021-08-17 15:39:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 17:06:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计