首先来分析一下,这几种存储结构需要实现的共同点,也就是最基础的增删改查。
那么把它们的共性先提取出来,形成一个List接口。然后编写实现时需要继承该接口,重写里面的方法即可。
List接口
这是一个接口,包含这几个操作都需要的基本方法,头部添加元素,尾部添加元素,删除头部元素,删除尾部元素,删除指定元素,更改元素,查找元素,和元素的个数统计。
public interface List<T> {
//头部添加
void addHead(T value);
//尾部添加
void addTail(T value);
//头部删除
void removeHead();
//尾部删除
void removeTail();
//指定元素的删除
void removeValue(T value);
//更新元素
void change(T srcValue, T aimValue);
//查找元素
boolean search(T value);
int size();
}
ArrayList(动态数组)的实现
MyArrayList
import java.util.Arrays;
public class MyArrayList<T extends Comparable<T>> implements List<T> {
private T[] element;
private int size;// 标记当前有效数据个数
private static final int INITSIZE = 10;//开始时的数组大小
public MyArrayList() {
element = (T[]) new Comparable[INITSIZE];
size = 0;
}
/*
比较元素的个数和数组的大小
如果满就进行1.5倍扩容
创建一个新的数组(是原数组的1.5倍)并把之前的数组元素复制过来
*/
private void ensureCapacity() {
if (element.length == size) { // 已经填满
int newLength = element.length + (element.length >> 1);
element = Arrays.copyOf(element, newLength);
}
}
/**
* 尾部添加操作
* @param value 需要添加的值
*/
public void addTail(T value) {
// 判满扩容操作
ensureCapacity();
element[size++] = value;
}
/**替换制定元素
*
* @param index 旧元素的下标
* @param value 新元素的值
*/
public void change(T index, T value) {
for (int i = 0; i < size; i++) {
if (element[i].compareTo(index) == 0) {
element[i] = value;
}
}
}
/**头部添加
*
* @param value 新值
*/
public void addHead(T value) {
//1. 判满操作 扩容?
ensureCapacity();
//2. 数据移动
// for(int i = size-1;i>=0;i--){
// element[i+1] = element[i];
// }
System.arraycopy(element, 0, element, 1, size);
//3. 0下标位置填充value
element[0] = value;
//4. size++
size++;
}
/**尾部添加
*
* @param value
*/
public void addtail(T value) {
ensureCapacity();
element[size++] = value;
}
/**删除value
*
* @param value
*/
public void removeValue(T value) { // 1 2 2 2 3 value:2
//1. size == 0 判空操作
if (size == 0) {
return;
}
for (int i = 0; i < size; i++) {
if (element[i].compareTo(value) == 0) {
// 数据移动覆盖
for (int j = i + 1; j < size; j++) {
element[j - 1] = element[j];
}
size--;
i--; //如果元素出现移动,i值不增加,
}
}
}
/**删除头部
*
*/
public void removeHead() {
if (size == 0) {
return;
}
// for(int i = 1;i<size;i++){
// element[i-1] = element[i];
// }
System.arraycopy(element, 1, element, 0, size - 1);
size--;
}
/**删除尾部
*
*/
public void removeTail() {
if (size == 0) {
return;
}
size--;
}
/**查找
*
* @param value 需要查找的元素
* @return
*/
public boolean search(T value) {
for (int i = 0; i < size; i++) {
if (element[i].compareTo(value) == 0) {
return true;
}
}
return false;
}
@Override
public int size() {
return size;
}
//打印
public void show() {
System.out.print("动态数组中的元素:");
for (int i = 0; i < size; i++) {
System.out.print(element[i] + " ");
}
System.out.println();
}
}
MyArrayListDemo
import java.util.Scanner;
public class MyArrayListDemo {
public static void main(String[] args) {
MyArrayList<Integer> list = new MyArrayList();
while (true) {
System.out.println("----请选择以下操作(动态数组):-----");
System.out.println("1、头部添加");
System.out.println("2、尾部添加");
System.out.println("3、头部删除");
System.out.println("4、尾部删除");
System.out.println("5、查找值");
System.out.println("6、删除特定值");
System.out.println("7、修改值");
System.out.println("8、查看");
System.out.println("------------------------");
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
switch (i) {
case 1: {
System.out.println("请输入需要添加的元素");
Integer s = scanner.nextInt();
list.addHead(s);
list.show();
continue;
}
case 2: {
System.out.println("请输入需要添加的元素");
Integer s1 = scanner.nextInt();
list.addTail(s1);
list.show();
continue;
}
case 3:
list.removeHead();
list.show();
continue;
case 4:
list.removeTail();
list.show();
continue;
case 5: {
System.out.println("请输入需要查找的元素");
Integer s2 = scanner.nextInt();
boolean search = list.search(s2);
System.out.println(search);
continue;
}
case 6: {
System.out.println("请输入需要删除的元素");
Integer s3 = scanner.nextInt();
list.removeValue(s3);
list.show();
continue;
}
case 7: {
System.out.println("请输入需要修改的下标");
Integer s4 = scanner.nextInt();
System.out.println("请输入需要修改的新元素");
Integer s5 = scanner.nextInt();
list.change(s4, s5);
list.show();
continue;
}
case 8:
list.show();
continue;
default:
System.out.println("输入错误请重新输入!");
continue;
}
}
}
}
LinkedList(单链表)
SingleLinkedList
public class SingleLinkedList<E extends Comparable<E>> implements List<E> {
//单链表
private Node<E> head;//头
private Node<E> tail;//尾
int size;//统计节点个数
/**
* 头部添加
*
* @param value
*/
@Override
public void addHead(E value) {//在头部添加一个节点
Node<E> newNode = new Node<E>(value);//申请节点
if (head == null) {//链表里没有任何元素
head = newNode;
tail = newNode; //将尾部也更新到新节点中
} else {
newNode.next = head;//新的节点的下一个保存原来的头结点
head = newNode;//更新头结点
}
size++;
}
/**
* 尾部添加
*
* @param value
*/
@Override
public void addTail(E value) {//在尾部添加一个节点
Node<E> newNode = new Node<E>(value);
if (size == 0) {//链表里没有任何元素 //if(head == null)
head = newNode;
tail = newNode; //将尾部也更新到新节点中
} else {
tail.next = newNode;//尾巴节点的下一个保存新节点
tail = newNode;//更新尾结点
}
size++;
}
/**
* 删除头部
*/
@Override
public void removeHead() {//删除头结点
if (size == 0) {
return;
}
head.value = null;//释放空间
if (size == 1) {//链表只有一个节点时,头部和尾部都为null
head = null;
tail = null;
} else {
head = head.next;//头部指向头部的下一个
}
size--;
}
/**
* 删除尾部
*/
@Override
public void removeTail() {//删除尾节点
Node<E> p = head;
if (size == 0) {
return;
}
tail.value = null;//释放空间
if (size == 1) {//链表只有一个节点时,头部和尾部都为null
head = null;
tail = null;
} else {
for (; p.next != tail; p = p.next) {
}
p.next = null;//尾巴的next =null
tail = p;//更新尾巴
}
size--;
}
/**
* 删除指定元素
*
* @param value
*/
@Override
public void removeValue(E value) {//删除指定元素(可能有多个节点的value值是该元素)
if (size == 0) {
return;
}
if (tail.value.compareTo(value) == 0) {//如果尾结点等于指定节点,调用删除尾结点方法
removeTail();
removeValue(value);
}
if (head.value.compareTo(value) == 0) {如果头结点等于指定节点,调用删除尾结点方法
removeHead();
removeValue(value);
} else if (size == 1 && head.value.compareTo(value) != 0) {
return;
} else { //size>=2 head.value != value
for (Node<E> p = head; p.next != null; ) {
if (p.next.value.compareTo(value) == 0) {
// if(p.next == tail){
// tail = p;
// }
p.next.value = null;// 防止内存泄漏
p.next = p.next.next;
size--;
} else {
p = p.next;
}
}
}
}
/**
* 修改值
*
* @param srcValue 原数据
* @param aimValue 新数据
*/
@Override
public void change(E srcValue, E aimValue) {//改变节点的value值
for (Node<E> p = head; p != null; p = p.next) {
if (p.value.compareTo(srcValue) == 0) {//遍历链表找到要替换的节点,重新把新的值赋值给value
p.value = aimValue;
}
}
}
public Node<E> getHead() {
return head;
}
public Node<E> getTail() {
return tail;
}
public void setHead(Node<E> head) {
this.head = head;
}
public void setTail(Node<E> tail) {
this.tail = tail;
}
/**
* 搜索节点
*
* @param value
* @return
*/
@Override
public boolean search(E value) {//判断元素是否存在
for (Node<E> p = head; p != null; p = p.next) {
if (p.value.compareTo(value) == 0) {
return true;
}
}
return false;
}
/**
* 返回链表节点的个数
*
* @return
*/
@Override
public int size() {
return size;
}//返回size元素个数
/**
* 遍历单链表
*/
public void show() {//展示链表中所有的元素
System.out.print("单链表中的元素:");
for (Node<E> p = head; p != null; p = p.next) {
System.out.print(p.value + "\t");
}
System.out.println();
}
static class Node<T> {
private T value;
private Node<T> next;
public T getValue() {
return value;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node(T value) {
this.value = value;
}
}
}
SingleLinkedListDemo
import java.util.Scanner;
public class SingleLinkedListDemo {
//单链表
//头插,尾插,头删,尾删
public static <T> void main(String[] args) {
SingleLinkedList<Integer> list = new SingleLinkedList<>();
while (true) {
System.out.println("----请选择以下操作(单链表):-----");
System.out.println("1、头部添加");
System.out.println("2、尾部添加");
System.out.println("3、头部删除");
System.out.println("4、尾部删除");
System.out.println("5、查找值");
System.out.println("6、删除特定值");
System.out.println("7、修改值");
System.out.println("8、查看");
System.out.println("------------------------");
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
switch (i) {
case 1: {
System.out.println("请输入需要添加的元素");
Integer s = scanner.nextInt();
list.addHead(s);
list.show();
continue;
}
case 2: {
System.out.println("请输入需要添加的元素");
Integer s1 = scanner.nextInt();
list.addTail(s1);
list.show();
continue;
}
case 3:
list.removeHead();
list.show();
continue;
case 4:
list.removeTail();
list.show();
continue;
case 5: {
System.out.println("请输入需要查找的元素");
Integer s2 = scanner.nextInt();
boolean search = list.search(s2);
System.out.println(search);
continue;
}
case 6: {
System.out.println("请输入需要删除的元素");
Integer s3 = scanner.nextInt();
list.removeValue(s3);
list.show();
continue;
}
case 7: {
System.out.println("请输入需要修改的旧元素");
Integer s4 = scanner.nextInt();
System.out.println("请输入需要修改的新元素");
Integer s5 = scanner.nextInt();
list.change(s4, s5);
list.show();
continue;
}
case 8:
list.show();
continue;
default:
System.out.println("输入错误请重新输入!");
continue;
}
}
}
}
双向链表的实现
DLink
public class DLink<T extends Comparable<T>> implements List<T> {
private Node<T> head;
private Node<T> tail;
private int size;
/**
* 头部添加
* @param value
*/
@Override
public void addHead(T value) {
Node<T> newNode = new Node<T>(value);
if(head == null){//链表为空
head = newNode;
tail = newNode;
}else{
newNode.next = head;
head.prev = newNode;
head = newNode;
}
size++;
}
/**
* 尾部添加
* @param value
*/
@Override
public void addTail(T value) {
Node<T> newNode = new Node<T>(value);
if(tail == null){
head = newNode;
tail = newNode;
}else{
newNode.prev = tail;
newNode.next = null;
tail.next = newNode;
tail = newNode;
}
size++;
}
/**
* 删除头部
*/
@Override
public void removeHead() {
if(size == 0){
return;
}
head.value = null;//释放空间
if(size == 1){//链表只有一个节点时,头部和尾部都为null
head = null;
tail = null;
}else {
head = head.next;//头部指向头部的下一个
head.prev = null;
}
size--;
}
/**
* 删除尾部
*/
@Override
public void removeTail() {
Node<T> p = head;
if(size == 0){
return;
}
tail.value = null;//释放空间
if(size == 1){//链表只有一个节点时,头部和尾部都为null
head = null;
tail = null;
}else {
tail.prev.next = null;
tail = tail.prev;
}
size--;
}
/**
* 删除特定元素
* @param value
*/
@Override
public void removeValue(T value) {
if(size == 0){
return;
}
if(head.value.compareTo(value) == 0){
removeHead();
removeValue(value);
}else if(size == 1 && head.value.compareTo(value) != 0){
return;
}
else{ //size>=2
for(Node<T> p=head; p!=null;p = p.next){
if(p.value.compareTo(value) == 0){
if(p.next == null){
removeTail();
}else {
p.value = null;// 防止内存泄漏
p.prev.next = p.next;
p.next.prev = p.prev;
size--;
p = p.prev;
}
}
}
}
}
/**
* 修改元素值
* @param srcValue
* @param aimValue
*/
@Override
public void change(T srcValue, T aimValue) {
for(Node<T> p = head;p!= null;p= p.next){
if(p.value.compareTo(srcValue) == 0){
p.value = aimValue;
}
}
}
/**
* 查找元素
* @param value
* @return
*/
@Override
public boolean search(T value) {
for(Node<T> p = head;p != null; p = p.next){
if(p.value.compareTo(value) == 0){
return true;
}
} return false;
}
/**
* 链表的长度
* @return
*/
@Override
public int size() {
return size;
}
/**
* 打印链表
*/
public void show(){
System.out.print("双向链表中的元素:");
for(Node<T> p = head;p!= null;p= p.next){
System.out.print(p.value + "\t");
}
System.out.println();
}
//定义链表中的节点
static class Node<E>{
E value;//元素
Node<E> next;//后一个节点的地址
Node<E> prev;//前一个节点的地址
public Node(E value) {
this.value = value;
}
}
}
DLinkDemo
import java.util.Scanner;
public class DLinkDemo {
public static <T>void main(String[] args) {
DLink<Integer> dlink = new DLink<>();
while (true) {
System.out.println("----请选择以下操作(动态数组):-----");
System.out.println("1、头部添加");
System.out.println("2、尾部添加");
System.out.println("3、头部删除");
System.out.println("4、尾部删除");
System.out.println("5、查找值");
System.out.println("6、删除特定值");
System.out.println("7、修改值");
System.out.println("8、查看");
System.out.println("------------------------");
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
switch (i) {
case 1: {
System.out.println("请输入需要添加的元素");
Integer s = scanner.nextInt();
dlink.addHead(s);
dlink.show();
continue;
}
case 2: {
System.out.println("请输入需要添加的元素");
Integer s1 = scanner.nextInt();
dlink.addTail(s1);
dlink.show();
continue;
}
case 3:
dlink.removeHead();
dlink.show();
continue;
case 4:
dlink.removeTail();
dlink.show();
continue;
case 5: {
System.out.println("请输入需要查找的元素");
Integer s2 = scanner.nextInt();
boolean search = dlink.search(s2);
System.out.println(search);
continue;
}
case 6: {
System.out.println("请输入需要删除的元素");
Integer s3 = scanner.nextInt();
dlink.removeValue(s3);
dlink.show();
continue;
}
case 7: {
System.out.println("请输入需要修改的旧元素");
Integer s4 = scanner.nextInt();
System.out.println("请输入需要修改的新元素");
Integer s5 = scanner.nextInt();
dlink.change(s4, s5);
dlink.show();
continue;
}
case 8:
dlink.show();
continue;
default:
System.out.println("输入错误请重新输入!");
continue;
}
}
}
}