今天的突然看集合底層的時候發現了好多算法和數據結構。再次就比較一下和匯總一下。
數據結構分類:線性結構和非線性結構
問題一:
什么是線性和非線性;
我個人的理解是:數據結構中線性結構指的是數據元素之間存在着“一對一”的線性關系的數據結構;
線性結構包括:數組,鏈表,隊列,棧;
非線性結構包括:樹,圖,表;
詳解:
一.線性結構
1.數組
特點:我們都知道數組中的元素在內存中連續存儲的,可以根據是下標快速訪問元素,因此,查詢速度很快,然而插入和刪除時,需要對元素移動空間,比較慢。
數組使用場景:頻繁查詢,很少增加和刪除的情況。
2.鏈表
特點:元素可以不連續內存中,是以索引將數據聯系起來的,當查詢元素的時候需要從頭開始查詢,所以效率比較低,然而添加和刪除的只需要修改索引就可以了
使用場景:少查詢,需要頻繁的插入或刪除情況
3.隊列
特點:先進先出,
使用場景:多線程阻塞隊列管理非常有用
4.棧
特點:先進后出,就像一個箱子,
使用場景:實現遞歸以及表示式
5.數組與鏈表的區別
數組連續,鏈表不連續(從數據存儲形式來說)
數組內存靜態分配,鏈表動態分配
數組查詢復雜度0(1),鏈表查詢復雜度O(n)
數組添加或刪除,復雜度o(n),鏈表添加刪除,復雜度O(1)
數組從棧中分配內存。鏈表從堆中分配內存。
二。算法分類:
1)插入排序(直接插入排序、希爾排序)
2)交換排序(冒泡排序、快速排序)
3)選擇排序(直接選擇排序、堆排序)
4)歸並排序
5)分配排序(基數排序)
所需輔助空間最多:歸並排序
所需輔助空間最少:堆排序
平均速度最快:快速排序
不穩定:快速排序,希爾排序,堆排序。
1.直接插入排序
(1)基本思想:在要排序的一組數中,假設前面(n-1)[n>=2] 個數已經是排
好順序的,現在要把第n 個數插到前面的有序數中,使得這 n個數
也是排好順序的。如此反復循環,直到全部排好順序。
/** * 插入排序法 * * @param datas */ public static int[] sortInsert(int[] datas) { for (int i = 1; i < datas.length; i++) { int j = i - 1; AlgorithmUtil.temp = datas[i]; for (; j >= 0 && AlgorithmUtil.temp < datas[j]; j--) { datas[j + 1] = datas[j]; } datas[j + 1] = AlgorithmUtil.temp; } return datas; }
2.簡單選擇排序
(1)基本思想:在要排序的一組數中,選出最小的一個數與第一個位置的數交換;
然后在剩下的數當中再找最小的與第二個位置的數交換,如此循環到倒數第二個數和最后一
個數比較為止。
/** * 選擇排序 * * @return */ public static int[] sortSelect(int[] datas) { for (int i = 0; i < datas.length; i++) { int index = i; for (int j = i + 1; j < datas.length; j++) { if (datas[j] < datas[index]) index = j; } if (i != index) AlgorithmUtil.swap(datas, i, index); } return datas; }
3.冒泡排序
(1)基本思想:在要排序的一組數中,對當前還未排好序的范圍內的全部數,自上而下對
相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒。即:每當兩相鄰的
數比較后發現它們的排序與排序要求相反時,就將它們互換。
/** * 冒泡排序 * * @return */ public static int[] sortBubble(int[] datas) { for (int i = 0; i < datas.length - 1; i++) { for (int j = 0; j < datas.length - 1 - i; j++) { if (datas[j] > datas[j + 1]) AlgorithmUtil.swap(datas, j, j + 1); } } return datas; }
4.快速排序
(1)基本思想:選擇一個基准元素,通常選擇第一個元素或者最后一個元素,通過一趟掃描,
將待排序列分成兩部分,一部分比基准元素小,一部分大於等於基准元素,此時基准元素在其
排好序后的正確位置,然后再用同樣的方法遞歸地排序划分的兩部分。
/** * 快速排序;分割數組 * * @param datas */ public static int QuickPartition(int[] datas, int left, int right) { int pivot = datas[left]; while (left < right) { while (left < right && datas[right] >= pivot) --right; datas[left] = datas[right]; // 將比樞軸小的元素移到低端,此時right位相當於空,等待低位比pivotkey大的數補上 while (left < right && datas[left] <= pivot) ++left; datas[right] = datas[left]; // 將比樞軸大的元素移到高端,此時left位相當於空,等待高位比pivotkey小的數補上 } datas[left] = pivot; // 當left == right,完成一趟快速排序,此時left位相當於空,等待pivotkey補上 return left; } /** * 快速排序;遞歸返回數組 * * @param datas */ public static int[] sortQuick(int[] datas, int left, int right) { if (left < right) { int data = QuickPartition(datas, left, right); sortQuick(datas, left, data - 1); sortQuick(datas, data + 1, right); } return datas; }
1.冒泡算法,2.選擇算法,3.快速算法。4.插入算法,5.希爾算法,6.堆算法
public class AlgorithmUtil { public static int temp,index = 0; /** * 臨時值交換 * * @param datas * 數組 * @param i * @param j */ public static void swap(int[] datas, int i, int j) { temp = datas[i]; datas[i] = datas[j]; datas[j] = temp; } /** * 擴充數組長度 * * @param datas * @param value * @return */ public static int[] expandArray(int[] datas, int value) { if (datas.length <= index) { int[] arrays = new int[datas.length * 2]; System.arraycopy(datas, 0, arrays, 0, datas.length); datas = arrays; } datas[index] = value; index++; return datas; } }