代码地址: https://gitee.com/Tom-shushu/Algorithm-and-Data-Structure.git

一、ArrayList自定义封装

package com.zhouhong;
/**
* @ClassName: array
* @Description: 二次封装自己的数组类
* @Author: zhouhong
* @Create: 2021-03-29 15:47
**/
public class Array <E> { private E[] data;
private int size;
// 构造函数,传入数组的容量 capacity 构造Array
public Array(int capacity){
data = (E[])new Object[capacity];
size = 0;
}
// 无参构造函数,默认数组的容量 capacity = 10
public Array(){
this(10);
}
// 获取数组实际长度
public int getSize(){
return size;
}
// 获取容量
public int getCapacity(){
return data.length;
}
// 返回数组是否为空
public boolean isEmpty(){
return size == 0;
}
// 数组最后添加 O(n)
public void addLast(E e){
add(size, e);
}
// 向数组头部添加元素 O(1)
public void addFirst(E e){
add(0, e);
}
// 获取某个位置上的元素 O(1)
public E get(int index){
if (index < 0 || index > size){
throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
}
return data[index];
}
// 更新元素 O(1)
void set(int index, E e){
if (index < 0 || index >= size){
throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
}
data[index] = e;
}
// 向指定位置添加元素 O(n)
public void add(int index, E e){
if (index < 0 || index > size){
throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
}
// 数组已满:扩容
if (size == data.length){
// 扩容 2 倍
resize(data.length * 2);
}
for (int i = size - 1; i >= index ; i--) {
data[i + 1] = data[i];
}
data[index] = e;
size ++;
} // 查找数组中是否有元素e O(n)
public boolean contains(E e){
for (int i = 0; i < size; i++) {
if (data[i].equals(e)){
return true;
}
}
return false;
}
// 查找某个元素对应的索引(重复元素只返回一个索引) O(n)
public int find(E e){
for (int i = 0; i < size; i++) {
if (data[i].equals(e)){
return i;
}
}
return -1;
}
// 删除某个指定索引上的元素(直接覆盖、前移),返回删除的元素 O(n)
public E remove(int index){
if (index < 0 || index >= size){
throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
}
E result = data[index];
for (int i = index; i < size; i++) {
data[i] = data[i + 1];
}
size --;
data[size] = null;
// 当长度小于容量的 1/2 把容量自动缩小为原来长度的 1/2
// 懒加载,当为1/4时缩容
if (size == data.length >> 2 && data.length >> 1 != 0){
resize(data.length / 2);
} return result;
}
// 删除第一个元素 O(n)
public E removeFirst(){
return remove(0);
}
// 删除最后一个元素 O(1)
public E removeLast(){
return remove(size - 1);
}
// 如果数组中有某个元素,就删除(相同元素,只删除一个)
public void removeElenent(E e){
int index = find(e);
if (index != -1){
remove(index);
}
}
// 扩容
private void resize(int newCapacity){
E[] newData = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
} @Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(java.lang.String.format("Array: size = %d, capacity = %d\n", size, data.length));
result.append('[');
for (int i = 0; i < size; i++) {
result.append(data[i]);
if (i != size - 1){
result.append(", ");
}
}
result.append(']');
return result.toString();
}
}

二、用我们自定义的动态数组实现队列

package com.zhouhong;

/**
* @ClassName: array-queue
* @Description: 基于数组的普通队列
* @Author: zhouhong
* @Create: 2021-03-30 23:55
**/ public class ArrayQueue<E> implements QueueInterface<E> {
private Array<E> array; public ArrayQueue(int capacity){
array = new Array<>(capacity);
} public ArrayQueue(){
array = new Array<>();
} @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 int getSize() {
return array.getSize();
} public int getCapacity() {
return array.getCapacity();
} @Override
public boolean isEmpty() {
return array.isEmpty();
} @Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Queue:");
res.append("front [");
for (int i = 0; i < array.getSize(); i++) {
res.append(array.get(i));
if (i != array.getSize() - 1){
res.append(", ");
}
}
res.append("] tail");
return res.toString();
} }

三、使用动态数组实现栈

package com.zhouhong;

/**
* @ClassName: stack
* @Description: 使用数组实现一个栈
* @Author: zhouhong
* @Create: 2021-03-30 22:37
**/ public class ArrayStack<E> implements StackInterface<E>{ Array<E> array;
public ArrayStack(int capacity){
array = new Array<>(capacity);
}
public ArrayStack(){
array = new Array<>();
} @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();
}
public int getCapacity(){
return array.getCapacity();
} @Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Stack:");
res.append('[');
for (int i = 0; i < array.getSize(); i++) {
res.append(array.get(i));
if (i != array.getSize() - 1){
res.append(", ");
}
}
res.append("] top");
return res.toString();
}
}

四、链表常见操作实现

package com.zhouhong;

/**
* @ClassName: linkedlist
* @Description: 链表
* @Author: zhouhong
* @Create: 2021-03-31 15:25
**/ public class LinkedList<E> { private class Node{
public E e;
public Node next; public Node(E e, Node next){
this.e = e;
this.next = next;
}
public Node(E e){
this(e, null);
}
public Node(){
this(null, null);
}
@Override
public String toString(){
return e.toString();
}
}
//使用head,会使得add方法在向首部添加元素时找不到当前元素对应的前一个元素
// private Node head;
// 虚拟头结点
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;
}
// 在链表index中间添加元素
public void add(E e, int index){
if (index < 0 || index > size){
throw new IllegalArgumentException("ADD failed, Illegal index.");
}
Node pre = dummyHead;
// 遍历找到所要插入节点的前一个节点
for (int i = 0; i < index; i++) {
pre = pre.next;
}
// Node node = new Node(e);
// node.next = pre.next;
// pre = node;
pre.next = new Node(e, pre.next);
size ++;
}
// 为链表头部添加元素
public void addFirst(E e){
// Node node = new Node(e);
// node.next = head;
// head = node;
add(e,0);
}
// 想链表末尾添加元素
public void addLast(E e){
add(e, size);
}
// 获得链表的第index 个位置的元素
// 在链表中不是一个常用的操作,练习用
public E get(int index){
if (index < 0 || index >= size){
throw new IllegalArgumentException("ADD failed, Illegal index.");
}
Node cur = dummyHead.next;
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 - 1);
}
// 修改链表的第 index 个位置的元素为e
// 在链表中不是一个常用的操作,练习用
public void set(int index, E e){
if (index < 0 || index > size){
throw new IllegalArgumentException("Update failed, Illegal index.");
}
Node cur = dummyHead.next;
// 遍历找到所要插入节点的前一个节点
for (int i = 0; i < index; i++) {
cur = cur.next;
}
cur.e = 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("remove failed, Illegal index.");
}
Node pre = dummyHead;
// 遍历找到所要删除节点的前一个节点
for (int i = 0; i < index; i++) {
pre = pre.next;
}
Node node = pre.next;
pre.next = node.next;
node.next = null;
size --;
return node.e;
}
// 从链表中删除第一个元素,返回删除元素
public E removeFirst(){
return remove(0);
}
// 从链表中删除最后一个元素,返回删除元素
public E removeLast(){
return remove(size - 1);
} @Override
public String toString(){
StringBuilder res = new StringBuilder();
Node cur = dummyHead.next;
while (cur != null){
res.append(cur + "->");
cur = cur.next;
}
res.append("NULL");
return res.toString();
}
}

