一、数据结构的基本概念:
1.数据(Data)
数据是描述客观十四五的数值、字符以及能输入机器且能被处理的各种符号集合。
2.数据元素(Data Element)
数据元素是组成数据的基本单位,是数据集合的个体。
3.数据对象(Data Object)
数据对象谁性质相同的元素的集合,是数据的一个子集。
4.数据结构(Data Structure)
数据结构是指相互之间存在一种或多种特定关系的数据元素集合。
5.数据类型(Data Type)
数据类型是一组性质相同的集合以及定义这个值集合的一组数据操作的总称。
6.算法:性能评价
1.时间复杂度:使用大“O”表示法:比如:
T(n) = O(1)表示常数型;
O(n)表示线性型;
O(n^2)表示平方型;
O(2^n)表示指数型;
O(log n)对数型;
O(n log n)二维型;
2.空间复杂度:一个算法的占用空间是指算法实际占用的辅助空间总和。
时间和空间要想两者兼顾是很难的,有时候需要根据实际的需求以及条件来舍其一,来换取另一个。
二、接下来正式进入数据结构:
1、线性表:n个类型相同数据元素的有限集合。
(1) 特点: (1)同一性, (2)有穷性,(3)有序性
(2)线性表在 java 中的实现:
List表示线性表:有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。:
方法摘要 | ||
---|---|---|
boolean | add(E e) 向列表的尾部添加指定的元素(可选操作)。 | |
void | add(int index, E element) 在列表的指定位置插入指定元素(可选操作)。 | |
boolean | addAll(Collection<? extends E> c) 添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。 | |
boolean | addAll(int index, Collection<? extends E> c) 将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。 | |
void | clear() 从列表中移除所有元素(可选操作)。 | |
boolean | contains(Object o) 如果列表包含指定的元素,则返回 true。 | |
boolean | containsAll(Collection<?> c) 如果列表包含指定 collection 的所有元素,则返回 true。 | |
boolean | equals(Object o) 比较指定的对象与列表是否相等。 | |
E | get(int index) 返回列表中指定位置的元素。 | |
int | hashCode() 返回列表的哈希码值。 | |
int | indexOf(Object o) 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。 | |
boolean | isEmpty() 如果列表不包含元素,则返回 true。 | |
Iterator<E> | iterator() 返回按适当顺序在列表的元素上进行迭代的迭代器。 | |
int | lastIndexOf(Object o) 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。 | |
ListIterator<E> | listIterator() 返回此列表元素的列表迭代器(按适当顺序)。 | |
ListIterator<E> | listIterator(int index) 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。 | |
E | remove(int index) 移除列表中指定位置的元素(可选操作)。 | |
boolean | remove(Object o) 从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。 | |
boolean | removeAll(Collection<?> c) 从列表中移除指定 collection 中包含的其所有元素(可选操作)。 | |
boolean | retainAll(Collection<?> c) 仅在列表中保留指定 collection 中所包含的元素(可选操作)。 | |
E | set(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。 | |
int | size() 返回列表中的元素数。 | |
List<E> | subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。 | |
Object[] | toArray() 返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。 | |
| toArray(T[] a) 返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。 |
ArrayList :顺序表,线性表的顺序存储。底层使用数组实现。功能上也类似于数组。
(1).继承关系:
java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.ArrayList<E>
(2).类的声明:
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
(3).实例化对象:
//<Integer> 表示该 ArrayList 的元素类型是 Integer 型
//(java中的包装类型,上一篇文章中有所有基本类型的包装类)
List<Integer> arrayList = new ArrayList<>();
构造方法摘要 | |
---|---|
ArrayList() 构造一个初始容量为 10 的空列表。 | |
ArrayList(Collection<? extends E> c) 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。 | |
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表。 |
可以看到 ArrayList 实现了 List<E>接口。所以 List接口的所有方法ArrayList也同样可以使用。绝大多数情况下使用ArrayList就足够了,因为相比较LinkedList而言,ArrayList省时省力。除非是特定情况下使用 LinkedList。
LinkedList :链表,线性表的链式存储。
(1).继承关系:
java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.AbstractSequentialList<E> java.util.LinkedList<E>
(2).类的声明:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
(3).实例化对象:LinkedList对象可以完成链表的所有操作。
//linkedList 对象可以可以完成链表的所有操作。
List<Integer> linkedList = new LinkedList<>();
构造方法摘要 | |
---|---|
LinkedList() 构造一个空列表。 | |
LinkedList(Collection<? extends E> c) 构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。 |
LinkedList不仅实现了 List 接口还有Deque<E>双端队列接口。可以进行一系列关于队列的操作。
2、Queue队列接口:
什么是队列?队列是一种限定性线性表,他只允许在表的一端插入元素,另一端删除元素,所以队列有先进先出(First In First Out,FIFO)的特性。与我们日常生活中的排队是一样的道理。而双端队列则是允许在两端进行元素的插入和移除。
Queue方法摘要 | |
---|---|
boolean | add(E e) 将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。 |
E | element() 获取,但是不移除此队列的头。 |
boolean | offer(E e) 将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于 add(E) ,后者可能无法插入元素,而只是抛出一个异常。 |
E | peek() 获取但不移除此队列的头;如果此队列为空,则返回 null。 |
E | poll() 获取并移除此队列的头,如果此队列为空,则返回 null。 |
E | remove() 获取并移除此队列的头。 |
Deque方法摘要 | |
---|---|
boolean | add(E e) 将指定元素插入此双端队列所表示的队列(换句话说,此双端队列的尾部),如果可以直接这样做而不违反容量限制的话;如果成功,则返回 true,如果当前没有可用空间,则抛出 IllegalStateException。 |
void | addFirst(E e) 将指定元素插入此双端队列的开头(如果可以直接这样做而不违反容量限制)。 |
void | addLast(E e) 将指定元素插入此双端队列的末尾(如果可以直接这样做而不违反容量限制)。 |
boolean | contains(Object o) 如果此双端队列包含指定元素,则返回 true。 |
Iterator<E> | descendingIterator() 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。 |
E | element() 获取,但不移除此双端队列所表示的队列的头部(换句话说,此双端队列的第一个元素)。 |
E | getFirst() 获取,但不移除此双端队列的第一个元素。 |
E | getLast() 获取,但不移除此双端队列的最后一个元素。 |
Iterator<E> | iterator() 返回以恰当顺序在此双端队列的元素上进行迭代的迭代器。 |
boolean | offer(E e) 将指定元素插入此双端队列所表示的队列(换句话说,此双端队列的尾部),如果可以直接这样做而不违反容量限制的话;如果成功,则返回 true,如果当前没有可用的空间,则返回 false。 |
boolean | offerFirst(E e) 在不违反容量限制的情况下,将指定的元素插入此双端队列的开头。 |
boolean | offerLast(E e) 在不违反容量限制的情况下,将指定的元素插入此双端队列的末尾。 |
E | peek() 获取,但不移除此双端队列所表示的队列的头部(换句话说,此双端队列的第一个元素);如果此双端队列为空,则返回 null。 |
E | peekFirst() 获取,但不移除此双端队列的第一个元素;如果此双端队列为空,则返回 null。 |
E | peekLast() 获取,但不移除此双端队列的最后一个元素;如果此双端队列为空,则返回 null。 |
E | poll() 获取并移除此双端队列所表示的队列的头部(换句话说,此双端队列的第一个元素);如果此双端队列为空,则返回 null。 |
E | pollFirst() 获取并移除此双端队列的第一个元素;如果此双端队列为空,则返回 null。 |
E | pollLast() 获取并移除此双端队列的最后一个元素;如果此双端队列为空,则返回 null。 |
E | pop() 从此双端队列所表示的堆栈中弹出一个元素。 |
void | push(E e) 将一个元素推入此双端队列所表示的堆栈(换句话说,此双端队列的头部),如果可以直接这样做而不违反容量限制的话;如果成功,则返回 true,如果当前没有可用空间,则抛出 IllegalStateException。 |
E | remove() 获取并移除此双端队列所表示的队列的头部(换句话说,此双端队列的第一个元素)。 |
boolean | remove(Object o) 从此双端队列中移除第一次出现的指定元素。 |
E | removeFirst() 获取并移除此双端队列第一个元素。 |
boolean | removeFirstOccurrence(Object o) 从此双端队列移除第一次出现的指定元素。 |
E | removeLast() 获取并移除此双端队列的最后一个元素。 |
boolean | removeLastOccurrence(Object o) 从此双端队列移除最后一次出现的指定元素。 |
int | size() 返回此双端队列的元素数。 |
上面提到 LinkedList 实现了Deque接口,那么通过一下代码实例化的Deque对象就可以完成Deque接口的所有操作:
//queue对象是一个简单的队列,具体有如下操作:add(E e), element(), offer(E e), peek(), poll(), remove()
Queue<Integer> queue = new LinkedList<>();
//deque对象时一个双端队列,对应可以完成双端队列的操作。
Deque<Integer> deque = new LinkedList<>();
Queue 和 Deque的一些方法是等效的:
Queue 方法 | 等效 Deque 方法 |
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() |
3、Queue是线性结构的一种具体应用,线性结构还有另一种具体的应用,那就是栈(Stack)
栈作为一种限定性线性表,是将线性比表的插入和删除操作限制为仅在表的一段进行,通常将表中允许操作的一段成为栈顶(Top),另一端称为栈底(Bottom)
方法摘要 | |
---|---|
boolean | empty() 测试堆栈是否为空。 |
E | peek() 查看堆栈顶部的对象,但不从堆栈中移除它。 |
E | pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。 |
E | push(E item) 把项压入堆栈顶部。 |
int | search(Object o) 返回对象在堆栈中的位置,以 1 为基数。 |
(1).继承关系:
java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.Vector<E> java.util.Stack<E>
(2).类的声明:
public class Stack<E>
extends Vector<E>
Stack
类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。
(3).实例化对象:
Stack<Integer> stack = new Stack<>();
总结:以上是对java数据结构的一个入门介绍,对于 ArrayList 和 LinkedList 一定要学会使用它的各种操作,以及能够完成自己的 List。对于Queue 和 Stack 首先要理解其含义,并且能够使用线性表来实现自己的队列和栈。对于java给定的队列和栈也要学会使用它的各项操作。