一、实验题目
(1)实验题目
用单链表实现集合
(2)问题描述
用有序单链表实现集合的判等、交、并和差等基本运算。
二、实验内容
(1)采用有序单链表存储集合;
(2)实现交、并、差等基本运算时,要求算法的空间复杂度为 O(1);
(3)充分利用单链表的有序性,要求算法有较好的时间性能;
(4)分析算法的时空性能,设计测试数据并上机实现。
三、数据结构设计
//节点结构
static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
//判断集合 A 和 B 是否相等
public boolean isEqual(ListNode curA , ListNode curB)
//求集合 A 和 B 的交集
public ListNode Interest(ListNode curA , ListNode curB)
//求集合 A 和 B 的并集
public ListNode union(ListNode curA , ListNode curB)
//差集
public ListNode subtraction(ListNode curA , ListNode curB)
四、算法设计
(1)判断集合 A 和 B 是否相等
public boolean isEqual(ListNode curA , ListNode curB)
同时遍历A链表和B链表
ListNode pa = curA
ListNode pb = curB
循环条件:pa != null && pb != null
如果pa.val!=pb.val,返回false,如果pa.val=pb.val,pa=pa.next,pb=pb.next,直到循环 结束。如果两个链表都为空,直接返回true,否则返回false.
时间复杂度:O(N)
空间复杂度:O(1)
(2)求集合 A 和 B 的交集
public ListNode Interest(ListNode curA , ListNode curB)
ListNode pa = curA
ListNode pb = curB
首先循环遍历B链表,每遍历一个节点,去遍历链表A,如果A链表的值小于 B节点的值,需要将该节点删除,删除就需要定义prev,让prev指向要删除节点的前驱节点,prev.next = pa.next,当pa.val=pb.val,说明链表A中包含pa节点,让prev = pa,pa=pa.next,pb=pb.next,如果pa.val> pb.val,pb=pb.next.
最终返回A链表的头节点即可。
时间复杂度:O(N^2)
空间复杂度:O(1)
(3)求集合 A 和 B 的并集
public ListNode union(ListNode curA , ListNode curB)
遍历B链表的每个节点,每遍历到一个节点去判断A链表中是否包含该节点如果A链表中该节点,pb=pb.next,同时再次循环A链表中的每个节点,如果A链表中不包含该节点,使用尾插法将该节点插入到A链表中,prev .next = pb; prev = prev.next , prev.next = null;注意,将该链表插入到A链表后,需要将尾节点的next域置null,为了能够找到B链表的下一个节点,需要引入ListNode pbNext = pb.next;,定义在B链表每次进入循环的时候,防止找不到B链表的后续节点。
时间复杂度:O(N^2)
空间复杂度:O(1)
(4)差集
public ListNode subtraction(ListNode curA , ListNode curB)
遍历B链表的每个节点,遍历到每个节点的同时,遍历A链表,如果A链表中包含该节点,需要将该节点删除,如果不包含该节点,继续遍历B链表中的下一个节点即可。
时间复杂度:O(N^2)
空间复杂度:O(1)
五、运行结果
七、程序源码
```java
public class MyLinkedList {
//节点结构
static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public ListNode createList(String str){
LinkedList<ListNode> list = new LinkedList<>();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
int n = Integer.valueOf(ch)-48;
ListNode node = new ListNode(n);
list.add(node);
}
for (int i = 0; i < list.size()-1; i++) {
ListNode node = list.get(i);
ListNode node2 =list.get(i+1);
node.next = node2;
}
ListNode last = list.get(list.size()-1);
last.next = null;
return list.get(0);
}
//判断集合 A 和 B 是否相等
public boolean isEqual(ListNode curA , ListNode curB){
if(curA == null && curB == null){
return true;
}
if(curA != null && curB == null || curA == null && curB !=null){
return false;
}
//curA != null && curB != null
ListNode pa = curA;
ListNode pb =curB;
while(pa != null && pb != null){
if(pa.val != pb.val){
return false;
}
pa =pa.next;
pb = pb.next;
}
if(pa == null && pb == null){
return true;
}else{
return false;
}
}
//求集合 A 和 B 的交集
/**
*
* @param curA: 表示链表A的头结点
* @param curB: 表示链表B的头结点
* @return
*/
public ListNode Interest(ListNode curA , ListNode curB){
if(curA == null && curB == null){
return null;
}
if(curA != null && curB == null || curA == null && curB !=null){
return null;
}
//curA != null && curB != null
ListNode pa = curA;
ListNode pb =curB;
ListNode prev =null;
while(pa != null && pb !=null){
if(pa.val < pb.val){
if(pa == curA){
curA = curA.next;
pa = pa.next;
}else {
prev.next = pa.next;
pa = pa.next;
}
}else if(pa.val > pb.val){
pb = pb.next;
}else {
prev = pa;
pa = pa.next ;
pb =pb.next;
}
}
// prev.next = null;
return curA ;
}
//求集合 A 和 B 的并集
public ListNode union(ListNode curA , ListNode curB){
ListNode pb = curB;
int flg = 0 ;
ListNode prev = null;
while(pb != null){
ListNode pbNext = pb.next;
flg = 0;
ListNode pa = curA ;
prev = null;
while(pa != null){
if(pa.val == pb.val){
flg = 1;
break;
}
prev = pa;
pa = pa.next;
}
if(flg == 0){
prev .next = pb;
prev = prev.next;
prev.next = null;
}
pb =pbNext;
}
return curA;
}
//差集
public ListNode subtraction(ListNode curA , ListNode curB) {
ListNode pb =curB;
while(pb != null) {
ListNode pa =curA;
ListNode prev = null;
while(pa != null){
if(pa.val == pb.val){
if(pa == curA){
curA = curA.next;
}else {
prev.next = pa.next;
}
break;
}
//不相等,改变前驱节点
prev = pa;
pa = pa.next;
}
pb =pb.next;
}
return curA;
}
public void print(ListNode cur){
while(cur != null){
System.out.print(cur.val + " ");
cur =cur.next;
}
System.out.println();
}
}
public class Test {
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
System.out.println("请输入链表A的节点:");
Scanner scanner = new Scanner(System.in);
String strA = scanner.nextLine();
System.out.println("请输入链表B的节点:");
String strB = scanner.nextLine();
MyLinkedList.ListNode curA = myLinkedList.createList(strA);
MyLinkedList.ListNode curB = myLinkedList.createList(strB);
System.out.print("链表A和链表B是否相等: ");
System.out.println(myLinkedList.isEqual(curA, curB));
MyLinkedList.ListNode node = myLinkedList.Interest(curA, curB);
System.out.print("链表A和链表B的交集是: ");
myLinkedList.print(node);
MyLinkedList.ListNode node2 = myLinkedList.union(curA,curB);
System.out.print("链表A和链表B的并集是: ");
myLinkedList.print(node2);
MyLinkedList.ListNode node3 = myLinkedList.subtraction(curA,curB);
System.out.print("链表A和链表B的差集是: ");
myLinkedList.print(node3);
}
}