题目:利用单链表求集合的交集、并集和补集
要求:使用泛型

/*** 利用单链表求集合的交集、并集和补集* 要求:使用泛型* * @author zql**/
public class SingleLinkedList<T> extends Object{/*** 定义链表个数*/private int size;/*** 头节点*/private Node<T> head;// 构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行{this.size = 0;this.head = null;}/*** 定义一个无参构造函数,用于实例化头节点 */public SingleLinkedList() {this.head = new Node<T>();}/*** 定义一个添加集合元素到链表节点的构造函数* * @param values*/public SingleLinkedList(T[] values) {this();this.set(values);}/*** 链表的每个节点类* * @param <T>*/public class Node<E> {/*** 每个节点的数据*/private T data;/*** 每个节点指向下一个节点的连接*/public Node<E> next;public Node() {this(null);}public Node(T data) {this.data = data;}public T getData() {return this.data;}public void setData(T data) {this.data = data;}}/*** 设置每一个节点的数据* * @param valuse*/public void set(T[] values) {if (values == null || values.length == 0) {throw new NullPointerException(this.getClass().getName() + "构造参数长度不能为0且不能为空");} else {Node<T> rear = this.head;// 给头节点设置第一个元素rear.setData(values[0]);// 节点数加一this.size++;for (int i = 1, len = values.length; i < len; i++) {// 数据为null不添加入节点if (values[i] == null) {continue;}rear.next = new Node<T>(values[i]);rear = rear.next;// 节点数加一this.size++;}}}/*** 在链表头添加元素* * @param n* @return*/public void add(T value) {if (value == null) {throw new NullPointerException("添加的元素不能为空");}Node<T> newNode = new Node<T>(value);// 如果链表节点数为0,则头节点就是添加的新节点if (this.size == 0) {this.head = newNode;} else {// next指向原头节点newNode.next = this.head;// 将当前添加的节点设置为头节点this.head = newNode;}// 链表节点数加一this.size++;}/*** 在链表头指定位置添加元素* * @param i 从0开始,0表示添加进第一位,如果i大于等于size则添加进末尾节点* @param n*/public void add(int i,T value) {Node<T> newNode = new Node<T>(value);if (value == null) {throw new NullPointerException("添加的元素不能为空");}if (i == 0) {add(value);} else {Node<T> front = this.head;// j<=i,只需查找到要插入的位置即可for (int j = 1; j <= i && j < this.size; j++) {// 找到要添加的位置if (j == i) {// 保存原链表添加位置的节点数据Node<T> temp = front.next;// 把新添加的节点接上front.next = newNode;// 把保存的节点数据连上front.next.next = temp;} else {front = front.next;}}// 插入最后一个位置if (i >= this.size) {front.next = newNode;}// 链表节点数加一this.size++;}}/*** 根据索引获取节点数据* * @param i 索引,从0开始* @return*/public T get(int i) {if (i >= this.size || i < 0) {throw new ArrayIndexOutOfBoundsException("数组越界:" + i);}if (i == 0) {return this.head.data;}Node<T> current = this.head;for (int j = 1; j < this.size; j++) {if (i == j) {return current.next.data;}current = current.next;}return null;}/*** 根据传入的值判断节点是否存在* * @param value* @return 存在返回true*/public boolean isExist(T value) {Node<T> current = this.head;while (current.next != null) {if (value.equals(current.getData())) {return true;} else {current = current.next;}}return false;}/*** 求两个集合的并集* * @param values*/public void merge(T[] values) {for (int i = 0, len = values.length; i < len; i++) {// 不存在就添加if (!this.isExist(values[i])) {this.add(values[i]);}}}/*** 求两个集合的交集* * @param values*/@SuppressWarnings("unchecked")public void intersection(T[] values,SingleLinkedList<T> s) {// 也可以使用list,我想复习一个数组扩容就没用// 泛型无法实例化,所以使用实例化Object强制转换方式T[] tArr = (T[]) new Object[10];int j = 0;for (int i = 0, len = values.length; i < len; i++) {// 存在就添加if (this.isExist(values[i])) {tArr[j++] = values[i];// 进行评定是否达到,数组的最大存储量if (j >= tArr.length) {// 扩容tArr = getNewArray(tArr);}}}// 清空数据s.clear();// 重新装数据s.set(tArr);}/*** 数组的自动扩容,同时拷贝数据* * @param arrs 原始的数组* @return T [] 新的数组对象* @说明: 本方法扩容的因子为 50%*/@SuppressWarnings("unchecked")private T[] getNewArray(T[] arrs) {int maxnum = (int) (arrs.length * 1.5);T[] newArr = (T[]) new Object[maxnum];// 拷贝数据int i = 0;// 迭代器 保证每个元素都会被迭代一次for (T x : arrs) {newArr[i++] = x;}return newArr;}/*** 移除指定位置节点数据* * @param i*/public void remove(int i) {if (i >= this.size || i < 0) {throw new ArrayIndexOutOfBoundsException("数组越界:" + i);}// 如果移除的节点是第一个节点if (i == 0) {this.head = this.head.next;} else {Node<T> front = this.head;for (int j = 1; j < i && front != null; j++) {front = front.next;}if (front.next != null) {front.next = front.next.next;}}// 节点数减一this.size--;}/*** 根据传入的值移除所有和该值相同的节点* * @param values*/public void remove(T value) {if (value == null) {throw new NullPointerException("移除的元素不能为空");}Node<T> front = this.head;// 要移除的位置int i = 0;// 是否触发过移除操作boolean isRemove = false;while (front != null) {if (front.getData().equals(value)) {this.remove(i);// 重置ii = 0;isRemove = true;}// 如果触发过移除操作,则重新赋予头节点,同时把是否触发过移除操作设为falseif (isRemove) {front = this.head;isRemove = false;} else {i++;front = front.next;}}}/*** 根据传入的数组移除所有和该数组元素值相同的节点* * @param values*/public void removeAll(T[] values) {if (values != null && values.length != 0) {for (int i = 0, len = values.length; i < len; i++) {this.remove(values[i]);}}}/*** 去掉链表中重复的值 */@SuppressWarnings("unchecked")public void removeDuplicate() {T[] tArr = (T[]) new Object[this.size];int l = 0;Node<T> current = this.head;for (int i = 0; i < this.size; i++) {tArr[l++] = current.getData();current = current.next;}// 对数组去重,可以使用map或set集合,会更加简便for (int i = 0, len = tArr.length; i < len; i++) {// 等于null说明是重复的赋值为null就不需要再循循环了if (tArr[i] != null) {for (int j = i; j < len - 1; j++) {// 这里tArr[j+1]!=null同样是因为重复的已为nullif (tArr[i] == tArr[j + 1] && tArr[j + 1] != null) {tArr[j + 1] = null;}}}}// 清空数据this.clear();// 重新装数据this.set(tArr);}/*** 去泛型数组中重复的值 * * @param tArr 要去重的泛型数组* @return 返回去重后的Object类型数组* <br/>不返回泛型数组是因为返回了也接收不了,因为java中的强制类型转换只是针对单个对象的,将整个数组转换成另外一种类型的数组是不行的*/public Object[] removeDuplicate(T[] tArr) {// 去掉的重复个数int count = 0;// 对数组去重,可以使用map或set集合,会更加简便for (int i = 0, len = tArr.length; i < len; i++) {// 等于null说明是重复的赋值为null就不需要再循循环了if (tArr[i] != null) {for (int j = i; j < len - 1; j++) {// 这里tArr[j+1]!=null同样是因为重复的已为nullif (tArr[i] == tArr[j + 1] && tArr[j + 1] != null) {tArr[j + 1] = null;count++;}}}}if (count == 0) {return tArr;}// 拷贝去重后的数组Object[] newArr = new Object[tArr.length - count];int l = 0;for (int i = 0, len = tArr.length; i < len; i++) {if (tArr[i] != null) {newArr[l++] = tArr[i];}}return newArr;}/*** 清空所有数据* * @param i*/public void clear() {this.head = new Node<T>();this.size = 0;}/*** 返回链表大小* * @return*/public int size() {return this.size;}/*** 判断链表是否为空* * @return*/public boolean isEmpty(){return (this.size == 0);}/*** 打印节点信息* * @return*/public String display() {String str = "{";if (this.head != null && this.size != 0) {str += this.head.getData() + ",";for (Node<T> p = this.head.next; p != null; p = p.next) {str += p.getData() + ",";}str = str.substring(0, str.length() - 1);}return str + "}";}
}

