基础数据结构的Java实现
简介
基础数据结构:
Java自带类集合框架及继承关系:
数组(Array)
Array:数组结构的实现
package 数据结构.数组;
/**
* 数组
* */
public class Array<E> {
private E[] data;
private int size;
public Array(int ca){
// String[] data = (String[]) new Object[4];
//实例化
data = (E[])new Object[ca];
size = 0;
}
public Array(){
this(10);
}
public int getSize(){
return size;
}
public int getCapacity(){
return data.length;
}
public boolean isEmpty(){
return size == 0;
}
/**
* 向数组头部添加一个元素
* */
public void addFirst(E e){
add(0,e);
}
/**
* 向数组尾部插一个元素
* */
public void addLast(E e){
add(size,e);
}
/**
* 在数组的指定位置添加一个元素
* */
public void add(int index,E e){
if(index < 0 || index > size){
throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size");
}
if(size == data.length){
//如果数组容量满了,则动态扩容两倍
resize(2*data.length);
}
for (int i= size-1; i >= index; i--){
data[i+1] = data[i];
}
data[index] = e;
size++;
}
/**
* 数组动态扩容
* */
private void resize(int newCa){
E[] newData = (E[]) new Object[newCa];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
}
/**
* 获取指定位置的元素
* */
public E get(int index){
if(index < 0 || index >= size){
throw new IllegalArgumentException("Get failed. index is Illegal.");
}
return data[index];
}
/**
* 获取第一个元素
*/
public E getFirst() {
return data[0];
}
/**
* 获取最后一个元素
*/
public E getLast() {
return get(size - 1);
}
/**
* 修改指定位置的元素
*/
public void set(int index, E e){
if (index < 0 || index >= size){
throw new IllegalArgumentException("Set failed. index is Illegal.");
}
data[index] = e;
}
/**
* 查看数组中是否包含某个元素
*/
public boolean contains(E e){
for (int i = 0; i < size; i++) {
if(data[i].equals(e)){
return true;
}
}
return false;
}
/**
* 查找元素在数组的位置
* */
public int indexOf(E e){
for (int i = 0; i < size ; i++) {
if(data[i].equals(e)){
return i;
}
}
return -1;
}
/**
* 移除数组中的元素
* */
public E remove(int index){
if (index < 0 || index >= size){
throw new IllegalArgumentException("Remove failed. index is Illegal.");
}
E result = data[index];
for (int i = index + 1; i < size; i++) {
data[i-1] = data[i];
}
size--;
//修改对象引用,垃圾回收机制回收
data[size] = null;
//动态缩小数组一半容量
if(size == data.length/4 && data.length/2 != 0){
resize(data.length/2);
}
return result;
}
/**
* 移除数组中的第一个元素
*/
public E removeFirst(){
return remove(0);
}
/**
* 移除数组中的最后一个元素
*/
public E removeLast(){
return remove(size - 1);
}
/**
* 移除数组中的某个元素
*/
public void removeElement(E e){
int index = indexOf(e);
if(index != -1){
remove(index);
}
}
/**
* 自定义print方法
*/
public void print(){
System.out.println("Array: size = " + size + " , capacity = " +data.length);
System.out.print("[");
for (int i = 0; i < size; i++){
System.out.print(data[i]);
if(i != size - 1){
System.out.print(",");
}
}
System.out.println("]");
}
}
Test : 测试类
package 数据结构.数组;
public class Test {
public static void main(String[] args) {
Array<Integer> array= new Array(20);
for (int i = 0; i < 20; i++) {
array.addLast(i);
}
System.out.println("原始数组:");
array.print();
System.out.println("-------------------------------------------------------");
System.out.println("在index=1的位置添加元素200");
array.add(1,200);
array.print();
System.out.println("-------------------------------------------------------");
System.out.println("获取index=4的元素");
System.out.println("get:"+array.get(4));
System.out.println("-------------------------------------------------------");
System.out.println("把index=3的元素修改为500");
array.set(3,500);
array.print();
System.out.println("-------------------------------------------------------");
System.out.println("获取元素为200的index");
System.out.println("indexOf:"+array.indexOf(200));
System.out.println("-------------------------------------------------------");
System.out.println("移除index=1的元素");
array.remove(1);
array.print();
System.out.println("-------------------------------------------------------");
System.out.println("移除数组第一个元素");
array.removeFirst();
array.print();
System.out.println("-------------------------------------------------------");
System.out.println("移除最后一个元素");
array.removeLast();
array.print();
System.out.println("-------------------------------------------------------");
System.out.println("移除元素为8");
array.removeElement(8);
array.print();
}
}
结果:
原始数组:
Array: size = 20 , capacity = 20
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
-------------------------------------------------------
在index=1的位置添加元素200
Array: size = 21 , capacity = 40
[0,200,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
-------------------------------------------------------
获取index=4的元素
get:3
-------------------------------------------------------
把index=3的元素修改为500
Array: size = 21 , capacity = 40
[0,200,1,500,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
-------------------------------------------------------
获取元素为200的index
indexOf:1
-------------------------------------------------------
移除index=1的元素
Array: size = 20 , capacity = 40
[0,1,500,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
-------------------------------------------------------
移除数组第一个元素
Array: size = 19 , capacity = 40
[1,500,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
-------------------------------------------------------
移除最后一个元素
Array: size = 18 , capacity = 40
[1,500,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
-------------------------------------------------------
移除元素为8
Array: size = 17 , capacity = 40
[1,500,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18]
Process finished with exit code 0
链表(LinkedList)
LinkedList :链表结构的实现
package 数据结构.链表;
//链表结构
public class LinkedList<E> {
//虚拟头节点
private Node dummyHead;
//链表大小
private int size;
//初始化
public LinkedList(){
dummyHead = new Node(null,null);
size = 0;
}
public int getSize(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
//向链表指定位置添加元素
public void add(int index,E e){
if(index < 0 || index > size){
throw new IllegalArgumentException("Add faild. Illegal index.");
}
//prev 指向头节点(索引为0节点的前驱节点)
Node prev = dummyHead;
//找到index位置的前驱节点
for (int i = 0; i < index; i++) {
prev = prev.next;
}
//Node node = new Node(e);
//node.next = prev.next;
//prev.next = node;
prev.next = new Node(e,prev.next);
size++;
}
//向链表头添加元素
public void addFirst(E e){
add(0,e);
}
//向链表尾部添加元素
public void addLast(E e){
add(size,e);
}
//获取指定位置元素
public E get(int index){
if(index < 0 || index > size){
throw new IllegalArgumentException("Get faild. Illegal index.");
}
//cur指向索引为0的节点
Node cur = dummyHead.next;
//循环使cur指向index位置
for (int i = 0; i < index; i++) {
cur = cur.next;
}
return cur.e;
}
//获取链表头部的元素
public E getFirst(){
return get(0);
}
//获取链表尾部的元素
public E getLast(){
return get(size);
}
//修改指定位置元素
public void set(int index, E e){
if(index < 0 || index > size){
throw new IllegalArgumentException("Set failed. Illegal index.");
}
//指向索引为0的位置
Node cur = dummyHead.next;
//循环使cur指向index位置
for (int i = 0; i < index; i++) {
cur = cur.next;
}
cur.e = e;
}
//判断链表是否包含某个元素
public boolean contains(E e){
Node cur = dummyHead.next;
while(cur != null){
if(cur.e.equals(e)){
return true;
}
cur = cur.next;
}
return false;
}
//删除指定位置的元素(index)
public E remove(int index){
if(index < 0 || index > size){
throw new IllegalArgumentException("Delete failed. Illegal index.");
}
//prev 指向头节点(索引为0节点的前驱节点)
Node prev = dummyHead;
//prev指向index位置的前驱节点
for (int i = 0; i < index; i++) {
prev = prev.next;
}
Node delNode = prev.next; //要删除的节点
prev.next = delNode.next;
delNode.next = null;
size --;
return delNode.e;
}
//删除指定元素(第一个找到的)
public void remove(E e){
//判断是否存在
if(!contains(e)){
throw new IllegalArgumentException("Delete failed. e is not exists.");
}
Node prev = dummyHead;
//找到值为e的前驱节点
while (prev.next != null){
if(prev.next.e.equals(e)){
break;
}
prev = prev.next;
}
//删除节点
if(prev.next != null){
Node delNode = prev.next;
prev.next = delNode.next;
delNode.next = null;
size--;
}
}
//删除所有的指定元素
public void removeAll(E e){
if(!contains(e)){
throw new IllegalArgumentException("Delete failed. e is not exists.");
}
Node prev = dummyHead;
while(prev.next != null){
if(prev.next.e.equals(e)){
Node delNode = prev.next;
prev.next = delNode.next;
delNode.next = null;
size --;
continue;
}
prev = prev.next;
}
}
//删除链表头部的元素
public E removeFirst(){
return remove(0);
}
//删除链表尾部的元素
public E removeLast(){
return remove(size - 1);
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(String.format("LinkedList: size: %d\n",size));
result.append("head ");
Node cur = dummyHead.next;
while (cur != null){
result.append(cur+ "->");
cur = cur.next;
}
result.append("NULL");
return result.toString();
}
//定义节点
private class Node{
private E e;
private Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this.e = e;
}
public Node() {
this(null,null);
}
@Override
public String toString() {
return e.toString();
}
}
}
Test : 测试类
package 数据结构.链表;
public class Test {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 10; i++) {
linkedList.addFirst(i);
System.out.println(linkedList.toString());
}
System.out.println("————————————————————————————————————————————");
System.out.println("在index=5的位置插入520");
linkedList.add(5,520);
System.out.println(linkedList.toString());
System.out.println("————————————————————————————————————————————");
System.out.println("移除index = 5 的元素");
linkedList.remove(5);
System.out.println(linkedList.toString());
System.out.println("————————————————————————————————————————————");
System.out.println("移除链表第一个元素");
linkedList.removeFirst();
System.out.println(linkedList.toString());
System.out.println("————————————————————————————————————————————");
System.out.println("移除链表最后一个元素");
linkedList.removeLast();
System.out.println(linkedList.toString());
System.out.println("————————————————————————————————————————————");
System.out.println("移除index=4的元素");
linkedList.remove(4);
System.out.println(linkedList.toString());
System.out.println("————————————————————————————————————————————");
System.out.println("先插入e为4的元素,然后删除全部");
linkedList.addFirst(4);
linkedList.addFirst(4);
linkedList.addFirst(4);
linkedList.removeAll(4);
System.out.println(linkedList.toString());
System.out.println("————————————————————————————————————————————");
}
}
结果:
LinkedList: size: 1
head 0->NULL
LinkedList: size: 2
head 1->0->NULL
LinkedList: size: 3
head 2->1->0->NULL
LinkedList: size: 4
head 3->2->1->0->NULL
LinkedList: size: 5
head 4->3->2->1->0->NULL
LinkedList: size: 6
head 5->4->3->2->1->0->NULL
LinkedList: size: 7
head 6->5->4->3->2->1->0->NULL
LinkedList: size: 8
head 7->6->5->4->3->2->1->0->NULL
LinkedList: size: 9
head 8->7->6->5->4->3->2->1->0->NULL
LinkedList: size: 10
head 9->8->7->6->5->4->3->2->1->0->NULL
————————————————————————————————————————————
在index=5的位置插入520
LinkedList: size: 11
head 9->8->7->6->5->520->4->3->2->1->0->NULL
————————————————————————————————————————————
移除index = 5 的元素
LinkedList: size: 10
head 9->8->7->6->5->4->3->2->1->0->NULL
————————————————————————————————————————————
移除链表第一个元素
LinkedList: size: 9
head 8->7->6->5->4->3->2->1->0->NULL
————————————————————————————————————————————
移除链表最后一个元素
LinkedList: size: 8
head 8->7->6->5->4->3->2->1->NULL
————————————————————————————————————————————
移除index=4的元素
LinkedList: size: 7
head 8->7->6->5->3->2->1->NULL
————————————————————————————————————————————
先插入e为4的元素,然后删除全部
LinkedList: size: 7
head 8->7->6->5->3->2->1->NULL
————————————————————————————————————————————
Process finished with exit code 0
栈(Stack)
Stack:栈(接口)
package 数据结构.Stack;
/**
*栈
* */
public interface Stack<E> {
//获取栈的大小
int getSize();
//判断栈是否为空
boolean isEmpty();
//向栈中插入一个元素
void push(E e);
//向栈中移除一个元素
E pop();
//查看栈顶元素
E peek();
}
ArrayStack:利用数组实现栈
package 数据结构.Stack;
//利用动态数组实现栈
public class ArrayStack<E> implements Stack<E> {
//定义数组
Array<E> array;
public ArrayStack(int ca){
array = new Array<>(ca);
}
public ArrayStack(){
array = new Array<>();
}
public int getCapacity(){
return array.getCapacity();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public void push(E e) {
array.addLast(e);
}
@Override
public E pop() {
return array.removeLast();
}
@Override
public E peek() {
return array.getLast();
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(String.format("Stack: size = %d , capacity = %d\n",array.getSize(),array.getCapacity()));
result.append("[");
for (int i = 0; i < array.getSize(); i++) {
result.append(array.get(i));
if(i != array.getSize() - 1){
result.append(", ");
}
}
result.append("] top");
return result.toString();
}
}
LinkedListStack:利用链表实现栈
package 数据结构.Stack;
//链表来实现栈
public class LinkedListStack<E> implements Stack<E> {
//定义链表
private LinkedList<E> list;
public LinkedListStack(){
this.list = new LinkedList<>();
}
@Override
public int getSize() {
return list.getSize();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void push(E e) {
list.addFirst(e);
}
@Override
public E pop() {
return list.removeFirst();
}
@Override
public E peek() {
return list.getFirst();
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(String.format("Stack: size = %d \n", list.getSize()));
result.append("top ");
result.append(list);
return result.toString();
}
}
Test:测试数组栈和链表栈,同时进栈50000再全部出栈,消耗时间对比。
package 数据结构.Stack;
import java.util.Random;
public class Test {
public static void main(String[] args) {
int count = 50000;
ArrayStack<Integer> arrayStack = new ArrayStack<>();
System.out.println("ArrayStack: "+Stack_Use_Time(arrayStack,count)+"s");
LinkedListStack linkedListStack = new LinkedListStack();
System.out.println("LinkedListStack:"+Stack_Use_Time(linkedListStack,count)+"s");
}
private static double Stack_Use_Time(Stack<Integer> stack, int count){
long startTime = System.nanoTime();
Random random = new Random();
for (int i = 0; i < count; i++) {
int nextInt = random.nextInt(Integer.MAX_VALUE);
stack.push(nextInt);
}
for (int i = 0; i < count; i++) {
stack.pop();
}
long endTime = System.nanoTime();
return (endTime - startTime)/1000000000.0;
}
}
结果:
ArrayStack: 0.011231s
LinkedListStack:0.0068895s
Process finished with exit code 0
如果数据量变为5000000,结果为:
ArrayStack: 0.2077511s
LinkedListStack:1.792212s
Process finished with exit code 0
LetCode 20(补充)
题目:
- LeetCode 20
- 给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
- 有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 注意空字符串可被认为是有效字符串。
代码:
package 数据结构.Stack;
/**
* LeetCode 20
* 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
* 有效字符串需满足:
* 左括号必须用相同类型的右括号闭合。
* 左括号必须以正确的顺序闭合。
* 注意空字符串可被认为是有效字符串。
*/
public class LetCodeTest {
public boolean isValid(String str){
ArrayStack<Character> stack = new ArrayStack();
for (int i = 0; i < str.length() ; i++) {
char c = str.charAt(i);
if(c == '(' || c == '[' || c == '{'){
stack.push(c);
}else{
if(stack.isEmpty()){
return false;
} else if (c == ')' && stack.pop() == '('){
return true;
} else if (c == ']' && stack.pop() == '['){
return true;
} else if (c == '}' && stack.pop() == '{'){
return true;
}else{
return false;
}
}
}
return stack.isEmpty();
}
public static void main(String[] args) {
String str1 = "{([{)}";
String str2 = "{()}";
String str3 = "{(";
boolean b1 = new LetCodeTest().isValid(str1);
boolean b2 = new LetCodeTest().isValid(str2);
boolean b3 = new LetCodeTest().isValid(str3);
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
}
}
结果:
false
true
false
Process finished with exit code 0
队列(Queue)
Queue:队列接口
package 数据结构.Queue;
//队列
public interface Queue<E> {
//获取队列的大小
int getSize();
//查看队列是否为空
boolean isEmpty();
//将一个元素插入队尾
void enqueue(E e);
//将队首一个元素移除队列
E dequeue();
//获取队首的一个元素
E getFront();
}
ArrayQueue:利用数组实现队列
package 数据结构.Queue;
//用数组实现队列
public class ArrayQueue<E> implements Queue<E> {
private Array<E> array;
public ArrayQueue(int capacity){
array = new Array<>(capacity);
}
public ArrayQueue(){
array = new Array<>();
}
@Override
public int getSize() {
return array.getSize();
}
public int getCapacity(){
return array.getCapacity();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public void enqueue(E e) {
array.addLast(e);
}
@Override
public E dequeue() {
return array.removeFirst();
}
@Override
public E getFront() {
return array.getFirst();
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Queue: size = %d , capacity = %d",array.getSize(),array.getCapacity());
result.append("front [");
for (int i = 0; i < array.getSize(); i++) {
result.append(array.get(i));
if(i != array.getSize() - 1){
result.append(", ");
}
}
result.append("] tail");
return result.toString();
}
}
LinkedListQueue:利用链表实现队列
package 数据结构.Queue;
//利用链表实现队列
public class LinkedListQueue<E> implements Queue<E> {
LinkedList<E> list;
public LinkedListQueue() {
list = new LinkedList<>();
}
@Override
public int getSize() {
return list.getSize();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void enqueue(E e) {
list.addLast(e);
}
@Override
public E dequeue() {
return list.removeFirst();
}
@Override
public E getFront() {
return list.getFirst();
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(String.format("Queue: size = %d \n",list.getSize()));
result.append("front [");
result.append(list);
result.append("] tail");
return result.toString();
}
}
LoopQueue:循环队列
package 数据结构.Queue;
//循环队列
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front, tail;
private int size;
public LoopQueue(int capacity) {
data = (E[]) new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
}
public LoopQueue() {
this(10);
}
@Override
public int getSize() {
return size;
}
public int getCapacity() {
return data.length - 1;
}
@Override
public boolean isEmpty() {
return front == tail;
}
@Override
public void enqueue(E e) {
//判断队列容量是否已满
if ((tail + 1) % data.length == front) {
//扩容
resize(getCapacity() * 2);
}
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity + 1];
for (int i = 0; i < size; i++) {
newData[i] = data[(i + front) % data.length];
}
data = newData;
front = 0;
tail = size;
}
@Override
public E dequeue() {
if (isEmpty()) {
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
}
E result = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {
//缩容
resize(getCapacity() / 2);
}
return result;
}
@Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("Queue is empty");
}
return data[front];
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(String.format("Queue: size = %d , capacity = %d\n", size, data.length));
result.append("front [");
for (int i = front; i != tail; i = (i + 1) % data.length) {
result.append(data[i]);
if ((i + 1) % data.length != tail) {
result.append(", ");
}
}
result.append("] tail");
return result.toString();
}
}
Test:100000条数据测试ArrayQueue LinkedListQueue LoopQueue各自消耗时间
package 数据结构.Queue;
import java.util.Random;
public class Test {
public static void main(String[] args) {
int count = 100000;
ArrayQueue<Integer> queue = new ArrayQueue<>();
double arrayQueueTime = Queue_Use_time(queue, count);
System.out.println("ArrayQueue: "+arrayQueueTime + " s");
LoopQueue<Integer> loopQueue = new LoopQueue<>();
double loopQueueTime = Queue_Use_time(loopQueue, count);
System.out.println("LoopQueue: "+loopQueueTime + " s");
LinkedListQueue<Integer> linkedListQueue = new LinkedListQueue<>();
double linkedListQueueTime = Queue_Use_time(linkedListQueue, count);
System.out.println("LinkedListQueue: "+linkedListQueueTime + " s");
}
private static double Queue_Use_time(Queue<Integer> queue,int count){
long startTime = System.nanoTime();
Random random = new Random();
for (int i = 0; i < count; i++) {
int nextInt = random.nextInt(Integer.MAX_VALUE);
queue.enqueue(nextInt);
}
for (int i = 0; i < count; i++) {
queue.dequeue();
}
long endTime = System.nanoTime();
return (endTime - startTime)/1000000000.0;
}
}
结果:
ArrayQueue: 3.2535531 s
LoopQueue: 0.0115715 s
LinkedListQueue: 8.0370858 s
Process finished with exit code 0