用Java语言实现单向链表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Java语言实现单向链表相关的知识,希望对你有一定的参考价值。

单向链表的实现:
1.链表的结点:
一个单向链表是一组结点(数据元素)的序列,每个结点有两个域:数据域和指针域。
2.指针:
指针域存放其后继结点的地址,最后一个结点的指针域为空。头指针head指向链表的第一个结点,当链表为空时,头指针为空值。
3.结点的数据域:
-数据域存放数据,可能是三角形、矩形、圆形三种形状中的任何一种。
-形状除了具有与大小有关的属性外,还有颜色属性。
4.链表需要实现的功能:
(1)生成链表;
-根据输入生成链表
-生成一条长度为6、节点中的形状随机、颜色随机、大小均为10的链表。(其中大小为10的含义是指:三角形或矩形的边长都为10,圆的半径都为10。)
(2)链表中结点的插入与删除;
(3)在链表中删掉某类(三角形、圆形、矩形)的结点
(4)将链表中具有某种颜色A的节点改为颜色B。

1.先定义一个节点类

package com.buren;

public class IntNode
//定义一个节点类

int
info;
//定义属性,节点中的值
IntNode next;
//定义指向下一个节点的属性

public IntNode(int
i) //构造一个next为空的节点
this(i,null);


public IntNode(int i,IntNode
n) //构造值为i指向n的节点
info=i;
next=n;




2.再定义一个链表类,这是主要部分

package com.buren;

public class IntSLList

private IntNode head,tail;
//定义指向头结点和尾结点的指针,
//如果大家看着这个不像指针的话,那就需要对指针有更深刻的了解

public
IntSLList()
//定义一个空节点
head=tail=null;


public boolean
isEmpty()
//判断节点是否为空
return
head==null;
//这行代码看起来似乎很神奇,其实真的很神奇,偶是服了


public void addToHead(int el)
//将el插入到头结点前
head=new
IntNode(el,head);
//将节点插入到头结点前,作为新的投节点
if(head==tail)
//给空链表插入节点时
tail=head;
//头结点和尾结点指向同一个节点



public void addToTail(int
el)
//向链表的尾部增加结点
if(!isEmpty())
//判断链表是否为空
tail.next=new
IntNode(el);
//新建立一个值为el的节点,将链表的尾结点指向新节点
tail=tail.next;
//更新尾指针的指向
else
head=tail=new
IntNode(el);
//如果链表为空,新建立一个节点,将头尾指针同时指向这个节点



public int
deleteFromHead()
//删除头结点,将节点信息返回
int
el=head.info;
//取出节点信息
if(head==tail)
//如果链表中只有一个节点
head=tail=null;
//删除这一个节点
else
head=head.next;
//如果链表中不止一个节点,将头结点的下一个节点作为头结点

return
el;
//返回原头结点的值


public int
deleteFromTail()
//删除尾结点,返回尾结点的信息
int
el=tail.info;
//取出尾结点的值
if(head==tail)
// 如果链表中只有一个节点
head=tail=null;
//删除这个节点
else
IntNode
temp;
//定义中间变量
for(temp=head;temp.next!=tail;temp=temp.next);
//找出尾结点的前一个节点,注意最后的分号,

//这个for循环是没有循环体的,目的在于找出尾结点的前一个节点

//在整个程序中用了很多次这样的写法,相当经典啊
tail=temp;
//将找出来的节点作为尾结点,删除原来的尾结点
tail.next=null;
//将新尾结点的指向设为空

return
el;
//返回原尾结点的信息


