Java实现不带头结点的单链表



一、带头结点与不带头结点单链表的区别

  1. 带头结点的单链表,带头结点的单链表在初始化时产生一个 head 结点,其 data 域和 next 域均为空。带头结点的单链表可进行头部操作和尾部操作。

  2. 不带头结点的单链表,实际上初始化时,产生了一个 node 结点,其 next 域和 data 域为空。
    不同点在于它已经不是头结点而是普通结点,即这个结点是第一个带值结点,而前面说的head结点是不带值的。
    所以在增加结点时,要判断这个结点是否是第一个结点且是否为空,若空则将值赋给这个结点,否则申请新节点,用尾插法插入元素。
    即然没有头结点,那对链表的增加和删除结点操作只能使用尾删法和尾插法。



二、不带头结点单链表的实现

1、接口的定义:

interface Ilist{		//线性表的抽象数据Java接口
	public void clear();
	public boolean isEmpty();
	public int length();
	public Object get(int i) throws Exception;
	public void insert(int i, Object x) throws Exception;
	public void remove(int i) throws Exception;
	public int indexOf(Object x);
	public void display();
}

2、结点的定义:

class Node{
	public Object data;		//存放结点值
	public Node next;		//后继结点的引用
	public Node() {			//无参数时的构造函数
		this(null,null);
	}
	public Node(Object data) {	//带一个参数时的构造函数
		this(data, null);
	}
	public Node(Object data, Node next) {	//带两个参数时的构造函数
		this.data = data;
		this.next = next;
	}
}

3、创建不带头结点的单链表:

class LinkList implements Ilist{
	public Node head;
	public LinkList() {		//单链表的构造函数
		head = new Node();
	}
}

4、插入元素:

public void insert(int i, Object x) throws Exception {
	Node p = head;
	int j = 0;
	while(p != null && j<i-1) {
		p = p.next;
		++j;
	}
	if(j>i || p == null)
		throw new Exception("插入位置不合法");
	Node s = new Node(x);
	if(i==0) {
		s.next=head;
		head=s;
	}
	else {
		s.next = p.next;
		p.next = s;
	}
}

5、用尾插法创建单链表:

//用尾插法构造一个长度为n的单链表
public void create(int n) throws Exception{
	Scanner sc = new Scanner(System.in);
	for(int j=0; j<n; j++)
		insert(length()+1, sc.next());
}

6、清空单链表:

public void clear() {
	head.data = null;
	head.next = null;
}

7、判断单链表是否为空:

public boolean isEmpty() {
	return head.next == null;
}

8、返回单链表的长度:

public int length() {
	Node p = head.next;
	int length = 0;
	while(p != null) {
		p = p.next;
		++length;
	}
	return length;
}

10、返回指定位置的元素:

public Object get(int i) throws Exception {
	Node p = head.next;
	int j = 0;
	while(p!=null && j<i) {
		p = p.next;
		++j;
	}
	return p.data;
}

11、删除指定位置的元素:

public void remove(int i) throws Exception {
	Node p = head;
	int j = -1;
	while(p.next != null && j<i-1) {
		p = p.next;
		++j;
	}
	if(j>i-1 || p.next == null)
		throw new Exception("删除位置不合法");
	p.next = p.next.next;
}

12、返回指定元素的位置:

public int indexOf(Object x) {
	Node p = head.next;
	int j=0;
	while(p!=null && !p.data.equals(x.toString())) {
		p = p.next;
		++j;
	}
	if(p != null)
		return j;
	else
		return -1;
}

13、遍历输出元素:

public void display() {
	Node node = head.next;
	while(node != null) {
		System.out.print(node.data + " ");
		node = node.next;
	}
	System.out.println();
}


附上全部代码:

import java.util.Scanner;

