顺序表--List
底层是由可变数组实现,在构造中初始化一个数组并指定数组的长度,实现相应的Api。
public class DemoList<T> {
//定义数组的长度
private T[] size;
//元素的个数
private int N;
public DemoList(Integer size) {
this.size = (T[]) new Object[size];
this.N = 0;
}
public boolean add(T t) {
//添加数据是判断容量是否已满,满了就扩容
if (N == size.length) {
resize(size.length * 2);
}
this.size[N++] = t;
return true;
}
public T get(int i) {
return size[i];
}
//在索引i处添加值
public boolean add(int i, T t) {
//添加数据是判断容量是否已满,满了就扩容
if (N == size.length) {
resize(size.length * 2);
}
//遍历比索引i大的值
for (int index = N - 1; index > i; index--) {
//把前面索引的值移动到后面
size[index] = size[index - 1];
}
size[i] = t;
return true;
}
public boolean isEmpty() {
return N == 0;
}
public int indexOf(T t) {
for (int i = 0; i < N; i++) {
if (t.equals(size[i])) {
return i;
}
}
return -1;
}
//删除索引i处的值
public T remove(int i) {
T current = size[i];
for (int index = i; index < N - 1; index++) {
size[index - 1] = size[index];
}
return current;
}
//对数组进行扩容
private void resize(int newSize) {
//定义一个临时变量
T[] temp = size;
size = (T[]) new Object[newSize];
//将原来的数据拷贝到新的数组
for (int i = 0; i < N; i++) {
size[i] = temp[i];
}
}
public static void main(String[] args) {
DemoList<String> demoList = new DemoList(3);
demoList.add("luyu");
demoList.add("lisi");
demoList.add("zhangsan");
System.out.println(demoList.get(1));
}
}
链表--单向链表
单向链表的存储结构为我们提供一个Node节点,为我们指向下一个元素,每一个节点为两个域,分别存储具体的数据,以及下一个节点所指向的元素。其中在该链表中会初始化一个head节点,用于引用下一个(next)节点,但并不存储数据。
/**
* 单向链表
*
* @param <T>
*/
public class LinkListTest<T> implements Iterable<T> {
//头结点
private Node head;
//链表的长度
private Integer N;
public class Node {
//数据
T date;
//下一个节点
Node next;
//节点的构造
public Node(T date, Node next) {
this.date = date;
this.next = next;
}
}
//链表的构造
public LinkListTest() {
this.head = new Node(null, null);
N = 0;
}
public int indexOf(T t) {
//判断元素t在链表中第一次出现的位置
Node n = head;
for (int i = 0; n.next != null; i++) {
if (n.date.equals(t)) {
return i;
}
}
return -1;
}
public int size() {
return N;
}
//添加节点
public void addNode(T t) {
//初始化头结点
Node n = head;
//找到尾结点
while (n.next != null) {
n = n.next;
}
//创建新的节点
Node newNode = new Node(t, null);
//把找到的尾结点指向新创建的节点
n.next = newNode;
//让链表长度自增
N++;
}
public void addNode(int i, T t) {
//初始化上一个结点
Node pre = head;
//找到i节点的前一个节点
for (int index = 0; index < i - 1; i++) {
//得到上一个节点
pre = pre.next;
}
//获取i的节点
Node curr = pre.next;
//创建新的节点
Node newNode = new Node(t, curr);
//让上一个节点指向新的节点
pre.next = newNode;
}
public T remove(int i) {
//初始化上一节点
Node pre = head;
//找到要删除节点的前一个节点
for (int index = 0; index < i - 1; i++) {
pre = pre.next;
}
//获取要删除的节点(当前节点)
Node curr = pre.next;
//获取要删除节点的下一个节点
Node nextNode = curr.next;
//让前一个节点指向下一个节点
pre.next = nextNode.next;
N--;
return curr.date;
}
//获得指定元素位置的数据
public T get(int i) {
Node n = head;
//从头结点依次遍历
for (int index = 0; index < i; index++) {
n = n.next;
}
return n.date;
}
@Override
public Iterator<T> iterator() {
return new LIterator();
}
private class LIterator implements Iterator {
private Node n;
public LIterator() {
this.n = head;
}
//判断是否还有下一个值
@Override
public boolean hasNext() {
return n.next != null;
}
//获取下一个节点的值
@Override
public Object next() {
n = n.next;
return n.date;
}
}
public static void main(String[] args) {
//创建顺序表对象
LinkListTest<String> sl = new LinkListTest<>();
//测试插入
sl.addNode("张三");
sl.addNode("王五");
sl.addNode("赵六");
sl.addNode("李四");
sl.addNode("卢宇");
System.out.println(sl.remove(1));
System.out.println(sl.size());
for (int i = 0; i < sl.size(); i++) {
System.out.println(sl.get(i));
}
System.out.println("----");
System.out.println(sl.get(4));
System.out.println("----");
Iterator<String> iterator = sl.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("----");
for (String s : sl) {
System.out.println(s);
}
}
}
链表--双向链表
双向链表的存储结构为我们提供一个Node节点,其每个节点存储三个域对象,分别为具体的数据,以及上一个节点(pre)所指向的元素和下一个节点(next)所指向的元素。其中在该链表中会初始化一个head节点,用于引用下一个(next)节点,但并不存储数据。
package com.macro.mall.malladmin.DataStructuresAndAlgorithms;
/**
* 双向链表实现
*/
public class TowWayLinkList<T> {
//头结点
private Node head;
//链表的最后一个节点
private Node last;
//链表的长度
private int N;
private class Node {
//存储的数据
private T data;
//指向的上一个节点
private Node pre;
//指向的下一个节点
private Node next;
public Node(T data, Node pre, Node next) {
this.data = data;
this.pre = pre;
this.next = next;
}
}
//双向链表的构造
public TowWayLinkList() {
//初始化有节点和尾结点
this.head = new Node(null, null, null);
this.last = null;
this.N = 0;
}
//判断链表是否为空
public boolean isEmpty() {
return N == 0;
}
//获得第一个元素
public T firstData() {
if (isEmpty()) {
return null;
}
return head.next.data;
}
//添加元素
public void insert(T date) {
//如果链表为空链表
if (isEmpty()) {
//创建一个新的节点
Node newNode = new Node(date, head, null);
//让新节点称为尾结点
last = newNode;
//让头结点指向尾结点
head.next = last;
} else {
//旧的尾结点
Node oldNode = last;
//如果添加节点是链表不为空
Node newLast = new Node(date, oldNode, null);
//让旧的尾节点指向新的节点
oldNode.next = newLast;
//让新的节点变为尾结点
last = newLast;
}
N++;
}
public T get(int i) {
//初始化头结点
Node n = head.next;
//从头结点开始循环
for (int index = 0; index < i; index++) {
//从新赋值
n = n.next;
}
return n.data;
}
//找到元素t在链表中第一次出现的位置
public int indexOf(T t) {
//初始化头结点
Node n = head;
for (int index = 0; n.next != null; index++) {
if (t.equals(n.next.data)) {
return index;
}
}
return -1;
}
public T remove(int i) {
//初始化上一个节点
Node pre = head;
//查询出上一个节点的位置
for (int index = 0; index < i - 1; index++) {
pre = pre.next;
}
//查询当前i位置节点
Node curr = pre.next;
//查询i位置的下一个节点
Node nextNode = curr.next;
//让i位置的下一个结点的上一个结点变为i位置的前一个结点
nextNode.pre = pre;
//数量递减
N--;
return curr.data;
}
public static void main(String[] args) {
TowWayLinkList<String> list = new TowWayLinkList();
list.insert("卢宇");
list.insert("李四");
list.insert("李四");
list.insert("李四");
System.out.println(list.get(2));
System.out.println(list.firstData());
System.out.println("------");
System.out.println(list.remove(3));
// System.out.println(list.remove(3));
}
}