public void
printAll()
//打印链表中所有节点的信息
if(isEmpty())
//如果链表为空
System.out.println("This
list is
empty!");
//输出提示信息
return;
//返回到调用的地方

if(head==tail)
//当链表中只有一个节点时
System.out.println(head.info);
//输出这个节点的信息,就是头结点的信息
return;

IntNode
temp;
//定义一个中间变量
for(temp=head;temp!=null;temp=temp.next)
//遍历整个链表
System.out.print(temp.info+"
");
//输出每个节点的信息

System.out.println();
//输出一个换行,可以没有这一行


public boolean isInList(int
el)
//判断el是否存在于链表中
IntNode
temp;
//定义一个中间变量
for(temp=head;temp!=null
&&
temp.info!=el;temp=temp.next);
//将el找出来,注意最后的分
return
temp!=null;
// 如果存在返回true,否则返回flase,这两行代码很有思想


public void delete(int
el)
//删除链表中值为el的节点
if(head.info==el
&&
head==tail)
//如果只有一个节点,并且节点的值为el
head=tail=null;
//删除这个节点
else
if(head.info==el)
// 不止一个节点,而头结点的值就是el
head=head.next;
//删除头结点
else
IntNode
pred,temp;
//定义两个中间变量
for(pred=head,temp=head.next;temp.info!=el
&&
temp.next!=null;pred=pred.next,temp=temp.next);
//跟上面的类似,自己琢磨吧,也是要注意最后的分号
pred.next=temp.next;
//将temp指向的节点删除,最好画一个链表的图,有助于理解
if(temp==tail)
//如果temp指向的节点是尾结点
tail=pred;
//将pred指向的节点设为尾结点,




//下面这个方法是在链表中值为el1的节点前面插入一个值为el2的节点,
//用类似的思想可以再写一个在链表中值为el1的节点后面插入一个值为el2的节点
public boolean insertToList(int el1,int
el2)
//定义一个插入节点的方法,插入成功返回true,否则返回false
IntNode
pred,temp; //定义两个中间变量
if(isEmpty())
//判断链表是否为空
return
false;
//如果链表为空就直接返回false

if(head.info==el1
&&
head==tail)
//如果链表中只有一个节点,并且这个节点的值是el1
head=new
IntNode(el2,head);
//新建立一个节点
return
true;
else if(head.info==el1)
IntNode t=new
IntNode(el2);
t.next=head;
head=t;
return
true;
else
for(pred=head,temp=head.next;temp!=null
&&
temp.info!=el1;pred=pred.next,temp=temp.next);
if(temp!=null)
IntNode
a=new IntNode(el2);
pred.next=a;
a.next=temp;
return
true;
else
System.out.println(el1+"
NOT EXEISTS!");
return
false;




3.下面是测试代码
public static void main(String[] args)
IntSLList test=new
IntSLList();

//test.addToHead(7);
test.addToTail(7);

System.out.println(test.insertToList(7,5));
test.printAll();
System.out.println(test.isInList(123));

参考技术A 实现代码如下:

erface StackPK
void Push(Object obj);
Object Pop;
boolean isEmpty;
Size;


public LinkStack implements StackPK
private SLLNode
private Object data;
private SLLNode next;
SLLNode
SLLNode(Object obj)
data=obj;


public void Data(Object o)
(onull)
throw IllegalArgumentException("object is null");
data=o;

public Object getData
data;

public void Next(SLLNode n)
next=n;

public SLLNode getNext
next;

public String toString
(String)data;



private SLLNode top;
public LinkStack
top=null;

public void Push(Object obj)
(objnull)
throw IllegalArgumentException("n is null");
(topnull)

SLLNode temp= SLLNode(obj);
top=temp;



SLLNode temp= SLLNode(obj);
temp.Next(top);
top=temp;


public Object Pop
SLLNode temp;
(topnull)
throw IllegalArgumentException("stack is empty");
temp=top;
top=top.getNext;
temp.getData;

public boolean isEmpty
(top null)
true;

false;

public Size
SLLNode cnt;
cnt=top;
count=0;
(cnt null)
0;
while(cnt != null)
count;
cnt=cnt.getNext;

count;

public void (String args)
LinkStack ls= LinkStack;
Object arr= String"liangming","gaojie","liangbing","wuxia","zhangjun";
for( i=0;i<arr.length;i)
ls.Push(arr[i]);
while(ls.Size>0)

.out.prln(ls.Pop);


本回答被提问者采纳

单向链表的简单Java实现-sunziren

  写在前面,csdn的那篇同名博客就是我写的,我把它现在在这边重新发布,因为我实在不想用csdn了,那边的广告太多了,还有就是那个恶心人的“阅读更多”按钮,惹不起我躲得起。


  最近面试的过程中,发现有的公司的面试题考到了链表的逆序,这一块我正好不是特别清楚。于是打算把链表这一块好好的学习学习。在网上搜寻了众多的资料以后,了解到链表的核心是节点与节点之间的互相链接。

  于是自己也写了一个单向链表的类,里面包括input插入方法,inputById按指定下标插入方法,deleteAll删除所有节点方法,deleteById按指定下标删除结点方法,showAll控制台查看所有元素方法,reverse反转当前链表方法,length获取当前链表长度方法,等基本方法。

  需要说明的是,这个类还有很多不足之处,它还有很多需要改进的地方。但是基本原理和单向链表是相同的,仅供参考。

  1 package demo_4;
  2  
  3 import java.util.Stack;
  4  
  5 public class MyList<Re_Helix> {
  6     //节点内部类;
  7     private class Node{
  8         private Re_Helix data;            //数据;
  9         private Node next = null;            //下个节点的引用;
 10         
 11         public Node() {         //节点的无参构造;
 12             super();
 13         }
 14         
 15         public Node(Re_Helix data) {         //节点的有参构造;
 16             super();
 17             this.data = data;
 18         }
 19     }
 20     
 21     private Node head;            //头部节点;
 22     private Node end;            //尾部节点;
 23     private Node point;            //临时节点;
 24     private int length;            //长度属性;
 25     
 26     public MyList() {            //链表的无参构造;
 27         head = new Node();
 28         end = head;
 29         length = 0;
 30     }
 31     
 32     public void input(Re_Helix data) {            //给链表插入新值;
 33         point = new Node(data);
 34         if(length==0) {
 35             end.data = point.data;
 36         }else {
 37             end.next = point;
 38             end = point;
 39         }
 40         length++;
 41     }
 42     
 43     public void inputById(int target,Re_Helix data) {            //在指定下标的位置插入新值,如果两端超出范围,则分别按照head和end处理;
 44         Node temp = new Node(data);
 45         if(target>=length) {
 46             end.next = temp;
 47             end = temp;
 48         }else if(target<=0) {
 49             temp.next = head;
 50             head = temp;
 51         }else {
 52             temp.next = packPoint(target);
 53             packPoint(target-1).next = temp;
 54         }
 55         length++;
 56     }
 57     
 58     public int length() {            //返回链表的长度;
 59         return length;
 60     }
 61     
 62     public Re_Helix getById(int target) {            //输入下标返回值;
 63         return packPoint(target).data;
 64     }
 65     
 66     public void showAll() {            //在控制台查看当前链表中的所有数据
 67         point = head;
 68         int i = 0;
 69         while(point!=null) {
 70             System.out.println("第"+(i++)+"个:"+point.data);
 71             point = point.next;
 72         }
 73     }
 74     
 75     public void reverse() {            //将链表反转;
 76         Stack<Node> s1 = new Stack<Node>();            //利用队列的先进先出的特性;
 77         point = head;
 78         while(point!=null) {
 79             s1.push(point);
 80             point = point.next;
 81         }
 82         head = s1.pop();
 83         point = head;
 84         while(!s1.isEmpty()) {
 85             point.next = s1.pop();
 86             point = point.next;
 87         }
 88         end = point;
 89         end.next = null;  //要将逆序后的end位置节点的next置空,不然会造成最后两位的循环;
 90     }
 91     
 92     public void deleteById(int target) {            //输入下标删除值
 93         if(target>0) {
 94             packPoint(target-1).next = packPoint(target).next;
 95         }else {
 96             head = head.next;
 97         }
 98         length--;
 99     }
100     
101     public void deleteAll() {            //清空链表;
102         length = 0;
103         head.data = null;
104         head.next = null;
105         point = null;
106         end = head; 
107         System.gc();
108     }
109     
110     public boolean editById(int target,Re_Helix data) {            //修改传入下标位置的值;
111         if(target<0 || target>length) {
112             return false;
113         }else {
114             packPoint(target).data = data;
115             return true;
116         }
117     }
118     
119     private Node packPoint(int target) {            //内部方法,将指针指向指定下标的节点;
120         if(target<=0) {
121             point = head;
122         }else if(target>=length) {
123             point = end;
124         }else {
125             int i = 0;
126             point = head;
127             while(i++!=target) {
128                 point = point.next;
129             }
130         }
131         return point;
132     }
133 }

  多有不足,欢迎评论区批评指正。

 

以上是关于用Java语言实现单向链表的主要内容,如果未能解决你的问题,请参考以下文章

Java 数据结构 & 算法宁可累死自己, 也要卷死别人 7 单向链表

Java 数据结构 & 算法宁可累死自己, 也要卷死别人 7 单向链表

03-java实现双向链表

用Java语言实现单向链表

LeetCode刷题总结-链表

3-1单向链表