之前做数据结构课程设计时遇到的一道小题,感觉对链表的知识覆盖比较广,对链表知识的理解挺有帮助的。
一、问题描述
对双向循环列表进行如下操作:
1.建立一个空表。
2.在第i个位置插入新的元素x。
3.删除第i个位置上的元素。
4.取第i个位置上的元素。
5.返回元素x第一次出现在双向循环链表中的位置号。
6.求双向循环链表的长度,即元素个数。
7.输出双向循环链表中所有的元素值。
8.实现双向循环链表的就地逆置。
二、问题解析
1.创建空表
图1 创建空表
2.双向循环链表
图2 双向循环链表结构
3.插入
图3 插入前
图4 插入后
4.删除
图5 删除前
图6 删除后
5.就地逆置
图7 就地逆置前
图8 就地逆置过程
三、总体思路
(1)清楚双向循环链表的结构,写出双向循环链表的节点类。
(2)建立一个空的双向循环链表,即只有头结点。
(3)使用头插法建立一个双向循环链表。
(4)建立完成后弹出选项菜单进行选择并运行相关程序,包含插入、删除、取元素、返回位置号、求长度、输出所有元素、就地逆置等操作。
(5)根据用户意愿继续弹出菜单进行选择或者退出程序。
四、函数或类的具体定义和功能
函数 | 具体功能 |
DuLinkList | 建立一个空表 |
insert | 在第i个位置插入新的元素x |
remove | 删除第i个位置上的元素 |
length | 求双向循环链表的长度,即元素个数 |
display | 输出双向循环链表中所有的元素值 |
get | 取第i个位置上的元素 |
indexOf | 返回元素x第一次出现在双向循环链表中的位置号 |
reverse | 实现双向循环链表的就地逆置 |
五、代码
public class DuLinkList {
public DuLNode head;
public DuLinkList(){
head = new DuLNode();
head.prior = head;
head.next = head;
}
public void insert(int i,Object x) throws Exception{
if(i<0 || i>length())
throw new Exception("下标不合法");
DuLNode node = head.next;
int j = 0;
while(!node.equals(head) && j<i){
j++;
node = node.next;
}
DuLNode newNode = new DuLNode(x);
node.prior.next = newNode;
newNode.prior = node.prior;
newNode.next = node;
node.prior = newNode;
}
public void remove(int i) throws Exception{
if(i<0 || i>length()-1)
throw new Exception("下标不合法");
DuLNode node = head.next;
int j = 0;
while(!node.equals(head) && j<i){
j++;
node = node.next;
}
node.prior.next = node.next;
node.next.prior = node.prior;
}
public int length(){
DuLNode node = head.next;
int j = 0;
while(node!=head){
j++;
node = node.next;
}
return j;
}
public void display(){
DuLNode node = head.next;
while(node!=head){
System.out.print(node.data+" ");
node = node.next;
}
}
public Object get(int i) throws Exception{
DuLNode p=head.next;
int j=0;
while(!p.equals(head)&&j<i) {
p=p.next;
++j;
}
if(j>i||p.equals(head)) {
throw new Exception("第"+i+"个元素不存在");
}
return p.data;
}
public int indexOf(Object x) {
DuLNode p = head.next;
int j=0;
while(p!=head&&!p.data.equals(x)) {
p=p.next;
++j;
}
if(p!=head)
return j;
else
return -1;
}
public void reverse() {
DuLNode p=head.next;
while(!p.equals(head)) {
DuLNode q=p;
DuLNode r=p.next;
q.next=q.prior;
q.prior=r;
p=p.prior;
}
DuLNode s=head.prior;
head.prior=head.next;
head.next=s;
}
}
public class DuLNode {
public Object data;
public DuLNode prior;
public DuLNode next;
public DuLNode(){
this(null);
}
public DuLNode(Object data){
this.data=data;
this.prior=null;
this.next=null;
}
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("输入双向循环链表的长度:");
int n = sc.nextInt();
//1. 建立一个空表
DuLinkList list = new DuLinkList();
//头插法
System.out.print("依次输入双向循环链表的值:");
for (int i = 0; i < n; i++) {
try {
list.insert(0, sc.next());
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.print("双向循环链表各元素的值为:");
list.display();
System.out.println();
boolean flag=true;
while (flag) {
System.out.println("输入编号执行相关程序:");
System.out.println("2.在第i个位置插入新的元素x。");
System.out.println("3.删除第i个位置上的元素。");
System.out.println("4.取第i个位置上的元素。");
System.out.println("5.返回元素x第一次出现在双向循环链表中的位置号。");
System.out.println("6.求双向循环链表的长度,即元素个数。");
System.out.println("7.输出双向循环链表中所有的元素值。");
System.out.println("8.实现双向循环链表的就地逆置。");
System.out.println("输入想要执行程序的编号");
Scanner num = new Scanner(System.in);
int z = num.nextInt();
switch (z) {
case 2:
//2. 在第i个位置插入新的元素x
System.out.print("在双向循环链表第i个位置插入新的元素x,依次输入i和x:");
int a = sc.nextInt();
Object b = sc.next();
try {
list.insert(a, b);
} catch (Exception e) {
e.printStackTrace();
}
System.out.print("在第" + a + "个位置插入新的元素" + b + "后的双向循环链表:");
list.display();
System.out.println();
break;
case 3:
//3. 删除第i个位置上的元素
System.out.print("删除双向循环链表第i个位置上的元素,输入i:");
int c = sc.nextInt();
try {
list.remove(c);
} catch (Exception e) {
e.printStackTrace();
}
System.out.print("删除位置" + c + "后的双向循环链表:");
list.display();
System.out.println();
break;
case 4:
//4. 取第i个位置上的元素
System.out.print("输入要查找的位置i:");
int d = sc.nextInt();
try {
System.out.println("第i个位置上的元素为:" + list.get(d));
} catch (Exception e) {
e.printStackTrace();
}
break;
case 5:
//5. 返回元素x第一次出现在双向循环链表中的位置号
System.out.print("返回元素x第一次出现在双向循环链表中的位置号,输入x:");
Object e = sc.next();
System.out.println("元素x第一次出现在双向循环链表中的位置号为:" + list.indexOf(e));
break;
case 6:
//6. 求双向循环链表的长度,即元素个数
System.out.println("双向循环链表的长度,即元素个数:" + list.length());
break;
case 7:
//7. 输出双向循环链表中所有的元素值
System.out.print("输出双向循环链表中所有的元素值:");
list.display();
System.out.println();
break;
case 8:
//8. 实现双向循环链表的就地逆置
System.out.print("双向循环链表的就地逆置:");
list.reverse();
list.display();
System.out.println();
break;
default:
System.out.println("输入错误");
}
System.out.println("上一个程序执行完成!输入1继续选择,输入其他则程序结束");
int x=sc.nextInt();
if (x==1){
flag=true;
}
else {
flag=false;
}
}
}
}
六、测试结果
测试数据:
博主已经测试过所有情况了,由于结果太多这里就放三条结果了。