测试类:

public class Test {public static void main(String[] args) {System.out.println("----------求补集---------");complementarySet();System.out.println("----------求并集---------");unionSet();System.out.println("----------求交集---------");intersection();}/*** 求补集*/public static void complementarySet() {String[] c1 = { "b", "c", "d", "e", "a" };String[] c2 = { "b", "c", "f", "g" };SingleLinkedList<String> s1 = new SingleLinkedList<String>(c1);SingleLinkedList<String> s2 = new SingleLinkedList<String>(c2);System.out.println("初始数据:" + s1.display());s1.add("a");System.out.println("添加头节点后的数据:" + s1.display());s1.add(5, "f");System.out.println("添加头节点后再在第6位插入后数据:" + s1.display());s1.removeDuplicate();System.out.println("去重后的数据:" + s1.display());// 补集:属于全集U不属于集合A的元素组成的集合称为集合A的补集System.out.print("全集U:" + s1.display());s1.removeAll(c2);System.out.println(",集合A:" + s2.display() + ",属于全集U不属于集合A的补集:" + s1.display());s1.clear();System.out.println("清空后:" + s1.display());}/*** 求并集*/public static void unionSet() {String[] c1 = { "a", "b", "c", "d", "e", "a" };String[] c2 = { "b", "c", "f", "g" };SingleLinkedList<String> s2 = new SingleLinkedList<String>(c2);Object[] o1 = s2.removeDuplicate(c1);// 对数组进行去重String[] newC = new String[o1.length];for (int i = 0, len = o1.length; i < len; i++) {newC[i] = (String) o1[i];}// 其实也可以直接使c1,因为重复的元素已经变成null了SingleLinkedList<String> s1 = new SingleLinkedList<String>(newC);System.out.println("初始数据:" + s1.display());s1.add(5, "f");System.out.println("在第6位插入后数据:" + s1.display());// 补集:属于全集U不属于集合A的元素组成的集合称为集合A的补集System.out.print("集合A:" + s1.display());s1.merge(c2);System.out.println(",集合B:" + s2.display() + ",集合A和集合B的并集:" + s1.display());}/*** 求交集*/public static void intersection() {String[] c1 = { "b", "c", "d", "e", "a" };String[] c2 = { "b", "c", "f", "g" };SingleLinkedList<String> s1 = new SingleLinkedList<String>(c1);SingleLinkedList<String> s2 = new SingleLinkedList<String>(c2);System.out.println("初始数据:" + s1.display());s1.add("a");System.out.println("添加头节点后的数据:" + s1.display());s1.add(5, "f");System.out.println("添加头节点后再在第6位插入后数据:" + s1.display());// 补集:属于全集U不属于集合A的元素组成的集合称为集合A的补集System.out.print("集合A:" + s1.display());s1.intersection(c2, s1);System.out.println(",集合B:" + s2.display() + ",集合A和集合B的交集:" + s1.display());}
}

测试效果图:

java算法编程题:利用单链表求集合的交集、并集和补集相关推荐

