Java实现单链表的各种操作

主要内容:1.单链表的基本操作

     2.删除重复数据

     3.找到倒数第k个元素

       4.实现链表的反转

       5.从尾到头输出链表

     6.找到中间节点

     7.检测链表是否有环

     8.在不知道头指针的情况下删除指定节点

     9.如何判断两个链表是否相交并找出相交节点

直接上代码,就是这么奔放~~~

package pers.ty.$1101datastructure;

import java.util.Hashtable;

/**
* @author Administrator
* 实现单链表的基本操作,增加删除节点、排序、打印、计算长度
*/
public class MyLinkedList {
Node head = null;//链表头的作用
/**向链表中插入数据
* @param d:插入数据的内容
*/
public void addNode(int d){
Node newNode=new Node(d);
if(head==null){
head=newNode;
return;
}
Node tmp=head;
while(tmp.next!=null){
tmp=tmp.next;
}
//add Node to end
tmp.next=newNode;
}
/**
* @param index:删除第index个节点
* @return 成功返回true,失败返回false
*/
public Boolean deleteNode(int index){
if(index<1||index>length()){
return false;//删除元素位置不合理
}
//删除链表中的第一个元素
if(index==1){
head=head.next;
return true;
}
int i=1;
Node preNode=head;
Node curNode=preNode.next;
while(curNode!=null){
if(i==index){
preNode.next=curNode.next;
return true;
}
preNode=curNode;
curNode=curNode.next;
i++;
}
return true;
}
/**
* @return 返回链表的长度length
*/
public int length(){
int length=0;
Node tmp=head;
while(tmp!=null){
length++;
tmp=tmp.next;
}
return length;
}
/**
* 对链表进行排序
* @return 返回排序后的头结点
*/
public Node orderList(){
Node nextNode=null;
int temp=0;
Node curNode=head;
while(curNode.next!=null){
nextNode=curNode.next;
while(nextNode!=null){
if(curNode.data>nextNode.data){
temp=curNode.data;
curNode.data=nextNode.data;
nextNode.data=temp;
}
nextNode=nextNode.next;
}
curNode=curNode.next;
}
return head;
}
/**
* 打印链表中所有数据
*/
public void printList(){
Node tmp=head;
while(tmp!=null){
System.out.print(tmp.data+" ");
tmp=tmp.next;
}
System.out.println();
}
/**
* 从链表中删除数据的第一种方法
* 遍历链表,把遍历到的数据存到一个Hashtable中,在遍历过程中若当前访问的值在Hashtable
* 中存在,则可以删除
* 优点:时间复杂度低 缺点:需要额外的存储空间来保存已访问过得数据
*/
public void deleteDuplecate1(){
Hashtable<Integer,Integer> table=new Hashtable<Integer,Integer>();
Node tmp=head;
Node pre=null;
while (tmp!=null) {
if(table.containsKey(tmp.data))
pre.next=tmp.next;
else{
table.put(tmp.data, 1);
pre=tmp;
}
tmp=tmp.next;
}
}
/**
* 从链表中删除重复数据的第二种方法
* 双重循环遍历
* 优缺点很明显
*/
public void deleteDuplecate2(){
Node p=head;
while (p!=null) {
Node q=p;
while(q.next!=null){
if(p.data==q.next.data){
q.next=q.next.next;
}else{
q=q.next;
}
}
p=p.next;
}
}
/**
* @param k:找到链表中倒数第k个节点
* @return 该节点
* 设置两个指针p1、p2,让p2比p1快k个节点,同时向后遍历,当p2为空,则p1为倒数第k个节点
*/
public Node findElem(Node head,int k){
if(k<1||k>this.length())
return null;
Node p1=head;
Node p2=head;
for (int i = 0; i < k-1; i++)
p2=p2.next;
while (p2.next!=null) {
p2=p2.next;
p1=p1.next;
}
return p1;
}
/**
* 实现链表的反转
* @param head链表的头节点
*/
public void reverseIteratively(Node head){
Node pReversedHead=head;
Node pNode=head;
Node pPrev=null;
while (pNode!=null) {
Node pNext=pNode.next;
if(pNext==null)
pReversedHead=pNode;
pNode.next=pPrev;
pPrev=pNode;
pNode=pNext;
}
this.head=pReversedHead;
}
/**
* 通过递归从尾到头输出单链表
* @param head
*/
public void printListReversely(Node head){
if(head!=null){
printListReversely(head.next);
System.out.print(head.data+" ");
}
}
/**
* 查询单链表的中间节点
* 定义两个指针,一个每次走一步,一个每次走两步...
* @param head
* @return q为中间节点
*/
public Node searchMid(Node head){
Node q=head;
Node p=head;
while (p!=null&&p.next!=null&&p.next.next!=null) {
q=q.next;
p=p.next.next;
}
return q;
}
/**
* 在不知道头指针的情况下删除指定节点
* 链表尾节点无法删除,因为删除后无法使其前驱节点的next指针置为空
* 其他节点,可以通过交换这个节点与其后继节点的值,然后删除后继节点
* @param n
* @return
*/
public boolean deleteNode(Node n){
if(n==null||n.next==null)
return false;
int tmp=n.data;
n.data=n.next.data;
n.next.data=tmp;
n.next=n.next.next;
return true;
}
/**
* 判断两个链表是否相交
* 如果两个链表相交,则肯定有相同的尾节点,遍历两个链表,记录尾节点,看是否相同
* @param h1链表1的头节点
* @param h2链表2的头结点
* @return 是否相交
*/
public boolean isIntersect(Node h1,Node h2){
if(h1==null||h2==null)
return false;
Node tail1=h1;
while (tail1.next!=null){
tail1=tail1.next;
}
Node tail2=h2;
while(tail2.next!=null){
tail2=tail2.next;
}
return tail1==tail2;
}
/**
* 找出相交的第一个节点
* @param h1
* @param h2
* @return
*/
public Node getFirstMeetNode(Node h1,Node h2){
if(h1==null||h2==null)
return null;
Node tail1=h1;
int len1=1;
while (tail1.next!=null){
tail1=tail1.next;
len1++;
}
Node tail2=h2;
int len2=1;
while(tail2.next!=null){
tail2=tail2.next;
len2++;
}
if(tail1!=tail2){
return null;
}
Node t1=h1;
Node t2=h2;
//找出较长的链表先遍历
if(len1>len2){
int d=len1-len2;
while(d!=0){
t1=t1.next;
d--;
}
}
if(len1<len2){
int d=len2-len1;
while(d!=0){
t2=t2.next;
d--;
}
}
while(t1!=t2){
t1=t1.next;
t2=t2.next;
}
return t1;
}
public static void main(String[] args) {
MyLinkedList list=new MyLinkedList(); }
}

