一、带头结点与不带头结点单链表的区别
-
带头结点的单链表,带头结点的单链表在初始化时产生一个 head 结点,其 data 域和 next 域均为空。带头结点的单链表可进行头部操作和尾部操作。
-
不带头结点的单链表,实际上初始化时,产生了一个 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());
}
}
运行结果: