数据结构与算法(二+)——向量的Java实现
时间:2020-03-24
本文章向大家介绍数据结构与算法(二+)——向量的Java实现,主要包括数据结构与算法(二+)——向量的Java实现使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
数据结构与算法(二+)——向量的Java实现
iwehdio的博客园:https://www.cnblogs.com/iwehdio/
1、项目结构
理论部分见:https://www.cnblogs.com/iwehdio/p/12273829.html
-
项目结构:
-
核心类体系结构与功能:
2、辅助类
-
User:
package Domin; public class User { private int id; private int age; private String phoneNumber; public User(int id, int age, String phoneNumber) { this.id = id; this.age = age; this.phoneNumber = phoneNumber; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return id == user.id && age == user.age && phoneNumber.equals(user.phoneNumber); } @Override public String toString() { return "User{id=" + id + ", age=" + age + ", phoneNumber='" + phoneNumber + '\'' + '}'; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } }
-
Fib:
package Domin; public class Fib { private int[] Arr; private int max_num = 5; private int N; private int n; private int index; public Fib(int N) { Arr = new int[max_num]; this.N = N; this.generateTable(); } private int generateTable(){ if(this.N <= 0) return -1; else if(this.N == 1) { Arr[0] = 1; return 1; }else { Arr[0] = 1; Arr[1] = 1; } int i = 1; while (Arr[this.n = i++] < this.N) { if(i >= max_num) this.expand(); Arr[i] = Arr[i-1] + Arr[i-2]; } this.index = i; this.prev(); return this.n; } public int prev(){ return --this.index; } public int get(){ return this.Arr[this.index-1]; } public void show(){ if(this.n == 0){ System.out.println("向量为空"); } else { System.out.print("["); for (int i = 0; i < this.n; i++) { System.out.print(this.Arr[i] + ", "); } System.out.println(this.Arr[this.n] + "]"); } } private int expand(){ int new_size = this.max_num * 2; int[] B = new int[new_size]; for(int i = 0; i < this.max_num; i++){ B[i] = this.Arr[i]; } max_num = new_size; this.Arr = B; System.out.println("Fib数组扩容完成,最大容量为" + this.max_num); return new_size; } }
-
Fib_Test 测试类:
package Test; import Domin.Fib; public class Fib_Test { public static void main(String[] args) { int num = 100; Fib fib = new Fib(num); fib.show(); System.out.println("最后一项" + fib.get()); fib.prev(); System.out.println("前移一项" + fib.get()); } }
-
结果为:
Fib数组扩容完成,最大容量为10 Fib数组扩容完成,最大容量为20 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144] 最后一项89 前移一项55
-
-
ExceptionBoundaryViolation:
package Error; public class ExceptionBoundaryViolation extends RuntimeException { public ExceptionBoundaryViolation(String error){ super(error); } }
3、Vector接口的实现
-
Vector接口:
- 要传入秩作为参数的,都需要考虑下标越界异常。
- 删除重载了单个元素删除和区间删除。
- 引入了泛型,但只用于元素输入输出时的类型转换。
import Error.ExceptionBoundaryViolation; public interface Vector<T> { //规模 public int getSize(); //判空 public boolean isEmpty(); //索引,有索引输入的都抛出下标越界异常 public T get(int rank) throws ExceptionBoundaryViolation; //替换 public T replace(int rank, T obj) throws ExceptionBoundaryViolation; //插入 public T insert(int rank, T obj) throws ExceptionBoundaryViolation; //删除 public T remove(int rank) throws ExceptionBoundaryViolation; public int remove(int left, int right) throws ExceptionBoundaryViolation; //显示 public void show(); }
-
Vector_Array 不可扩容向量实现类:
package Vector; import Error.ExceptionBoundaryViolation; public class Vector_Array<T> implements Vector<T> { private final int max_num = 1024; private int n = 0; private Object[] Array; public Vector_Array() { Array = new Object[max_num]; n = 0; } @Override public int getSize() { return n; } @Override public boolean isEmpty() { return (n == 0)? true : false; } @Override public T get(int rank) throws ExceptionBoundaryViolation { if (rank < 0 || rank >= n){ throw new ExceptionBoundaryViolation("错误0:秩越界"); } return (T)Array[rank]; } @Override public T replace(int rank, T new_obj) throws ExceptionBoundaryViolation { if (rank < 0 || rank >= n){ throw new ExceptionBoundaryViolation("错误0:秩越界"); } Object past_obj = Array[rank]; Array[rank] = new_obj; return (T)past_obj; } @Override public T insert(int rank, T obj) throws ExceptionBoundaryViolation { if (rank < 0 || rank > n) { //注意插入时对越界的判断,与n比较没有=号 throw new ExceptionBoundaryViolation("错误0:秩越界"); } else if (n + 1 > max_num) { throw new ExceptionBoundaryViolation("错误1:容量不足"); } for (int index = n; index > rank; index--) { Array[n] = Array[n-1]; } n++; Array[rank] = obj; return (T)obj; } @Override public T remove(int rank) throws ExceptionBoundaryViolation { if(rank < 0 || rank >= n) { throw new ExceptionBoundaryViolation("错误0:秩越界"); } Object past_obj = Array[rank]; for (int index = rank; index < n-1; index++){ Array[index] = Array[index + 1]; } n--; return (T)past_obj; } @Override public int remove(int left, int right){ if(left == right) return 0; while(right < n){ Array[left++] = Array[right++]; } n = left; return right - left; } @Override public void show() { if(n == 0){ System.out.println("向量为空"); } else { System.out.print("["); for (int index = 0; index < n-1; index++) { System.out.print(this.get(index) + ", "); } System.out.println(this.get(n-1) + "]"); } } }
-
Vector_ExtArray 可扩容向量实现类:
- 重载了基于复制区间的构造方法。
- 扩容方法每次加倍扩容。
package Vector; import Error.ExceptionBoundaryViolation; public class Vector_ExtArray<T> implements Vector<T> { //protected 可以在子类中使用 protected int max_num = 8; //初始容量 protected int n = 0; protected Object[] Array; public Vector_ExtArray() { Array = new Object[max_num]; n = 0; } public Vector_ExtArray(Vector<T> vector, int left, int right) { if(left < 0 || right > vector.getSize()) throw new ExceptionBoundaryViolation("错误2:指定的复制区域错误"); n = right - left; Array = new Object[n]; for(int i=left, j=0; i<right; i++, j++){ Array[j] = vector.get(i); } } @Override public int getSize() { return n; } @Override public boolean isEmpty() { return (n == 0)? true : false; } @Override public T get(int rank) throws ExceptionBoundaryViolation { if (rank < 0 || rank >= n){ throw new ExceptionBoundaryViolation("错误0:秩越界"); } return (T)Array[rank]; } @Override public T replace(int rank, T new_obj) throws ExceptionBoundaryViolation { if (rank < 0 || rank >= n){ throw new ExceptionBoundaryViolation("错误0:秩越界"); } Object past_obj = Array[rank]; Array[rank] = new_obj; return (T)past_obj; } @Override public T insert(int rank, T obj) throws ExceptionBoundaryViolation { if (rank < 0 || rank > n) { //注意插入时对越界的判断,与n比较没有=号 throw new ExceptionBoundaryViolation("错误0:秩越界"); } else if (n == max_num) { System.out.println("容量不足,需要扩容"); this.expand(); } for (int index = n; index > rank; index--) { Array[index] = Array[index-1]; } n++; Array[rank] = obj; return (T)obj; } @Override public T remove(int rank) throws ExceptionBoundaryViolation { if(rank < 0 || rank >= n) { throw new ExceptionBoundaryViolation("错误0:秩越界"); } Object past_obj = Array[rank]; for (int index = rank; index < n-1; index++){ Array[index] = Array[index + 1]; } n--; return (T)past_obj; } @Override public int remove(int left, int right){ if(left == right) return 0; while(right < n){ Array[left++] = Array[right++]; } n = left; return right - left; } @Override public void show() { if(n == 0){ System.out.println("向量为空"); } else { System.out.print("["); for (int index = 0; index < n-1; index++) { System.out.print(this.get(index) + ", "); } System.out.println(this.get(n-1) + "]"); } } private int expand(){ int new_size = max_num * 2; Object[] B = new Object[new_size]; for(int index = 0; index < max_num; index++){ B[index] = Array[index]; } max_num = new_size; Array = B; System.out.println("扩容完成,最大容量为" + max_num); return new_size; } }
-
Vector_ExtArray_Test 可扩容向量测试:
package Test; import Vector.Vector; import Vector.Vector_ExtArray; public class Vector_ExtArray_Test { public static void main(String[] args) { Vector<Integer> vector = new Vector_ExtArray<Integer>(); System.out.println("空向量:"); vector.show(); System.out.println("判空:" + vector.isEmpty()); System.out.println("规模:" + vector.getSize()); int num = 10; int doAt = 5; int new_data = doAt * 2; for (int i=0; i < num; i++){ vector.insert(i, i*i); } vector.show(); vector.insert(3, doAt * doAt); System.out.println("插入数据后"); vector.show(); System.out.println("规模:" + vector.getSize()); System.out.println("在秩为" + doAt + "的数据为:" + vector.get(doAt)); vector.replace(doAt, new_data); System.out.println("将在秩为" + doAt + "的数据替换为:" + new_data); System.out.println("替换后:"); vector.show(); vector.remove(doAt); System.out.println("将在秩" + doAt + "的数据移除后新数据为:" + new_data); System.out.println("删除后:"); vector.show(); System.out.println("规模:" + vector.getSize()); int left = 2; int rigth = 5; System.out.println(left + "到" + rigth + "之间删除"); vector.remove(left, rigth); vector.show(); //测试异常 vector.get(num + 1); } }
-
结果为:
空向量: 向量为空 判空:true 规模:0 插入数据后 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 规模:10 在秩为5的数据为:25 将在秩为5的数据替换为:10 替换后: [0, 1, 4, 9, 16, 10, 36, 49, 64, 81] 将在秩5的数据移除后新数据为:10 删除后: [0, 1, 4, 9, 16, 36, 49, 64, 81] 规模:9 Exception in thread "main" Error.ExceptionBoundaryViolation: 错误0:秩越界 at Vector.Vector_Array.get(Vector_Array.java:28) at Test.Vector_Array_Test.main(Vector_Array_Test.java:39)
-
-
Vector_ExtArray_AsObject_Test 向量元素为对象测试:
package Test; import Domin.User; import Vector.Vector; import Vector.Vector_ExtArray; public class Vector_ExtArray_AsObject_Test { public static void main(String[] args) { Vector<User> vector = new Vector_ExtArray<User>(); System.out.println("空向量:"); vector.show(); System.out.println("判空:" + vector.isEmpty()); System.out.println("规模:" + vector.getSize()); int num = 10; int doAt = 5; User new_data = new User(20, 22, "10086" + Integer.toString(20 * 2)); for (int i=0; i < num; i++){ vector.insert(i, new User(i, 22, "10086" + Integer.toString(i * 2))); } System.out.println("插入数据后"); vector.show(); System.out.println("规模:" + vector.getSize()); System.out.println("在秩为" + doAt + "的数据为:" + vector.get(doAt)); vector.replace(doAt, new_data); System.out.println("将在秩为" + doAt + "的数据替换为:" + new_data); System.out.println("替换后:"); vector.show(); vector.remove(doAt); System.out.println("将在秩" + doAt + "的数据移除后新数据为:" + new_data); System.out.println("删除后:"); vector.show(); System.out.println("规模:" + vector.getSize()); //测试异常 vector.get(num + 1); } }
4、无序向量与有序向量
-
DisorderVector 无序向量:
package Vector; import Error.ExceptionBoundaryViolation; public class DisorderVector<T> extends Vector_ExtArray<T>{ public int find(T e, int left, int right){ if(left < 0 || right > super.n) return -1; //right是右哨兵节点,可以等于n while((left < right--) && (!e.equals(super.Array[right]))); return right; } public int find(T e){ return find(e, 0, super.n); } //唯一化 public int uniquify(){ int removeNum = 0; for(int index=1 ; index<super.n; index++){ //从第二个元素开始 int Rank = this.find((T)super.Array[index], 0, index); if(Rank != -1){ remove(index--); removeNum++; } } return removeNum; } public DisorderVector() { super(); } @Override public T remove(int rank) throws ExceptionBoundaryViolation { return super.remove(rank); } @Override public int remove(int left, int right) { return super.remove(left, right); } @Override public int getSize() { return super.getSize(); } @Override public boolean isEmpty() { return super.isEmpty(); } @Override public T get(int rank) throws ExceptionBoundaryViolation { return super.get(rank); } @Override public T replace(int rank, T new_obj) throws ExceptionBoundaryViolation { return super.replace(rank, new_obj); } @Override public T insert(int rank, T obj) throws ExceptionBoundaryViolation { return super.insert(rank, obj); } @Override public void show() { super.show(); } }
-
Vector_DisorderVector_Test 无序向量测试:
package Test; import Vector.Vector; import Vector.DisorderVector; public class Vector_DisorderVector_Test { public static void main(String[] args) { DisorderVector<Integer> vector = new DisorderVector<Integer>(); int num = 10; int doAt = 25; for (int i=0; i < num; i++){ vector.insert(i, i*i); } vector.insert(3, doAt); vector.insert(5, doAt); vector.insert(7, doAt); vector.insert(9, doAt); vector.insert(11, 64); vector.insert(13, 0); System.out.println("插入数据后:"); vector.show(); System.out.println("寻找数据为" + doAt + "的位置:"); int Rank = vector.find(doAt); System.out.println(Rank); System.out.println("去重:"); int removeNum = vector.uniquify(); vector.show(); System.out.println("共移除了" + removeNum + "个重复元素"); } }
-
结果为:
容量不足,需要扩容 扩容完成,最大容量为16 插入数据后: [0, 1, 4, 25, 9, 25, 16, 25, 25, 25, 36, 64, 49, 0, 64, 81] 寻找数据为25的位置: 9 去重: [0, 1, 4, 25, 9, 16, 36, 64, 49, 81] 共移除了6个重复元素
-
-
Ordered 有序接口:
- 泛型必须已经实现了
compareTo()
方法。
package Vector; public interface Ordered<T extends Comparable> { //唯一化 public int uniquify(); //冒泡排序 public void bubbleSort(int left, int right); public void bubbleSort(); //归并排序 public void mergeSort(int left, int right); public void mergeSort(); //二分查找 public int binsearch(T e, int left, int right); public int binsearch(T e); //Fib查找 public int fibsearch(T e, int left, int right); public int fibsearch(T e); }
- 泛型必须已经实现了
-
OrderedVector 有序向量:
- 归并排序要注意,索引后半段向量的起始位置要加 mid,赋值原向量的起始位置要加 left 。
package Vector; import Domin.Fib; public class OrderedVector<T extends Comparable> extends Vector_ExtArray<T> implements Ordered<T> { @Override public int uniquify() { int left = 0; //双指针 int right = 0; while(++right < super.n){ if(!super.Array[left].equals(super.Array[right])){ super.Array[++left] = super.Array[right]; } } super.n = ++left; //左指针左侧是结果 return right - left; } @Override public void bubbleSort(int left, int right) { while (left < (right = bubble(left, right))); } @Override public void bubbleSort() { bubbleSort(0, super.n); } private int bubble(int left, int right){ int last = left; while (++left < right){ if(((T)super.Array[left]).compareTo(super.Array[left-1]) == -1){ last = left; T temp = (T)super.Array[left-1]; super.Array[left-1] = super.Array[left]; super.Array[left] = temp; } } return last; } @Override public void mergeSort(int left, int right) { if(right - left < 2)return; int mid = (left + right) >> 1; mergeSort(left, mid); mergeSort(mid, right); merge(left, mid, right); } @Override public void mergeSort() { mergeSort(0, super.n); } private void merge(int left, int mid, int right) { Vector_ExtArray<T> vector = new Vector_ExtArray<T>(this, left, mid); int lb = mid - left; int lc = right - mid; for(int i=0, j=0, k=0; (j<lb) || (k<lc); ) { if((j<lb) && (lc<=k || (vector.get(j).compareTo(super.Array[k + mid])<1))){ super.Array[left + i++] = vector.get(j++); } if((k<lc) && (lb<=j || (vector.get(j).compareTo(super.Array[k + mid])==1))){ super.Array[left + i++] = super.Array[k++ + mid]; } } } public int binsearch_A(T e, int left, int right) { while(left < right){ int mid = (left + right) >> 1; if(e.compareTo(super.Array[mid]) == -1){ right = mid; } else if(e.compareTo(super.Array[mid]) == 1){ left = mid + 1; } else { return mid; } } return -1; } public int binsearch_A(T e) { return binsearch_A(e, 0, super.n); } public int binsearch_B(T e, int left, int right) { int mid = (left + right) >> 1; while(right - left > 1){ mid = (left + right) >> 1; if(e.compareTo(super.Array[mid]) == -1){ right = mid; } else { left = mid ; } } return (e.equals(super.Array[mid]))? mid : -1; } public int binsearch_B(T e) { return binsearch_A(e, 0, super.n); } @Override public int binsearch(T e, int left, int right) { while(left < right){ int mid = (left + right) >> 1; if(e.compareTo(super.Array[mid]) == -1){ right = mid; } else if(e.compareTo(super.Array[mid]) == 1){ left = mid + 1; } } return --left; } @Override public int binsearch(T e) { return binsearch(e, 0, super.n); } @Override public int fibsearch(T e, int left, int right) { Fib fib = new Fib(right - left); int mid; while (right - left > fib.get()){ fib.prev(); mid = left + fib.get() -1; if(e.compareTo(super.Array[mid]) == -1){ right = mid; } else if(e.compareTo(super.Array[mid]) == 1){ left = mid + 1; } else { return mid; } } return -1; } @Override public int fibsearch(T e) { return fibsearch(e, 0, super.n); } }
-
Vector_OrderedVector_Test 有序向量测试:
package Test; import Vector.Vector; import Vector.OrderedVector; import Vector.Vector_ExtArray; import java.util.Random; public class Vector_OrderedVector_Test { public static void main(String[] args) { OrderedVector<Integer> vector = new OrderedVector<Integer>(); Random random = new Random(); int num = 20; System.out.println("查找:"); int doAt1 = 3*3; int doAt2 = 7*7; int doAt3 = 11*11; int doAt4 = 15*15; for (int i=0; i < num; i++){ vector.insert(i, i * i); } System.out.println("插入数据后"); vector.show(); int Rank = vector.binsearch_A(doAt1); System.out.println("binsearch_A:数据" + doAt1 + "在位置" + Rank); Rank = vector.binsearch_B(doAt2); System.out.println("binsearch_B:数据" + doAt2 + "在位置" + Rank); Rank = vector.binsearch_A(doAt3); System.out.println("binsearch_C:数据" + doAt3 + "在位置" + Rank); Rank = vector.fibsearch(doAt4); System.out.println("fibsearch:数据" + doAt4 + "在位置" + Rank); System.out.println("-------------------------"); System.out.println("排序:"); OrderedVector<Integer> vector1 = new OrderedVector<Integer>(); for (int i=0; i < num; i++){ vector1.insert(i, random.nextInt(100)); } System.out.println("插入数据后"); vector1.show(); System.out.println("冒泡排序:"); vector1.bubbleSort(); vector1.show(); OrderedVector<Integer> vector2 = new OrderedVector<Integer>(); for (int i=0; i < num; i++){ vector2.insert(i, random.nextInt(100)); } System.out.println("插入数据后"); vector2.show(); System.out.println("归并排序:"); vector2.mergeSort(); vector2.show(); } }
-
结果为:
查找: 容量不足,需要扩容 扩容完成,最大容量为16 容量不足,需要扩容 扩容完成,最大容量为32 插入数据后 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361] binsearch_A:数据9在位置3 binsearch_B:数据49在位置7 binsearch_C:数据121在位置11 Fib数组扩容完成,最大容量为10 fibsearch:数据225在位置15 ------------------------- 排序: 容量不足,需要扩容 扩容完成,最大容量为16 容量不足,需要扩容 扩容完成,最大容量为32 插入数据后 [89, 17, 15, 88, 80, 95, 93, 57, 21, 93, 67, 69, 30, 79, 84, 5, 19, 6, 70, 2] 冒泡排序: [2, 5, 6, 15, 17, 19, 21, 30, 57, 67, 69, 70, 79, 80, 84, 88, 89, 93, 93, 95] 容量不足,需要扩容 扩容完成,最大容量为16 容量不足,需要扩容 扩容完成,最大容量为32 插入数据后 [39, 89, 73, 24, 3, 57, 54, 83, 11, 81, 30, 42, 24, 78, 29, 73, 48, 31, 7, 38] 归并排序: [3, 7, 11, 24, 24, 29, 30, 31, 38, 39, 42, 48, 54, 57, 73, 73, 78, 81, 83, 89]
-
参考:数据结构与算法(清华大学C++描述):https://www.bilibili.com/video/av49361421
iwehdio的博客园:https://www.cnblogs.com/iwehdio/
原文地址:https://www.cnblogs.com/iwehdio/p/12558435.html
- 碎片化 | 第四阶段-32-Struts2列表展示-视频
- Angularjs中UI Router超级详细的教程{{下}}
- 碎片化 | 第四阶段-33-Struts2-Spring整合环境概述讲解-视频
- 碎片化 | 第四阶段-34-Struts2-Spring重构项目案例-视频
- Python|高阶函数
- OpenCV特征点检测——ORB特征
- 智能图片压缩-腾讯智图
- 理解javascript闭包前,先理解作用域链
- 图片加速 WebP格式
- 移动端是时候考虑抛弃jQuery了?
- 深入理解Java的接口和抽象类
- nginx负载均衡的健康检查
- 鹅厂优文 | 企点PC端性能测试-UI卡顿分析
- Javascript获取数组中的最大值和最小值的方法汇总
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 「问答」解决jar包运行时相对路径问题
- 「Eclipse」生成能用命令行运行的jar包
- 「AndroidStudio」fastjson导包报错:Could not resolve com.alibaba:fastjson:1.1.56.android
- 「Android」通过注解自动生成类文件:APT实战(AbstractProcessor)
- 五、开始Github和码云之旅,新手如何上路
- 用 Shader 写个完美的波浪~
- K8s上的Go服务怎么扩容、发版更新、回滚、平滑重启?教你用Deployment全搞定!
- 图解Go内存管理器的内存分配策略
- why哥这里有一道Dubbo高频面试题,请查收。
- 「容器平台」Kubernetes网络策略101
- 架构师之路 - 服务器硬件扫盲
- 零基础Python教程045期 元组的增删改查测试实验
- 零基础Python教程044期 列表的函数方法,很耐用!
- 零基础Python教程047期 GUI窗体界面编程,迈出软件开发的第一步
- 零基础Python教程046期 矩阵行列互换算法,二维数组的典型应用