一、实验目的
1、掌握线性链表的操作特点,即指针是逻辑关系的映像。
2、掌握动态产生带尾指针的单循环链表(有头结点)的方法。
3、熟练掌握单循环链表基本操作的实现过程。
二、实验内容
1、定义单循环链表类型并动态创建使用tail指向尾结点的单循环链表(有头结点);
2、实现单循环链表的取元素、插入、删除、索引元素位置号等操作以及迭代器;
3、实现输出单循环链表中各元素值的操作;
4、将单循环链表中的最小元素移到最前面。
三、实验步骤
1、定义单循环链表结点类;
2、定义单循环链表类,并实现使用tail指向尾结点的单循环链表(有头结点)的创建、插入、删除、取元素操作和将单链表中的最小元素移到最前面的操作,以及迭代器;
3、从键盘上依次输入21、75、30、18、42、56,创建单循环链表,并输出单循环链表中的各元素值;
5、分别在单链表的第3个位置和第9个位置插入67和10,给出插入成功或失败的信息,并输出单循环链表中的各元素值;
6、删除单循环链表中的第4个数据元素和第8个数据元素,给出删除成功或失败的信息,并输出单循环链表中的各元素值;
7、取单循环链表中的第5个数据元素和第7个数据元素;
8、将单循环链表中的最小元素移到最前面,并输出单链表中的各元素以检查操作是否正确实现。
四、代码及运行结果
import java.util.Scanner;
public class LinkList implements IList{
public Node tail;
public LinkList(){
tail=new Node();
tail.next=tail;
}
public void create(int n)throws Exception {
Scanner sc=new Scanner(System.in);
Node p=tail.next;
Node q=tail.next;
Node newnode;
for(int i=0;i<n;i++)
{
newnode=new Node(sc.nextInt());
p.next=newnode;
p=p.next;
}
tail=p;
tail.next=q;
}
public void insert(int i,Object x) throws Exception{
Node p=tail.next;
int j=-1;
while (p != tail && j < i - 1) {
p=p.next;
++j;
}
if(j>i-1 || p==tail){
throw new Exception("插入位置不合法");
}
Node s=new Node(x);
s.next=p.next;
p.next=s;
}
public void remove(int i)throws Exception
{
int j=-1;
Node p=tail.next,q;
while(p!=tail&&j<i-1)
{p=p.next;j++;}
if(j>i-1||p==tail)
throw new Exception("删除位置不合法");
q=p.next;
if(q==tail)
throw new Exception("删除位置不合法");
p.next=q.next;
}
public Object get(int i)throws Exception{
Node p=tail.next.next;
int j=0;
while (p!=tail.next&&j<i){
p=p.next;
++j;
}
if (j>i||p==tail.next){
throw new Exception("元素不存在");
}
return p.data;
}
public void display(){
Node node=tail.next;
while (node.next!=tail.next){
System.out.print(Integer.parseInt(String.valueOf(node.next.data))+" ");
node=node.next;
}
System.out.println();
}
public int length(){
Node p=tail.next.next;
int length=0;
while (p!=null){
p=p.next;
++length;
}
return length;
}
public void change(){
Node p=tail.next.next;
int i=0;
int j=0;
int min=Integer.parseInt(String.valueOf(tail.next.next.data));
while (p!=tail.next){
if(Integer.parseInt(String.valueOf(p.data))<min)
{
min=Integer.parseInt(String.valueOf(p.data));
i=j;
}
p=p.next;
j++;
}
Object temp= null;
try {
temp = get(i);
} catch (Exception e) {
e.printStackTrace();
}
try {
remove(i);
} catch (Exception e) {
e.printStackTrace();
}
try {
insert(0,temp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public 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;
}
}
public interface IList {
// 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();
}
import java.util.Scanner;
public class Test {
public static void main(String[] args){
LinkList l1=new LinkList();
System.out.println("结点个数");
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
System.out.println("输入链表中的各元素值");
try {
l1.create(num);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("链表中的各元素值为");
l1.display();
try {
l1.insert(3,67);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("第3个位置插入67后");
l1.display();
try {
l1.insert(9,10);
} catch (Exception e) {
System.out.println("插入位置不合法");
}
try {
l1.remove(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("删除第四个位置的元素后");
l1.display();
try {
l1.remove(8);
} catch (Exception e) {
System.out.println("删除位置不合法");
}
try {
Object index = l1.get(5);
int k=Integer.parseInt(String.valueOf(index));
System.out.println("第五个数据为"+k);
} catch (Exception e) {
e.printStackTrace();
}
try {
Object in = l1.get(7);
} catch (Exception e) {
System.out.println("元素不存在");
}
l1.change();
System.out.println("最小元素移动后的链表:");
l1.display();
}
}
运行结果:
五、问题讨论
1、
顺序存储的优缺点:
优点:
(1)物理位置上相邻表示逻辑相邻,无须为表示元素间的逻辑关系而增加额外的存储空间。
(2)存储密度高。
(3)可以方便地随机存取表中的任一元素。
缺点:
(1)不便于插入和删除操作,因为插入和删除平均须移动一半元素。
(2)需要预先分配存储空间(静态分配)
链式存储的优缺点:
优点:
(1)插入和删除操作的效率较高,不需要移动元素。
(2)动态分配存储空间。
缺点:
(1)借助于指针表示逻辑相邻。
(2)空间利用 率低,存储密度低。
(3)只能顺序存取表中的任一元素。
2、
若是仅用头指针标识循环链表,则访问第一个结点的时间复杂度为O(1),但访问最后一个结点的时间复杂度为O(n);若仅用尾指针标识的循环链表则不论是访问第一个结点还是访问最后一个结点其时间复杂度都是O(1)。