一、链表
链表作为数据结构中重要的组成部分,其相较于不易于增删操作的顺序表而言,在逻辑和空间上都具有更高的灵活性。以下将通过Java实现单向不带头非循环链表并实现增、删、查找、获取大小、展示、清空方法。
二、代码结构
1.AddIndexPosIlegalException:自定义运行时异常类,用于在输入下标非法时抛出异常。
2.SingleLinkedList(包含内部类ListNode:定义节点的数值域和引用域):包含头节点引用以及各种链表方法。
3.Test:其main方法用于测试链表操作。
三、程序源码
1.AddIndexPosIlegalException类:
//定义下标添加异常类AddIndexPosIlegalException
public class AddIndexPosIlegalException extends RuntimeException{
public AddIndexPosIlegalException(){
super();
}
public AddIndexPosIlegalException(String msg){
super(msg);
}
}
值得注意的是该异常属于运行时异常,应当继承RuntimeException。
2.SingleLinkedList类:
(1)定义:
public class SingleLinkedList
(2)成员变量:
private ListNode head=null;//头节点引用本地初始化为空
(3)定义节点内部类ListNode(当然类外定义也可以):
class ListNode{
//数值域
public int val;
//引用域
public ListNode next;
//Node类的有参构造方法
public ListNode(int val){
this.val=val;
this.next=null;
}
}
(4)头插方法:
//头插法
public void addFirst(int data){
ListNode listNode=new ListNode(data);
listNode.next=head;
head=listNode;
}
(5)尾插方法:
//尾插法
public void addLast(int data){
ListNode listNode=new ListNode(data);
//判断头节点是否为空,为空则直接添加
if(head==null){
head=listNode;
}
//遍历链表找到最后一个节点
ListNode current=head;
while(current.next!=null){
current=current.next;
}
current.next=listNode;
}
(6) 在指定下标插入数据(包含判断下标是否合法以及寻找直接前驱节点两个底层方法):
//底层方法,检查下标
public void checkIndex(int index)throws AddIndexPosIlegalException{
if(index<0||index>getSize()){
throw new AddIndexPosIlegalException("下标非法");
}
}
//底层方法,寻找某个下标直接前驱节点
public ListNode findSuboneIndex(int index){
ListNode current=head;
int count=0;
while(count!=index-1){
current=current.next;
count++;
}
return current;
}
//在指定下标插入数据
public void addIndex(int index,int data){
//解决下标非法异常
try{
checkIndex(index);
}catch (AddIndexPosIlegalException e){
e.printStackTrace();
}
//找到直接前驱节点
ListNode subOneListNode=findSuboneIndex(index);
//插入新节点
ListNode listNode=new ListNode(data);
listNode.next=subOneListNode.next;
subOneListNode.next=listNode;
}
(7)删除第一次出现值为key的节点方法:
//删除第一次出现的值为key的节点
public void remove(int key) {
//判空
if(head==null){
return;
}
ListNode current = head;
//后续以head.next判断的形式进行遍历无法涉及到开始节点
//所以要对开始节点进行处理
if (current.val == key) {
head = null;
return;
}
while (current.next != null) {
if (current.next.val == key) {
current.next = current.next.next;
return;
}
current=current.next;
}
}
(8)删除所有值为key的节点方法:
//删除所有值为key的节点
public void removeAllKey(int key){
//判空
if(head==null){
return;
}
//双引用遍历链表
ListNode pre=head;
ListNode cur=head.next;
while(cur!=null){
if(cur.val==key) {
pre.next = cur.next;
}else{
pre=cur;
}
cur=cur.next;
}
//双引用遍历并没有涉及到头节点,所以最后对头节点进行处理
if(head.val==key) {
head = head.next;
}
}
(9)查找链表中是否包含某值的方法:
//查找链表中是否包含某值
public boolean contains(int key){
ListNode current=head;
while(current!=null){
if(current.val==key){
return true;
}
}
return false;
}
(10)获取链表大小(长度)的方法:
//获取链表的长度
public int getSize(){
ListNode current=head;
int count=0;
//遍历全部链表
while(current!=null){
count++;
current=current.next;
}
return count;
}
(11)展示整个链表的方法:
//展示整个链表
public void display(){
ListNode current=head;
//遍历全部链表
while(current!=null){
System.out.print(current.val+" ");
current=current.next;
}
System.out.println();
}
(12)清空整个链表的方法:
//清空整个链表
public void clear(){
//判空
if(head==null){
return;
}
//双引用遍历全部链表
ListNode cur=head;
ListNode suc=head.next;
while(suc!=null){
cur.next=null;
cur=suc;
suc=suc.next;
}
cur=null;
head=null;
}
四、操作示例
Test中源码为:
public class Test {
public static void main(String[] args) {
//创建链表
SingleLinkedList singleLinkedList=new SingleLinkedList();
//头插演示
singleLinkedList.addFirst(1);
singleLinkedList.addFirst(2);
singleLinkedList.addFirst(3);
singleLinkedList.addFirst(4);
//尾插演示
singleLinkedList.addLast(1);
singleLinkedList.addLast(1);
singleLinkedList.addLast(1);
singleLinkedList.addLast(1);
singleLinkedList.display();
System.out.println("****************");
//删除第一个值为key的节点
singleLinkedList.remove(2);
singleLinkedList.display();
System.out.println("****************");
//删除所有值为key的节点
singleLinkedList.removeAllKey(1);
singleLinkedList.display();
System.out.println("****************");
//指定位置插入演示
singleLinkedList.addIndex(1,10);
singleLinkedList.display();
System.out.println("****************");
//获取大小演示
System.out.println("链表大小为"+singleLinkedList.getSize());
System.out.println("****************");
//清空演示
singleLinkedList.clear();
singleLinkedList.display();
}
}
运行结果如下:
注:最后一行打印为空说明链表已经清空。
五、小结
以上便是通过java实现单向不带头非循环链表的全部内容,部分思路来自互联网,如有不当,敬请斧正!