interface Ilist{		//线性表的抽象数据Java接口
	public void clear();
	public boolean isEmpty();
	public int length();
	public Object get(int i) throws Exception;
	public void insert(int i, Object x) throws Exception;
	public void remove(int i) throws Exception;
	public int indexOf(Object x);
	public void display();
}

class Node{
	public Object data;		//存放结点值
	public Node next;		//后继结点的引用
	public Node() {			//无参数时的构造函数
		this(null,null);
	}
	public Node(Object data) {	//带一个参数时的构造函数
		this(data, null);
	}
	public Node(Object data, Node next) {	//带两个参数时的构造函数
		this.data = data;
		this.next = next;
	}
}

class LinkList implements Ilist{
	public Node head;
	public LinkList() {		//单链表的构造函数
		head = new Node();
	}
	
	//用尾插法构造一个长度为n的单链表
	public void create(int n) throws Exception{
		Scanner sc = new Scanner(System.in);
		for(int j=0; j<n; j++)
			insert(length()+1, sc.next());
	}

	public void clear() {
		head.data = null;
		head.next = null;
	}

	//构造判断单链表是否为空函数
	public boolean isEmpty() {
		return head.next == null;
	}

	//构造返回单链表长度的函数
	public int length() {
		Node p = head.next;
		int length = 0;
		while(p != null) {
			p = p.next;
			++length;
		}
		return length;
	}

	//构造查找单链表某位置上的元素
	public Object get(int i) throws Exception {
		Node p = head.next;
		int j = 0;
		while(p!=null && j<i) {
			p = p.next;
			++j;
		}
		return p.data;
	}

	//构造插入函数
	public void insert(int i, Object x) throws Exception {
		Node p = head;
		int j = 0;
		while(p != null && j<i-1) {
			p = p.next;
			++j;
		}
		if(j>i || p == null)
			throw new Exception("插入位置不合法");
		Node s = new Node(x);
		if(i==0) {
			s.next=head;
			head=s;
		}
		else {
			s.next = p.next;
			p.next = s;
		}
	}

	//构造删除函数
	public void remove(int i) throws Exception {
		Node p = head;
		int j = -1;
		while(p.next != null && j<i-1) {
			p = p.next;
			++j;
		}
		if(j>i-1 || p.next == null)
			throw new Exception("删除位置不合法");
		p.next = p.next.next;
	}

	//构造查找单链表上某值的位置
	public int indexOf(Object x) {
		Node p = head.next;
		int j=0;
		while(p!=null && !p.data.equals(x.toString())) {
			p = p.next;
			++j;
		}
		if(p != null)
			return j;
		else
			return -1;
	}

	//构造输出函数
	public void display() {
		Node node = head.next;
		while(node != null) {
			System.out.print(node.data + " ");
			node = node.next;
		}
		System.out.println();
	}
}

public class Task_7_1 {
	public static void main(String[] args) throws Exception {
		Scanner in = new Scanner(System.in);
		System.out.print("输入单链表的长度:");
		int n = in.nextInt();
		
		LinkList L = new LinkList();
		System.out.print("用头插法输入单链表个元素的值:");
		L.create(n);
		System.out.print("输出此时单链表各元素的值:");
		L.display();
		
		L.insert(3,3);
		System.out.print("输出插入元素'3'后的单链表:");
		L.display();
		
		L.remove(4);
		System.out.print("输出第4个位置元素后的单链表:");
		L.display();
		
		System.out.print("输入要查找的位置:");
		int m = in.nextInt();
		if(m>L.length() || L.get(m)==null) 
			System.out.println("该元素不存在!");
		else
			System.out.println("查找的位置上的值:" + L.get(m));
		
		System.out.print("输入要查找的值:");
		int k = L.indexOf(in.nextInt());
		if(k!=-1)
			System.out.println("查找的值所在的位置:" + k);
		else
			System.out.println("该元素不存在!");
		
		L.clear();
		System.out.println("清空后单链表的长度:" + L.length());
	}
}

运行结果:
在这里插入图片描述

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值