用Java语言实现单向链表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Java语言实现单向链表相关的知识,希望对你有一定的参考价值。
单向链表的实现:
1.链表的结点:
一个单向链表是一组结点(数据元素)的序列,每个结点有两个域:数据域和指针域。
2.指针:
指针域存放其后继结点的地址,最后一个结点的指针域为空。头指针head指向链表的第一个结点,当链表为空时,头指针为空值。
3.结点的数据域:
-数据域存放数据,可能是三角形、矩形、圆形三种形状中的任何一种。
-形状除了具有与大小有关的属性外,还有颜色属性。
4.链表需要实现的功能:
(1)生成链表;
-根据输入生成链表
-生成一条长度为6、节点中的形状随机、颜色随机、大小均为10的链表。(其中大小为10的含义是指:三角形或矩形的边长都为10,圆的半径都为10。)
(2)链表中结点的插入与删除;
(3)在链表中删掉某类(三角形、圆形、矩形)的结点
(4)将链表中具有某种颜色A的节点改为颜色B。
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 单向链表