数据结构List浅谈(java描述)
List(线性表):
List线性表是一种最基本、最简单、同时也是最常用的一种数据结构,一个线性表是具有n个相同类型数据元素的有限序列,其中数据元素之间的关系都是一一对应的。
其特征有:
- 集合中必存在唯一的一个“第一元素”
- 集合中必存在唯一的一个“最后元素”
- 除最后一个元素之外,均有唯一的后继
- 除第一个元素之外,均有唯一的前驱
此处所指的 “线性” 只是逻辑上的线性,所以双向链表、循环链表也属于线性表
在逻辑上细分,线性表可分为一般线性表和受限线性表,一般线性表就是诸如顺序表、链表可以自由的增删结点,受限线性表则包括栈,队列结点操作收到限制
Java中 List接口 实现的方法
List接口实现自Collection接口,该界面用户可精准的控制列表中每个元素的插入位置,用户可通过整数索引访问元素,并搜索列表中的元素。
与集合不同,列表通常允许重复(e1.equals(e2)== true)的元素。
List接口的使用示例:
List 实现杨辉三角
public List<List<Integer>> generate(int numRows) {
List<Integer> row = new ArrayList<>();
List<List<Integer>> col = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
row = new ArrayList<>();
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
row.add(1);
} else {
List<Integer> temp = col.get(i - 1);
row.add(temp.get(j - 1) + temp.get(j));
}
}
col.add(row);
}
return col;
}
ArrayList顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,
将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构是顺序结构
顺序表的本质是一个数组
Java中 ArrayList接口 实现自List接口,可调整大小的数组的实现List接口,实现所有可选列表操作,并允许所有元素,包括null 。 除了实现List 接口之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。
每个ArrayList实例都有一个容量 。容量是用于存储列表中的元素的数组的大小,它总是至少与列表大小一样大,当元素添加到ArrayList中容量已满时,其容量会自动增长。
ArrayList的实现 ——
- 仿写Iterable 接口
package List;
//仿写真实的(java.util.Iterable)接口
public interface Iterable {
Iterator iterator();
}
- 仿写List 接口
public interface List<E> extends Iterable{
boolean add(E e);
void addIndex(int index,E e);
void clean();
boolean contains(Object o);
boolean equals(Object e);
E get(int index);
int indexOf(Object o);
boolean isEmpty();
E remove(int index);
boolean remove(Object o);
E set(int index, E e);
int size();
}
- 仿写Iterator 接口
package List;
//仿写真实的(java.util.Iterator)接口
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
- 实现一个ArrayList的迭代器
package List;
public class ArrayListIterator implements Iterator {
//对一个顺序表迭代,重要在于控制下标
private MyArrayList arrayList;
private int index;
public ArrayListIterator(MyArrayList arrayList) {
this.arrayList = arrayList;
this.index = 0;
}
public ArrayListIterator() {
}
@Override
public boolean hasNext() {
return index < arrayList.size();
}
@Override
public Object next() {
return arrayList.get(index++);
}
@Override
public void remove() {
arrayList.clean();
}
}
- 具体实现ArrayList
package List;
import java.util.Arrays;
//仿写真实的(java.util.ArrayList)实现类
public class MyArrayList<E> implements List{
private int[] arr;
private int size;
public MyArrayList() {
this.arr = new int[10];
this.size = 0;
}
@Override
public boolean add(Object o) {
if (!(o instanceof Integer)) {
return false;
}
if (size == arr.length) {
capacity();
}
arr[size] = (int)o;
size++;
return true;
}
@Override
public void addIndex(int index, Object o) {
if(index < 0 || index > size+1){
return;
}
if (size == arr.length) {
capacity();
}
for (int i = size; i >= index; i--) {
arr[i + 1] = arr[i];
if (i == index) {
arr[index] = (int)o;
size++;
}
}
}
private void capacity() {
int[] newArr = new int[2 * arr.length];
System.arraycopy(arr, 0, newArr, 0, arr.length);
arr = newArr;
}
@Override
public void clean() {
size = 0;
}
@Override
public boolean contains(Object o) {
for (int e : arr){
if(e == (int)o){
return true;
}
}
return false;
}
@Override
public Object get(int index) {
if(index < 0 && index > size-1){
return null;
}else{
return arr[index];
}
}
@Override
public int indexOf(Object o) {
for (int i = 0 ;i < size;i++) {
if(arr[i] == (int)o){
return i;
}
}
return -1;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public Object remove(int index) {
if(index < 0 || index > size+1){
return null;
}
int num = arr[index];
if (size - 1 - index >= 0) System.arraycopy(arr, index + 1, arr, index, size - 1 - index);
arr[size-1] = 0;
size--;
return num;
}
@Override
public boolean remove(Object o) {
int i;
boolean isFind = false;
for (i = 0; i < size; i++) {
if(arr[i] == (int)o){
isFind = true;
break;
}
}
if(isFind) {
if (size - 1 - i >= 0) System.arraycopy(arr, i + 1, arr, i, size - 1 - i);
arr[size - 1] = 0;
size--;
}
return isFind;
}
@Override
public Object set(int index, Object o) {
if(index < 0 || index > size+1){
return null;
}
arr[index] = (int)o;
return arr[index];
}
@Override
public int size() {
return size;
}
public Iterator iterator() {
return new ArrayListIterator(this);
}
@Override
public String toString() {
return "MyArrayList{" +
"arr=" + Arrays.toString(arr) +
'}';
}
}
LinkedList(链表)
链表是一种物理存储单元上非连续、非顺序,逻辑上顺序存储的存储结构。使用链表结构可以克服顺序表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。链表有很多种不同的类型:单向链表,双向链表以及循环链表,Java中链表以引用的形式存储
Java中的LinkedList 接口实现自List 接口, Deque 接口, Cloneable接口, Serializable接口,双链表实现了List和Deque接口。
实现所有可选列表操作,并允许所有元素(包括null )。所有的操作都能像双向列表一样预期。 索引到列表中的操作将从开始或结束遍历列表,以更接近指定的索引为准。
简单实现链表(单向链表)——
- 仿写 Iterable接口
package MyLinkedList;
public interface Iterable {
Iterator iterator();
}
- 仿写 Iterator接口
package MyLinkedList;
public interface Iterator {
boolean hasNext();
Integer next();
}
- 仿写 List接口
package MyLinkedList;
public interface List extends Iterable {
void add(Integer e);
//将指定的元素追加到此列表的末尾
boolean add(int index, Integer element);
//在此列表中的指定位置插入指定的元素
void addFirst(Integer e);
//在该列表开头插入指定的元素
void addLast(Integer e);
//将指定的元素追加到此列表的末尾
void clear();
//从列表中删除所有元素
boolean contains(Object o);
//如果此列表包含指定的元素,则返回 true
Integer getFirst();
//返回此列表中的第一个元素
Integer getLast();
//返回此列表中的最后一个元素
int indexOf(Object o);
//返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1
int lastIndexOf(Object o);
//返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1
Integer remove();
//检索并删除此列表的头(第一个元素)
Integer remove(int index);
//删除该列表中指定位置的元素
boolean remove(Object o);
//从列表中删除指定元素的第一个出现(如果存在)
Integer removeFirst();
//从此列表中删除并返回第一个元素
Integer set(int index, Integer element);
//用指定的元素替换此列表中指定位置的元素
int size();
//返回此列表中的元素数
Integer removeLast();
//从此列表中删除并返回最后一个元素
}
- 定义LinkedListIterator类,实现Iterator 接口的方法
package MyLinkedList;
public class LinkedListIterator implements Iterator {
private SinglyLinkedList list;
private Node cur;
public LinkedListIterator(SinglyLinkedList list) {
this.list = list;
this.cur = list.head;
}
@Override
public boolean hasNext() {
return cur != null;
}
@Override
public Integer next() {
if(cur != null) {
cur = cur.next;
return cur.element;
}else{
return null;
}
}
}
- 定义Node类,存放结点数据
package MyLinkedList;
public class Node {
Integer element;
Node next;
public Node(Integer val) {
this.element = val;
}
@Override
public String toString() {
return " " + element + " ";
}
}
- 定义SinglyLinkedList类,实现 list 接口的方法
package MyLinkedList;
public class SinglyLinkedList implements List{
protected Node head;
private int size;
@Override
public void add(Integer e) {
Node node = new Node(e);
if(head == null){
head = node;
}else{
Node cur = head;
while (cur.next != null){
cur = cur.next;
}
cur.next = node;
}
size++;
}
@Override
public boolean add(int index, Integer element) {
if(index < 0 || index > size){
return false;
}
if(index == 0){
addFirst(element);
return true;
}
int count = 0;
Node node = new Node(element);
Node cur = head;
while (count < index-1){
cur = cur.next;
count++;
}
Node t = cur.next;
cur.next = node;
node.next = t;
size++;
return true;
}
@Override
public void addFirst(Integer e) {
Node node = new Node(e);
node.next = head;
head = node;
size++;
}
@Override
public void addLast(Integer e) {
add(e);
}
@Override
public void clear() {
size = 0;
head = null;
}
@Override
public boolean contains(Object o) {
Node cur = head;
while (cur != null){
if(o.equals(cur.element)){
return true;
}
cur = cur.next;
}
return false;
}
@Override
public Integer getFirst() {
if(head == null) {
return null;
}else{
return head.element;
}
}
@Override
public Integer getLast() {
if(head == null){
return null;
}else{
Node cur = head;
while (cur.next != null){
cur = cur.next;
}
return cur.element;
}
}
@Override
public int indexOf(Object o) {
Node cur = head;
int count = 0;
while (cur != null) {
if(o.equals(cur.element)){
return count;
}
cur = cur.next;
count++;
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
int out = -1;
int count = 0;
Node cur = head;
while (cur != null){
if(o.equals(cur.element)){
out = count;
}
cur = cur.next;
count++;
}
return out;
}
@Override
public Integer remove() {
if(head == null){
return null;
}
int out = head.element;
head = head.next;
size--;
return out;
}
@Override
public Integer remove(int index) {
if(index < 0 || index > size-1){
return null;
}
if(index == 0){
return remove();
}
Node cur = head;
Node pre = null;
int count = 0;
while(count < index){
pre = cur;
cur = cur.next;
count++;
}
int out = cur.next.element;
pre.next = cur.next;
size--;
return out;
}
@Override
public boolean remove(Object o) {
Node cur = head;
Node pre = null;
int count = 0;
while(cur != null){
if(o.equals(cur.element)){
if(pre == null){
remove();
}else {
pre.next = cur.next;
}
return true;
}
pre = cur;
cur = cur.next;
}
return false;
}
@Override
public Integer removeFirst() {
return remove();
}
@Override
public Integer set(int index, Integer element) {
int count = 0;
Node cur = head;
while (cur != null){
if(count == index){
int out = cur.element;
cur.element = element;
return out;
}
count++;
cur = cur.next;
}
return null;
}
@Override
public int size() {
return size;
}
@Override
public Integer removeLast() {
Node pre = null;
Node cur = head;
while (cur.next != null){
pre = cur;
cur = cur.next;
}if(pre == null){
return null;
}
pre.next = null;
return cur.element;
}
@Override
public Iterator iterator() {
return new LinkedListIterator(this);
}
public void print(){
Node cur = head;
System.out.print("[");
while (cur != null){
System.out.print(cur);
cur = cur.next;
}
System.out.println("]");
}
}
以上即是本博客对 list 的总结,随着后续学习的深入还会同步的对内容进行补充和修改,如能帮助到各位博友将不胜荣幸,敬请斧正