java算法编程题:利用单链表求集合的交集、并集和补集
题目:利用单链表求集合的交集、并集和补集
要求:使用泛型
/*** 利用单链表求集合的交集、并集和补集* 要求:使用泛型* * @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算法编程题:利用单链表求集合的交集、并集和补集相关推荐
- 使用顺序表、单链表求集合运算
******.设有两个顺序表A和B,编写一个算法将属于A,但是不属于B的数据元素放大到另一个顺序表C中 (1).算法设计 遍历顺序表A,将A中每一个元素依次与顺序表B比较,如果相等直接跳过开始比较下一 ...
- java算法编程题_【java题目】考验你编程能力和算法的时候到了
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这是我写的,但是算法很复杂,唉,求高手啊 package com.sky.woodwall; import java.util.ArrayList; im ...
- java算法编程题:士兵列队问题
题目:300名士兵分别编号为1-300,按顺序排成一排,长官下令:"双数士兵出列!",剩下的士兵重新按原序编号.长官下令:"双数士兵出列!",如此进行下去直到最 ...
- Java基础编程题(02)求100-200之间的素数
2 [程序 2 输出素数] 题目:判断 101-200 之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除 2 到 sqrt(这个数),如果能被整除,则表明此数不是素数,反 ...
- java链表交集并集,一个链表求集合并集交集的异常
C/C++ code//求并集的函数: void bingji(mylist*p,mylist*q,mylist*&r)//r作为并集列表的头指针,p,q是输入的两个指针 { mylist * ...
- A和B 单链表表示 集合,求其 交集 并集 差集
A和B 单链表表示 集合的 交集 并集 差集 /* A和B 单链表表示 集合的 交集 并集 差集 */ //#include <iostream> //using namespace st ...
- c语言用单链表实现lru算法,利用单链表实现LRU算法
利用单链表实现LRU算法 首先,我们先看下对于Node的定义: package datastructure.linklist.node; import lombok.Data; /** * 单链表节点 ...
- 【面试锦囊】14种模式搞定面试算法编程题(1-7)
面试锦囊之知识整理系列 面试锦囊系列一直有收到大家的反馈,包括后台内推成功的消息.朋友的同事从创业小公司成功跳到huawei等等,非常高兴小破号的这些整理分享能够真正地帮助到大家,以后也会继续.为了更 ...
- 【面试锦囊】14种模式搞定面试算法编程题(8-14)
面试锦囊之知识整理系列 面试锦囊系列一直有收到大家的反馈,包括后台内推成功的消息.朋友的同事从创业小公司成功跳到huawei等等,非常高兴小破号的这些整理分享能够真正地帮助到大家,以后也会继续.为了更 ...
- system verilog编程题_拼多多2020校招部分算法编程题合集
拼多多2020校招部分算法编程题2道,多多的魔术盒子和多多的排列函数 其实根据他的匹配职位我们可以看到,这5道题的难度还是并不高,只是作为一个初步筛选,我这边选择了前两道跟大家分享 [编程题一] 多多 ...
最新文章
- 数据中心液冷技术发展分析
- 薪资那么高的Web前端的工作者,想要提高薪资就必须看的书单
- AI人工智能ML机器学习DL深度学习
- 麦肯锡在全球调研分析160个案例,给出5个行业的34个AI应用场景
- 会动的图解!GMP模型里为什么要有P?背后的原因让人暖心
- 如何在ASP.NET Core中上传文档
- python期望输出隐藏_【归纳综述】马尔可夫、隐马尔可夫 HMM 、条件随机场 CRF 全解析及其python实现...
- 云服务器选ssd还是hdd_云服务器应该怎么选择?
- Android_WakeLock使用
- Citrix XenApp/XenDesktop版本正确选择
- 半路学习编程,有希望成为大牛吗?
- 【DBN预测】基于粒子群算法优化DBN深度置信网络实现数据预测matlab代码
- 语音关键词检索实验小结
- 魔方cfop公式软件_魔方与群论(一)(不要被标题吓到,高中生就可以看)
- 005-2-Python文件操作
- 水电设计院信息管理系统1.0
- Error creating bean with name ‘sqlSessionFactory’ defined in class path reso
- 如何将SW工程图转换成CAD格式?
- ubuntu设置pac代理
- 视频会议再添猛将:视源股份推出有“情怀”的MAXHUB会议平台
热门文章
- leetcode 39 : 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
- 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
- i78565U和i710510U的区别 i78565U和i710510U参数配置对比哪个好
- 信号指示RSSI与显示格数关系
- word embedding和contextual embedding
- Windows进行磁盘碎片化整理
- 安徽大学计算机专硕学几年,安徽大学专业硕士学制几年
- 6.13编一程序,将两个字符串连接起来,不要用strcat函数。
- MIPI-DSI 三种 Video Mode 理解
- 失业日记 9月30日