  1. 使用顺序表、单链表求集合运算

    ******.设有两个顺序表A和B,编写一个算法将属于A,但是不属于B的数据元素放大到另一个顺序表C中 (1).算法设计 遍历顺序表A,将A中每一个元素依次与顺序表B比较,如果相等直接跳过开始比较下一 ...

  2. java算法编程题_【java题目】考验你编程能力和算法的时候到了

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这是我写的,但是算法很复杂,唉,求高手啊 package com.sky.woodwall; import java.util.ArrayList; im ...

  3. java算法编程题:士兵列队问题

    题目:300名士兵分别编号为1-300,按顺序排成一排,长官下令:"双数士兵出列!",剩下的士兵重新按原序编号.长官下令:"双数士兵出列!",如此进行下去直到最 ...

  4. Java基础编程题(02)求100-200之间的素数

    2 [程序 2 输出素数] 题目:判断 101-200 之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除 2 到 sqrt(这个数),如果能被整除,则表明此数不是素数,反 ...

  5. java链表交集并集,一个链表求集合并集交集的异常

    C/C++ code//求并集的函数: void bingji(mylist*p,mylist*q,mylist*&r)//r作为并集列表的头指针,p,q是输入的两个指针 { mylist * ...

  6. A和B 单链表表示 集合,求其 交集 并集 差集

