数据结构
数据结构–操作
数组 Array
数组
数组允许元素的随机访问、数组更好缓存位置 ,特点如下:数组的大小是固定的,必须提前知道需要存储的元素个数,一般情况下,分配的内存等于上限,与使用情况无关;在数组中插入新元素是昂贵的,必须为新元素创建空间,创先现有空间元素必须进行位移
动态数组
动态数组大小可以重新设定,造成了空间浪费
python中的数组都是动态的
java array list
交错数组
数组操作
在数组最后添加元素
在数组特定位置添加元素
移除数组中的元素
JAVA代码如下
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Array {
public static void main(String args[]){
//Simple fixed-sized arrays java
String[] fixedArray = new String[3];
fixedArray[0] = "this";
fixedArray[1] = "is";
fixedArray[2] = "battle!";
for(int i=0;i<3;i++){
System.out.print(fixedArray[i]+" ");
}
//Resizable arrays, util module
List<String> resizable = new ArrayList<String>();
resizable.add("This");
resizable.add(1, "6");
resizable.add(0, "That");
System.out.print(resizable);
}
}
单链表 - Singly Linked List
单链表是一种线性的数据结构,不是存在连续的存储位置,如下图所示:
特性:动态大小,易于插入/删除
不允许随机访问,必须从第一个结点顺序访问元素,因此无法进行二进制搜索;
列表中的每一个指针元素都需要额外的内存空间
结构:数据、指向下一个结点的指针
注:在 Java 或 c # 中,LinkedList 可以表示为类,而 Node 可以表示为单独的类。 Linkedlist 类包含一个 Node 类类型的引用
// 创建一个包含三个节点的单链表
class LinkedList{
Node head; //head of the list
//使用静态类便于main()可以访问
static class Node{
int data;
Node next;
Node(int d)
{
data = d;
next=null; } //构造
//创建三节点链表的method
public static void main(String[] args){
LinkedList llist = new LinkedList();
llist.head = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
//连接第一个结点和第二个结点
llist.head.next = second;
second.next = third;
llist.printList();
}
}
private void printList() {
Node n = head;
while (n != null){
System.out.print(n.data + " ");
n = n.next;
}
}
}
循环链表 Circular Linked List
双链表 Double Linked List
栈
stack
栈:Last In, First Out (LIFO),后进先出。如:摆放的盘子
操作的时间复杂度都为O(1),可通过数组(array)和链表(list)实现
push:在堆栈中添加一个项目。如果堆栈已满,则称其为溢出条件。
pop:从堆栈中删除一个项目。这些项目以推入的相反顺序弹出。如果堆栈为空,则称为下溢条件。
Peek/Top:返回堆栈的顶部元素。
isEmpty:如果堆栈为空,则返回true,否则返回false
// 数组实现栈
class StackByArray {
static final int Max = 1000;
int top;
int s[] = new int[Max];
boolean isEmpty(){
return (top<0);
}
StackByArray(){
top = -1;
}
boolean push(int x){
if(top>=(Max-1)){
System.out.println("栈溢出");
return false;
}
else {
top = top +1;
s[top] = x;
System.out.println(x + " 加入栈");
return true;
}
}
int pop(){
if (top<0){
System.out.println("空栈,下溢出");
return 0;
}
else {
int x = s[top--];
return x;
}
}
int peek(){
if (top<0){
System.out.println("栈溢出");
return 0;
}
else {
int x = s[top];
return x;
}
}
}
// 运行代码
class Main {
public static void main(String args[])
{
StackByArray s = new StackByArray();
s.push(10);
s.push(20);
s.push(30);
System.out.println(s.pop() + " 从栈移除");
}
}
Queue
队列
First In, First Out(FIFO),顾客排队:先排好的顾客可以先买单了,后来的顾客在末尾排队等待
Enqueue:将项目添加到队列。如果队列已满,则称其为溢出条件。
Dequeue:从队列中删除项目。这些项目将以其推入的相同顺序弹出。如果队列为空,则称其为下溢条件。
Front:从队列中获取前一项。
Rear:从队列中获取最后一个项目。
class QueueArray {
int front, rear, size;
int capacity; int array[];
public QueueArray(int capacity){
this.capacity = capacity;
front = this.size = 0;
rear = capacity-1;
array = new int[this.capacity];
}
boolean isFull(QueueArray queueArray){
return (queueArray.size == queueArray.capacity);
}
boolean isEmpty(QueueArray queueArray){
return (queueArray.size == 0);
}
void enqueue(int item){
if(isFull(this)){
return;
}
this.rear = (this.rear+1)%this.capacity;
this.array[this.rear] = item;
this.size = this.size+1;
System.out.println(item + " 加入到队列");
}
int dequeue(){
if(isEmpty(this)){
return Integer.MIN_VALUE;
}
return this.array[this.front];
}
int front()
{
if (isEmpty(this))
return Integer.MIN_VALUE;
return this.array[this.front];
}
int rear(){
if(isEmpty(this)){
return Integer.MIN_VALUE;
}
return this.array[this.rear];
}
}
优先队列 Priority Queue
优先队列是具有以下属性的队列的扩展。
每个项目都有与之关联的优先级。
高优先级的元素在低优先级的元素之前出队。
如果两个元素具有相同的优先级,则将根据其在队列中的顺序为其提供服务。
在以下优先级队列中,具有最大ASCII值的元素将具有最高优先级。
双端队列 Deque
循环队列 Circular Queue
哈希表 Hash Table
哈希是一种重要的数据结构,使用哈希函数去创建一种得到元素的键方法
哈希表
哈希冲突:单独连接、开放地址
单独链接 Separate Chaining 用链表链接解决冲突
开放地址Open Addressing 三种方式
Linear Probing: 冲突后+1
(hash(x) + 2) % S is also full, then we try (hash(x) + 3) % S
Quadratic Probing: 冲突后+ x**2
(hash(x) + 22) % S is also full, then we try (hash(x) + 33) % S
Double Hashing: 用第二个哈希表来处理
(hash(x) + 2hash2(x)) % S is also full, then we try (hash(x) + 3hash2(x)) % S
Load Factor and Rehashing
集合
set
Set 继承于Collection接口,是一个不允许出现重复元素,并且无序的集合,主要有HashSet和TreeSet两大实现类。
表 List
用户可以精确控制列表中每个元素的插入位置,另外用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。 与 Set 不同,List 通常允许重复的元素。 另外 List 是有序集合而 Set 是无序集合
线程安全与非线程安全:多个线程操作同一个对象是否出问题 进程与线程:线程是程序运行的最小单位
ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。
LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率高。
Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。
Stack 是栈,它继承于Vector。它的特性是:先进后出(FILO, First In Last Out)。
图 MAP
树 Tree
二叉树
二叉树:每个节点最多有两个子树的树结构
完全二叉树:除最后一层不满或者右边缺少连续若干结点,n个结点的深度为llog2 n +1
满二叉树:深度为k,有2^k-1个节点
平衡二叉树:空树或它的左右两个子树的高度差绝对值不超过1
二叉查找树 BST
左侧子树小于结点,右侧子树大于结点,有序二叉树
红黑树
二叉查找树变成线性结构的情况,漫画介绍红黑树
B树
堆 heap
定义 每一个元素都要保证大于另外两个特定位置的元素,分最大堆和最小堆