用基础Array数组实现动态数组、链表、栈和队列的更多相关文章

  1. JS 索引数组、关联数组和静态数组、动态数组

    JS 索引数组.关联数组和静态数组.动态数组 数组分类: 1.从数组的下标分为索引数组.关联数组 var ary1 = [1,3,5,8]; //按索引去取数组元素,从0开始(当然某些语言实现从1开始 ...

  2. "《算法导论》之‘队列’":队列的三种实现(静态数组、动态数组及指针)

    本文有关栈的介绍部分参考自网站数据结构. 1. 队列  1.1 队列的定义 队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表. (1)允许删除的一端称为队头(Front) ...

  3. solidity定长数组和动态数组

    固定长度的数组 固定长度数组声明 直接在定义数组的时候声明固定长度数组的值: uint[5] fixedArr = [1,2,3,4,5]; 可通过数组的length属性来获得数组的长度,进而进行遍历 ...

  4. C语言- 基础数据结构和算法 - 动态数组

    听黑马程序员教程<基础数据结构和算法 (C版本)>,照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友可 ...

  5. array of TVarRec 动态数组使用

    FDQuery.AppendRecord()里是一个array of TVarRec.我们一般都是直接用[Var1,Var2,...].这样手工输入,但如果增加的元素我们预先不知道,就要声明一个arr ...

  6. C语言柔性数组和动态数组

    [前言]经常看到C语言里的两个数组,总结一下. 一.柔性数组 参考:https://www.cnblogs.com/veis/p/7073076.html #include<stdio.h> ...

  7. C语言数组:C语言数组定义、二维数组、动态数组、字符串数组

    1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...

  8. C/C++静态数组与动态数组的区别

    简介 以下三行代码有什么区别? int a[10]; int *a = (int*)malloc(sizeof(int)*10); int *a = new int[10]; 第一行代码定义a为包含1 ...

  9. "《算法导论》之‘栈’":栈的三种实现(静态数组、动态数组及指针)

    本文有关栈的介绍部分参考自网站数据结构. 1. 栈  1.1 栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底( ...

  10. Java程序猿学习C++之数组和动态数组

    数组: #include <iostream> using namespace std; //模板函数 template <class T> void dump(T val) ...

随机推荐

  1. dotnet OpenXML 读取 PPT 内嵌 xlsx 格式 Excel 表格的信息

    在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式.本文来介绍如何读取 PPT 内嵌 xlsx 格式的表格的方法 读取方法和 ...

  2. 前端如何操作动态渲染的多个checkbox列表单选

    input[type=checkbox]:after{     content:"";     display:inline-block;     width:16px;      ...

  3. JUC并发编程学习笔记(十九)原子引用

    原子引用 带版本号的原子操作! 解决ABA问题,引入原子引用(乐观锁思想) AtomicStampedReference类解决ABA问题 package org.example.cas; import ...

  4. 一键自动化博客发布工具,用过的人都说好(segmentfault篇)

    segmentfault是我在这些平台中看过界面最为简洁的博客平台了. 今天就以segmentfault为例,讲讲在blog-auto-publishing-tools中的实现原理. 前提条件 前提条 ...

  5. 模型压缩与部署-书生浦语大模型实战营学习笔记5&大语言模型11

    大语言模型-11.模型压缩与部署 书生浦语大模型实战营学习笔记4-模型压缩与部署 本文包括第二期实战营的第5课内容,介绍关于模型压缩的相关内容,主要包括.模型量化和模型部署的相关内容. 模型部署 定义 ...

  6. FE知识点(硕哥)

    目录 前传: 1.typeof和类型转换 正文: 1.作用域.作用域链([[scope]]) 2.立即执行函数 3.闭包 4.对象.包装类 5.原型原型链 6.call.apply 7.继承模式.命名 ...

  7. LLM实战:LLM微调加速神器-Unsloth + LLama3

    1. 背景 五一结束后,本qiang~又投入了LLM的技术海洋中,本期将给大家带来LLM微调神器:Unsloth. 正如Unsloth官方的对外宣贯:Easily finetune & tra ...

  8. powershell 设置代理

    $env:HTTP_PROXY="http://127.0.0.1:10809" $env:HTTPS_PROXY="http://127.0.0.1:10809&quo ...

  9. mybatis-puls解决多数据源事务的问题

    直接上代码: pom: <!--JTA组件核心依赖--> <dependency> <groupId>org.springframework.boot</gr ...

  10. Java8 Lambda表达式入门

    可能很多人都听说过java8的新特性----Lambada表达式,但可能很多人都不知道Lambda表达式到底有什么用,下面我带大家理解一下Lambada表达式. 在平时的编程中,我们常常会用到匿名内部 ...