一、实验题目
(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 != nullListNode 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 != nullListNode 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);}
}