数据结构与算法
程序=数据结构+算法
数据结构是一门研究非数值计算的程序设计中计算机的操作对象以及它们之间的关系和操作的学科。
评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间。
尽管数据情况不同,时间复杂度不一定相同,但时间复杂度取的是数据最差时的情况
选择排序:
public class SelectionSort{
public static void selectionSort(int[] arr){
//特殊情况:空数列,数列长度为1
if (arr == null || arr.length < 2){
return;
}
//0(i) ~ N - 1, 找到最小值,在哪,放到0位置
//1(i) ~ N - 1, 找到最小值,在哪,放到1位置
//2(i) ~ N - 1, 找到最小值,在哪,放到2位置
for (int i = 0; i<arr.length - 1; i++){
int minIndex = i;
for(int j = i + 1; j < arr.length; j++){
//i ~ N - 1 上找最小值的下标minIndex
minIndex = arr[j] < arr[minIndex] ? j : mindex;
}
swap(arr, i, miniIndex);
}
public static void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
冒泡排序:
public class BubbleSort{
public static void bubbleSort(int[] arr){
if (arr == null || arr.length < 2){
return;
}
for (int e = arr.length - 1; e > 0; e--){
//o ~ e
for(int i = 0; i < e; i++){
if(arr[i] > arr[i + 1]){
swap(arr, i, i + 1)
}
}
}
}
public static void swap(int[] arr, int i, int j){
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
插入排序:
public class InsertionSort{
public static void InsertionSort(int[] arr){
if (arr == null || arr.length < 2) {
return;
}
//0 ~ 1(i)
//0 ~ 2(i)
//0 ~ 3(i)
//....
for (int i = 1; i < arr.length; i++) {
for (int j = i - 1; j >= 0 &&arr[j] > arr[j + 1]; j--){
swap(arr, j, j + 1);
}
}
}
public static void swap(int[] arr, int i, int j){
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
二分法:
public class BSExist{
public static boolean exist(int[] sortedArr, int num){
if(sortedArr == null || sortedArr.length == 0) {
return false;
}
int L = 0;
int R = sortedArr.length - 1;
int mid = 0;
while (L < R) {
mid = L + ((R - L) >> 1);
if (num = sortedArr[mid]) {
return ture;
}
else if (sortedArr[mid] > num) {
R = mid - 1;
}
else {
L = mid + 1;
}
}
}
return sortedArr[L] == num;
}
-
数组
-
public class DynmicArray { private int size; private int capacity; private int[] array = new int[capacity]; public void add(int index,int element) { checkAndGrow(); if(index >= 0 && index <size) { System.arraycopy(array, index, array, index + 1, size - index); } array[index] = element; size++; } public int remove (int index){ int removed = array[index]; if(index < size - 1) { System.arraycopy(array, index + 1,array, size - index - 1); } size--; return removed; } private void checkAndGrow(){ if(size == capacity) { capacity +=capacity >> 1; int[] newArray = new int[capacity]; System.arraycopy(array, 0, newArray, 0, size); array = newArray; } } }
-
在对一个int[i] [j]遍历时,把i作为外层嵌套遍历用时更短,原理如下:
-
CPU从内存读取数据,速度太慢了,所以会将读取的数据放入高速缓存中,以防以后需要再读取该数据,可以做到从缓存中直接读取,不必读取内存,节约大量时间
-
缓存的最小单位是缓存行(cache line),大小是64bytes,一次读的数据少了不划算,所以在读取某个数据时,会将其周围临近的数据一并读取,这就是空间局部性
-
-
-
链表
-
//单向链表 public class SinglyLinkedList { //头节点 private Node head = null; //内部类 定义了节点 private static class Node{ int value; Node next; public Node(int value, Node next) { this.value = value; this.next = next; } } //向链表头部添加 public void addFirst(int value) { head = new Node(value, head); } //向链表尾部添加 private Node findLast(){ if(head == null){ return null; } Node p; for(p = head; p.next != null; p = p.next){} return p; } public void addLast(int value){ Node last = findLast(); if(last == null){ addFirst(value); return; } last.next =new Node(value,null); } //遍历链表(循环or实现迭代器) public void loop(){ for( Node p = head; p != null; p = p.next){ System.out.println(p.value); } } //根据索引查看值 private Node findNode(int index){ int i = 0; for(Node p = head; p != null; p = p.next, i++){ if (i == index) { return p; } } return null; } public int get(int index){ Node node = findNode(index); if(node ==null){ throw new IllegalArgumentException(String.format("index不合法")); } return node.value; } //插入元素 public void insert(int index, int value){ if(index == 0){ addFirst(value); return; } Node prev = findNode(index - 1); if(prev == null){ throw new IllegalArgumentException(String.format("index不合法")); } prev.next = new Node(value, prev.next); } //删除节点 public void removeFirst(){ if(head ==null){ throw new IllegalArgumentException(String.format("index不合法")); } head = head.next; } public void remove(int index){ if(index == 0){ removeFirst(); return; } Node prev = findNode(index - 1); if (prev ==null){ throw new IllegalArgumentException(String.format("index不合法")); } Node removed = prev.next; if(removed ==null){ throw new IllegalArgumentException(String.format("index不合法")); } prev.next = removed.next; } }
- 如果引入哨兵模式,可以不考虑空链表的情况
-
//双向链表(哨兵) public class DoublyLinkedListSentinel implements Iterable<Integer> { //一样的,先定义节点内部类 static class Node { Node prev; int value; Node next; public Node(Node prev, int value, Node next) { this.prev = prev; this.value = value; this.next = next; } } private Node head;//头哨兵 private NOde tail;//尾哨兵 public DoublyLinkedListSentinel() { head = new Node(null, 666, null); tail = new Node(null, 888, null); head.next = tail; tail.prev = head; } //查 private Node findNode(int index) { int i = -1; for(Node p = head; p != tail; p = p.next, i++){ if(i ==index){ return p; } } return null; } //插 public void insert(int index, int value) { Node prev = findNode(index - 1); if(prev == null) { throw new IllegalArgumentException(String.format("index不合法")); } Node next = prev.next; Noed inserted = new Node(prev, value, next); prev.next = indserted; next.prev = inserted; } //删 public void remove(int index) { Node prev = findNode(index - 1); if(prev == null) { throw new IllegalArgumentException(String.format("index不合法")); } Node removed = prev.next; if(removed == tail) { throw new IllegalArgumentException(String.format("index不合法")); } Node next = removed.next; prev.next = next; next,prev = prev; } @Override public Iterator<Integer> itreator() { return new Iterator<Integer>() { Node p = head.next; @Override public boolean hasNext() { return p != tail; } @Override public Integer next() { int value = p.value; p = p.next; return value; } }; } }
-
//环形链表(哨兵) public class CycleLinkedListSentinel { private static class Node {.....} private Node sentinel = new Node(null, -1, null); public DoublyLinkedListSentinel() { sentinel.prev = sentinel; sentinel.next = sentinel; } public void addFirst(int value){ Node a = sentinel; Node b = sentinel.next; Node added = new Node(a, value, b); a.next = added; b.prev = added; } public void addLast(int value){ Node a = sentinel.prev; Node b = sentinel; Node added = new Node(a, value, b); a.next = added; b.prev = added; } public void removeFirst() { Node removed = sentinel.next; Node a = sentinel; Node b = removed.next; a.next = b; b.prev = a; } public void removedLast() { Node removed = sentinrl.prev; Node a = removed.prev; Node b = sentinel; a.next = b; b.prev = a; } public void removeByValue(int value) { Node removed = findByValue(value); if(removed ==null) { return; } Node a = removed.prev; Node b = removed.next; a.next = b; b.prev = a } public Node findByValue(int value) { Node p = sentinel.next; while (p != sentinel) { if (p.value == value) { return p; } p = p.next; } return null; } }
-