Java实现单链表的各种操作的更多相关文章

  1. Java实现单链表反转操作

    单链表是一种常见的数据结构,由一个个节点通过指针方式连接而成,每个节点由两部分组成:一是数据域,用于存储节点数据.二是指针域,用于存储下一个节点的地址.在Java中定义如下: public class ...

  2. JAVA数据结构——单链表

    链表:一. 顺序存储结构虽然是一种很有用的存储结构,但是他有如下几点局限性:1. 因为创造线性表的时候已经固定了空间,所以当需要扩充空间时,就需要重新创建一个地址连续的更大的存储空间.并把原有的数据元 ...

  3. java实现单链表的增删功能

    JAVA 实现单链表的增删功能 package linked; class LinkedTable{ } public class LinkedTableTest { public static vo ...

  4. 使用java实现单链表(转载自:https://www.cnblogs.com/zhongyimeng/p/9945332.html)

    使用java实现单链表----(java中的引用就是指针)转载自:https://www.cnblogs.com/zhongyimeng/p/9945332.html ? 1 2 3 4 5 6 7 ...

  5. java实现单链表常见操作

    一.概述: 本文主要总结单链表常见操作的实现,包括链表结点添加.删除:链表正向遍历和反向遍历.链表排序.判断链表是否有环.是否相交.获取某一结点等. 二.概念: 链表: 一种重要的数据结构,HashM ...

  6. 数据结构——Java实现单链表

    一.分析 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点由元素和指针构成.在Java中,我们可以将单链表定义成一个类,单链表的基 ...

  7. (java实现)单链表

    什么是单链表 在了解单链表之前,你知道什么是链表吗?如果你不知道什么是链表,可以看看我的这篇博客<链表-LinkList> 单链表是链表的其中一种基本结构.一个最简单的结点结构如图所示,它 ...

  8. java实现单链表、栈、队列三种数据结构

    一.单链表 1.在我们数据结构中,单链表非常重要.它里面的数据元素是以结点为单位,每个结点是由数据元素的数据和下一个结点的地址组成,在java集合框架里面 LinkedList.HashMap(数组加 ...

  9. Java解释单链表中的头插法以及尾插法

    单链表属于数据结构中的一种基本结构,是一种线性结构,在此使用Java对其中的头插法以及尾插法进行解释. 首先定义好链表中的节点类: 其中,data代表节点所存放的数据,next代表指向下一节点 对于单 ...

随机推荐

  1. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  2. 数据库设计中的Soft Delete模式

    最近几天有点忙,所以我们今天来一篇短的,简单地介绍一下数据库设计中的一种模式——Soft Delete. 可以说,该模式毁誉参半,甚至有非常多的人认为该模式是一个Anti-Pattern.因此在本篇文 ...

  3. ABP(现代ASP.NET样板开发框架)系列之14、ABP领域层——领域事件(Domain events)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之14.ABP领域层——领域事件(Domain events) ABP是“ASP.NET Boilerplate P ...

  4. Spark join 源码跟读记录

    PairRDDFunctions类提供了以下两个join接口,只提供一个参数,不指定分区函数时默认使用HashPartitioner;提供numPartitions参数时,其内部的分区函数是HashP ...

  5. iOS开发入门知识归纳

    一.iOS-C基础 二.iOS-Objective-C基础 三.iOS-Swift编程 三.iOS开发简单介绍 四.iOS-UI基础 1.UI控件介绍 2.UI布局-屏幕适配 五.iOS-多线程基础 ...

  6. 架构设计:负载均衡层设计方案(3)——Nginx进阶

    版权声明:欢迎转载,但是看在我辛勤劳动的份上,请注明来源:http://blog.csdn.net/yinwenjie(未经允许严禁用于商业用途!) 目录(?)[-] Nginx继续进阶 1gzip ...

  7. 06.移动先行之谁主沉浮----我的代码我来写(Xaml的优势)

    如果移动方向有任何问题请参考===> 异常处理汇总-移动系列(点) 前面几节课,我们都是在前台创建对象,进行一些设置,那么我们为什么不用传统的方法来编程呢? 我们今天来试试你就明了了~~ 打开M ...

  8. 5.SVM核函数

    核函数(Kernels) 定义 1.1 (核或正定核) 设是中的一个子集,称定义在上的函数是核函数,如果存在一个从到Hilbert空间的映射 使得对任意的,都成立.其中表示Hilbert空间中的内积. ...

  9. Angular学习-指令入门

    1.指令的定义 从用户的角度来看,指令就是在应用的模板中使用的自定义HTML标签.指令可以很简单,也可以很复杂.AngularJS的HTML编译器会解析指令,增强模板的功能.也是组件化未来的发展趋势, ...

  10. 趣说游戏AI开发:对状态机的褒扬和批判

    0x00 前言 因为临近年关工作繁忙,已经有一段时间没有更新博客了.到了元旦终于有时间来写点东西,既是积累也是分享.如题目所示,本文要来聊一聊在游戏开发中经常会涉及到的话题--游戏AI.设计游戏AI的 ...