Java模拟有序链表数据结构的示例
作者:匆忙拥挤repeat 发布时间:2023-09-26 22:25:30
标签:Java,链表
有序链表:
按关键值排序。删除链头时,就删除最小(/最大)的值,插入时,搜索插入的位置。
插入时需要比较O(N),平均O(N/2),删除最小(/最大)的在链头的数据时效率为O(1),
如果一个应用需要频繁的存取(插入/查找/删除)最小(/最大)的数据项,那么有序链表是一个不错的选择
优先级队列 可以使用有序链表来实现
有序链表的插入排序:
对一个无序数组,用有序链表来排序,比较的时间级还是O(N^2)
复制时间级为O(2*N),因为复制的次数较少,第一次放进链表数据移动N次,再从链表复制到数组,又是N次
每插入一个新的链结点,不需要复制移动数据,只需要改变一两个链结点的链域
import java.util.Arrays;
import java.util.Random;
/**
* 有序链表 对数组进行插入排序
* @author stone
*/
public class LinkedListInsertSort<T extends Comparable<T>> {
private Link<T> first; //首结点
public LinkedListInsertSort() {
}
public boolean isEmpty() {
return first == null;
}
public void sortList(T[] ary) {
if (ary == null) {
return;
}
//将数组元素插入进链表,以有序链表进行排序
for (T data : ary) {
insert(data);
}
//
}
public void insert(T data) {// 插入 到 链头, 以从小到大排序
Link<T> newLink = new Link<T>(data);
Link<T> current = first, previous = null;
while (current != null && data.compareTo(current.data) > 0) {
previous = current;
current = current.next;
}
if (previous == null) {
first = newLink;
} else {
previous.next = newLink;
}
newLink.next = current;
}
public Link<T> deleteFirst() {//删除 链头
Link<T> temp = first;
first = first.next; //变更首结点,为下一结点
return temp;
}
public Link<T> find(T t) {
Link<T> find = first;
while (find != null) {
if (!find.data.equals(t)) {
find = find.next;
} else {
break;
}
}
return find;
}
public Link<T> delete(T t) {
if (isEmpty()) {
return null;
} else {
if (first.data.equals(t)) {
Link<T> temp = first;
first = first.next; //变更首结点,为下一结点
return temp;
}
}
Link<T> p = first;
Link<T> q = first;
while (!p.data.equals(t)) {
if (p.next == null) {//表示到链尾还没找到
return null;
} else {
q = p;
p = p.next;
}
}
q.next = p.next;
return p;
}
public void displayList() {//遍历
System.out.println("List (first-->last):");
Link<T> current = first;
while (current != null) {
current.displayLink();
current = current.next;
}
}
public void displayListReverse() {//反序遍历
Link<T> p = first, q = first.next, t;
while (q != null) {//指针反向,遍历的数据顺序向后
t = q.next; //no3
if (p == first) {// 当为原来的头时,头的.next应该置空
p.next = null;
}
q.next = p;// no3 -> no1 pointer reverse
p = q; //start is reverse
q = t; //no3 start
}
//上面循环中的if里,把first.next 置空了, 而当q为null不执行循环时,p就为原来的最且一个数据项,反转后把p赋给first
first = p;
displayList();
}
class Link<T> {//链结点
T data; //数据域
Link<T> next; //后继指针,结点 链域
Link(T data) {
this.data = data;
}
void displayLink() {
System.out.println("the data is " + data.toString());
}
}
public static void main(String[] args) {
LinkedListInsertSort<Integer> list = new LinkedListInsertSort<Integer>();
Random random = new Random();
int len = 5;
Integer[] ary = new Integer[len];
for (int i = 0; i < len; i++) {
ary[i] = random.nextInt(1000);
}
System.out.println("----排序前----");
System.out.println(Arrays.toString(ary));
System.out.println("----链表排序后----");
list.sortList(ary);
list.displayList();
}
}
打印
----排序前----
[595, 725, 310, 702, 444]
----链表排序后----
List (first-->last):
the data is 310
the data is 444
the data is 595
the data is 702
the data is 725
单链表反序:
public class SingleLinkedListReverse {
public static void main(String[] args) {
Node head = new Node(0);
Node temp = null;
Node cur = null;
for (int i = 1; i <= 10; i++) {
temp = new Node(i);
if (i == 1) {
head.setNext(temp);
} else {
cur.setNext(temp);
}
cur = temp;
}//10.next = null;
Node h = head;
while (h != null) {
System.out.print(h.getData() + "\t");
h = h.getNext();
}
System.out.println();
//反转1
// h = Node.reverse1(head);
// while (h != null) {
// System.out.print(h.getData() + "\t");
// h = h.getNext();
// }
//反转2
h = Node.reverse1(head);
while (h != null) {
System.out.print(h.getData() + "\t");
h = h.getNext();
}
}
}
/*
* 单链表的每个节点都含有指向下一个节点属性
*/
class Node {
Object data;//数据对象
Node next; //下一节点
Node(Object d) {
this.data = d;
}
Node(Object d, Node n) {
this.data = d;
this.next = n;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
//方法1 head被重置
static Node reverse1(Node head) {
Node p = null; //反转后新的 头
Node q = head;
//轮换结果:012,123,234,.... 10 null null
while (head.next != null) {
p = head.next; // 第1个 换成第2个 这时p表示原始序列头中的next
head.next = p.next; // 第2个 换成第3个
p.next = q; //已经跑到第1位置的原第2个的下一个 就要变成 原第1个
q = p; //新的第1个 要变成 当前第一个
}
return p;
}
//方法2 head没重置
static Node reverse2(Node head) {
//将中间节点的指针指向前一个节点之后仍然可以继续向后遍历链表
Node p1 = head, p2 = head.next, p3; // 前 中 后
//轮换结果 :012, 123, 234, 345, 456.... 9 10 null
while (p2 != null) {
p3 = p2.next;
p2.next = p1; //指向后 变 指向前
p1 = p2; //2、3向前挪
p2 = p3;
}
head.next = null;//head没变,当输出到0时,再请求0.next 为1
return p1;
}
}
0
投稿
猜你喜欢
- 一、Spring Bean 集合注入在【Spring学习笔记(三)】已经讲了怎么注入基本数据类型和引用数据类型,接下来介绍如何注入比较特殊的
- 1.前提已经配置Sleuth,可参考2.什么是Zipkin?官网:https://zipkin.io/大规模分布式系统的APM工具( App
- 日常对于金额计算,应该都是用的BigDecimal,可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这
- 1 请求映射 在SpringBoot中使用@XxxMapping注解完成前端请求与后端方法的一个映射。以前的时候,通常使用url映射命名的
- 本文实例讲述了java生成XML的方法。分享给大家供大家参考,具体如下:下拉框的生成,我是通过javascript读取xml文件生成的。Xm
- 开发环境win10Android Studio效果用于多级菜单展示,或选择。如 每个省,市,县;如 树木的病虫害;关键代码 @overrid
- 相关api见:点击进入/* * Copyright 2014 the original author or authors. * * Lic
- 直接来,RequestDemo5代码,get请求和post请求都请求转发了,转发到RequestDemo6请求 RequestDe
- 1、右值1.1 简介首先区分一下左右值:左值是指存储在内存中、有明确存储地址(可取地址)的数据;右值是指可以提供数据值的数据(不可取地址)如
- 本文介绍了SpringCloud +Zookeeper完成配置中心,分享给大家,具有如下:使用场景项目配置更改不需要打包,重启提供配置文件的
- 在linux主机部署Eureka高可用方案的时候,发现注册到服务中心的服务IP是随机的,由于主机的网卡是多个,随机的IP并不是自己想要的,上
- Spring JPA 增加字段执行异常用Spring jpa Entity里面增加了几个字段,但启动报错,提示column Unable t
- 1.用途在SpringBoot中,通过jasypt可以进行加密解密. 这个是双向的, 且可以配置密钥.2.使用:2.1通过UT创建工具类,并
- rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统。它遵循Mozilla Public License开源协议,采用
- 释放公平锁(基于JDK1.7.0_40)1. unlock()unlock()在ReentrantLock.java中实现的,源码如下:pu
- 之前在Spring Boot启动过程(二)提到过createEmbeddedServletContainer创建了内嵌的Servlet容器,
- 在Java中,可以通过Runtime类或ProcessBuilder类来实现调用外部程序。Runtime类与ProcessBuilder类使
- 若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的。 通常情况下, 静
- 一、特性无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对
- Java基于对象流实现银行系统的具体代码,供大家参考,具体内容如下系统特点:数据持久化到文件中,系统启动后,加载文件中数据到集合中,相当于做