Java实现链表的常见操作算法
链表分为单链表,双向链表和循环链表,是一种链式存储结构,由一个个结点链式构成,结点包含数据域和指针域,其中单链表是只有一个指向后驱结点的指针,双向链表除头结点和尾结点外,每个结点都有一个前驱指针和一个后继指针,循环链表的尾结点的指针指向头结点.
相比数组而言,链表的插入和删除比较快,查询慢.
本文主要以单链表为例,介绍下链表的常用算法操作.
单链表的结构:
在java语言中,链表的每个结点用Node类来表示:
package com.linkedlist;
public class Node {
private int data;// 结点数据
private Node next;// 下一个结点
public Node(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
定义一个链表操作类,里面包含常用的操作:
package com.linkedlist;
import java.util.Hashtable;
public class LinkedListOperator {
private Node head = null;// 头结点
// 在链表的末尾增加一个结点
private void addNode(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
}
Node temp = head;
while (temp.getNext() != null) {
temp = temp.getNext();
}
temp.setNext(newNode);
}
// 打印链表结点
private void printLink() {
Node curNode = head;
while (curNode != null) {
System.out.println(curNode.getData());
curNode = curNode.getNext();
}
System.out.println("===========");
}
// 求链表长度
private int getLength() {
int len = 0;
Node curNode = head;
while (curNode != null) {
len++;
curNode = curNode.getNext();
}
return len;
}
// 删除某一个结点
private boolean delNode(int index) {
if (index < 1) {
return false;
}
if (index == 1) {
head = head.getNext();
return true;
}
Node preNode = head;
Node curNode = head.getNext();
int n = 1;
while (curNode.getNext() != null) {
if (n == index) {
preNode.setData(curNode.getData());
preNode.setNext(curNode.getNext());
return true;
}
preNode = preNode.getNext();
curNode = curNode.getNext();
n++;
}
if (curNode.getNext() == null) {
preNode.setNext(null);
}
return false;
}
// 链表排序:选择排序法,从小到大
private void sortList() {
Node curNode = head;
while (curNode != null) {
Node nextNode = curNode.getNext();
while (nextNode != null) {
if (curNode.getData() > nextNode.getData()) {
int temp = curNode.getData();
curNode.setData(nextNode.getData());
nextNode.setData(temp);
}
nextNode = nextNode.getNext();
}
curNode = curNode.getNext();
}
}
// 去掉重复元素
private void distinctLink() {
Hashtable<Integer, Integer> map = new Hashtable<Integer, Integer>();
Node curNode = head;
Node preNode = null;
while (curNode != null) {
if (map.containsKey(curNode.getData())) {
preNode.setData(curNode.getData());
preNode.setNext(curNode.getNext());
} else {
map.put(curNode.getData(), 1);
preNode = curNode;
}
curNode = curNode.getNext();
}
}
// 返回倒数第k个结点,定义两个指针,第一个指针向前移动K-1次,之后两个指针同时前进,
// 当第一个指针到达末尾时,第二个指针所在的位置即为倒数第k个结点
private Node getReverNode(int k) {
if (k < 1) {
return null;
}
Node first = head;
Node second = head;
for (int i = 0; i < k - 1; i++) {
first = first.getNext();
}
while (first.getNext() != null) {
first = first.getNext();
second = second.getNext();
}
return second;
}
// 反转链表
private void reserveLink() {
Node preNode = null;
Node curNode = head;
Node tempNode = null;
while (curNode != null) {
tempNode = curNode.getNext();
curNode.setNext(preNode);
preNode = curNode;
curNode = tempNode;
}
head = preNode;
}
// 寻找链表的中间结点
private Node getMiddleNode() {
Node slowNode = head;
Node quickNode = head;
while (slowNode.getNext() != null && quickNode.getNext() != null) {
slowNode = slowNode.getNext();
quickNode = quickNode.getNext().getNext();
}
return slowNode;
}
// 判断链表是否有环
private boolean isRinged() {
if (head == null) {
return false;
}
Node slowNode = head;
Node quickNode = head;
while (slowNode.getNext() != null && quickNode.getNext() != null) {
slowNode = slowNode.getNext();
quickNode = quickNode.getNext().getNext();
if (slowNode.getData() == quickNode.getData()) {
return true;
}
}
return false;
}
// 删除指定结点
private boolean delNode(Node node) {
if (node.getNext() == null) {
return false;// 在不知道头结点的情况下,没法删除单链表的尾结点
}
node.setData(node.getNext().getData());
node.setNext(node.getNext().getNext());
return true;
}
// 判断两个链表是否相交:相交的链表的尾结点相同
private boolean isCross(Node n1, Node n2) {
while (n1.getNext() != null) {
n1 = n1.getNext();
}
while (n2.getNext() != null) {
n2 = n2.getNext();
}
if (n1.getData() == n2.getData()) {
return true;
}
return false;
}
// 求相交链表的起始点
private Node getFirstCrossNode(LinkedListOperator l1, LinkedListOperator l2) {
int len = l1.getLength() - l2.getLength();
Node n1 = l1.head;
Node n2 = l2.head;
if (len > 0) {
for (int i = 0; i < len; i++) {
n1 = n1.getNext();
}
} else {
for (int i = 0; i < len; i++) {
n2 = n2.getNext();
}
}
while (n1.getData() != n2.getData()) {
n1 = n1.getNext();
n2 = n2.getNext();
}
return n1;
}
public static void main(String[] args) {
LinkedListOperator llo = new LinkedListOperator();
llo.addNode(10);
llo.addNode(4);
llo.addNode(6);
llo.addNode(8);
llo.printLink();
// llo.delNode(4);
// llo.sortList();
// llo.distinctLink();
// System.out.println(llo.getReverNode(3).getData());
// llo.reserveLink();
// System.out.println(llo.getMiddleNode().getData());
// System.out.println(llo.isRinged());
llo.delNode(llo.head.getNext().getNext());
llo.printLink();
}
}
未完待续...
Java实现链表的常见操作算法的更多相关文章
- Java实现7种常见密码算法
原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 前面在密码学入门一文中讲解了各种常见的密码学概念.算法与运用场景,但没有介绍过代码,因此,为作补充,这一篇将会介绍 ...
- Java中几种常见排序算法
日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数 ...
- Java的几种常见排序算法
一.所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法.排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面. ...
- 【知了堂学习笔记】java 编写几种常见排序算法3
排序的分类: 1.希尔排序 希尔排序是快速插入排序的改进版,希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序:随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰 ...
- 【知了堂学习笔记】java 编写几种常见排序算法
排序的分类: 一.交换排序 所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 1.冒泡 ...
- 【知了堂学习笔记】java 编写几种常见排序算法2
排序的分类: 1.直接选择排序 它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~ ...
- 【java】String类常见操作
秋招做题需要,总结String类常用api如下: 简单的:str.length().str.isEmpty().str.split(“;”)切割 1.字符串反转:借助StringBuilder/Str ...
- 读Hadoop3.2源码,深入了解java调用HDFS的常用操作和HDFS原理
本文将通过一个演示工程来快速上手java调用HDFS的常见操作.接下来以创建文件为例,通过阅读HDFS的源码,一步步展开HDFS相关原理.理论知识的说明. 说明:本文档基于最新版本Hadoop3.2. ...
- java实现单链表常见操作
一.概述: 本文主要总结单链表常见操作的实现,包括链表结点添加.删除:链表正向遍历和反向遍历.链表排序.判断链表是否有环.是否相交.获取某一结点等. 二.概念: 链表: 一种重要的数据结构,HashM ...
随机推荐
- 查找linux下进程占用CPU过高的原因,以php-fpm为例
很多时候,线上服务器的进程在某时间段内长时间占用CPU过高,为了优化,我们需要找出原因. 1.找出占用CPU最高的10个进程 ps aux | sort -k3nr | head -n 10 或查看占 ...
- mysql学习记录
干净卸载mysql:https://blog.csdn.net/cxy_summer/article/details/70142322mysql 解压缩版安装说明:https://jingyan.ba ...
- Python实现对CSV文件的读写功能
我们要处理csv文件,首先要的导入csv模块 import csv #读取csv文件def readCsv(path): #传入变量csv文件的路径 list=[] #定义一个空列表 with ope ...
- centos7 安装 redis4.0.8
1.安装lrzsz yum install lrzsz -y 2.利用rz命令将window中从redis官网下载好的“redis-4.0.8.tar.gz” 拷贝到centos中 redis官网 : ...
- win10无法访问服务器上的共享文件夹怎么设置,提示:你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问
此问题需要修改Win10 网络策略 按window+R键输入gpedit.msc 来启动本地组策略编辑器. 依次找到“计算机配置-管理模板-网络-Lanman工作站”这个节点,在右侧内容区可以看到“启 ...
- 初学html,任务1:一个简单html页面,要求:内容页面装一篇文章 用html来分段
这是主要内容部分,用html实现版块分布. 接下来是样式部分. 让页面所有元素的padding和margin都设置为0 : 否则加入一张大的覆盖的背景图片后,会由于浏览器的缘故,图片周边有白边: 设置 ...
- tensorflow 源码编译
https://blog.csdn.net/xsfl1234/article/details/67669707 https://blog.csdn.net/guxi123/article/detail ...
- mac ssh,mac xshell,xshell替代,ssh客户端,ssh工具,远程桌面加速
下载地址 Windows版下载地址:http://www.hostbuf.com/downloads/finalshell_install.exe Mac版,Linux版安装及教程:http://ww ...
- 别人的Linux私房菜(20)启动流程、模块管理与Loader
系统启动时,首先加载BIOS,通过BOIS读取COMS的硬件信息,进行自我检测,取得第一个可启动的设备(多个根据设置有关). 读取并执行设备内的MBR启动引导程序,引导程序调用boot sector中 ...
- Code First的实体继承模式
Entity Framework的Code First模式有三种实体继承模式 1.Table per Type (TPT)继承 2.Table per Class Hierarchy(TPH)继承 3 ...