    A和B 单链表表示 集合的 交集 并集 差集 /* A和B 单链表表示 集合的 交集 并集 差集 */ //#include <iostream> //using namespace st ...

  7. c语言用单链表实现lru算法,利用单链表实现LRU算法

    利用单链表实现LRU算法 首先,我们先看下对于Node的定义: package datastructure.linklist.node; import lombok.Data; /** * 单链表节点 ...

  8. 【面试锦囊】14种模式搞定面试算法编程题(1-7)

    面试锦囊之知识整理系列 面试锦囊系列一直有收到大家的反馈,包括后台内推成功的消息.朋友的同事从创业小公司成功跳到huawei等等,非常高兴小破号的这些整理分享能够真正地帮助到大家,以后也会继续.为了更 ...

  9. 【面试锦囊】14种模式搞定面试算法编程题(8-14)

    面试锦囊之知识整理系列 面试锦囊系列一直有收到大家的反馈,包括后台内推成功的消息.朋友的同事从创业小公司成功跳到huawei等等,非常高兴小破号的这些整理分享能够真正地帮助到大家,以后也会继续.为了更 ...

  10. system verilog编程题_拼多多2020校招部分算法编程题合集

    拼多多2020校招部分算法编程题2道,多多的魔术盒子和多多的排列函数 其实根据他的匹配职位我们可以看到,这5道题的难度还是并不高,只是作为一个初步筛选,我这边选择了前两道跟大家分享 [编程题一] 多多 ...

最新文章

  1. 数据中心液冷技术发展分析
  2. 薪资那么高的Web前端的工作者,想要提高薪资就必须看的书单
  3. AI人工智能ML机器学习DL深度学习
  4. 麦肯锡在全球调研分析160个案例,给出5个行业的34个AI应用场景
  5. 会动的图解!GMP模型里为什么要有P?背后的原因让人暖心
  6. 如何在ASP.NET Core中上传文档
  7. python期望输出隐藏_【归纳综述】马尔可夫、隐马尔可夫 HMM 、条件随机场 CRF 全解析及其python实现...
  8. 云服务器选ssd还是hdd_云服务器应该怎么选择?
  9. Android_WakeLock使用
  10. Citrix XenApp/XenDesktop版本正确选择
  11. 半路学习编程,有希望成为大牛吗?
  12. 【DBN预测】基于粒子群算法优化DBN深度置信网络实现数据预测matlab代码
  13. 语音关键词检索实验小结
  14. 魔方cfop公式软件_魔方与群论(一)(不要被标题吓到,高中生就可以看)
  15. 005-2-Python文件操作
  16. 水电设计院信息管理系统1.0
  17. Error creating bean with name ‘sqlSessionFactory’ defined in class path reso
  18. 如何将SW工程图转换成CAD格式?
  19. ubuntu设置pac代理
  20. 视频会议再添猛将:视源股份推出有“情怀”的MAXHUB会议平台

热门文章

  1. leetcode 39 : 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
  2. 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
  3. i78565U和i710510U的区别 i78565U和i710510U参数配置对比哪个好
  4. 信号指示RSSI与显示格数关系
  5. word embedding和contextual embedding
  6. Windows进行磁盘碎片化整理
  7. 安徽大学计算机专硕学几年,安徽大学专业硕士学制几年
  8. 6.13编一程序,将两个字符串连接起来,不要用strcat函数。
  9. MIPI-DSI 三种 Video Mode 理解
  10. 失业日记 9月30日