數據結構大致包含以下幾種存儲結構:
**線性表**:零個或多個數據元素的有限序列
還可細分為順序表(底層實現靠數組)、鏈表、棧和隊列;棧和隊列隸屬于線性表,是特殊的線性表。
元素有多個時,第一個元素無前驅,最后一個無后繼,其他每個元素都有且只有一個前驅和后繼。
**樹結構**:包括普通樹,二叉樹,線索二叉樹等;
**圖存儲結構**
## 數組、順序表(順序存儲結構)
順序存儲:一段地址連續的存儲單元依次存儲線性表的數據元素。
三個重要屬性:
**起始位置、最大存儲容量、當前長度**
查詢的時間復雜度 o(1)
插入和刪除的復雜度是o(n)。 ?
插入時,后面的數據都要往后移動,刪除時,后面的數據都要往前移動
**優點:**
可以快速的存取表中任一位置的元素。
不需要為表示元素之間的邏輯關系而增加額外存儲空間。
**缺點:**
插入和刪除操作需要移動大量元素、性能受損
當元素數量變化較大,難以確定最大存儲容量
造成存儲空間的“碎片”
順序表底層就是使用數組。
## 鏈表、鏈式存儲結構
鏈式存儲:地址可以連續也可以不連續的存儲單元存儲數據元素
數據域:存儲數據元素信息的域
指針域:存儲直接后繼位置的域(后一個元素的地址)
數據域 + 指針域 ?就是結點
### 單鏈表
單鏈表:鏈表中的每個結點中只包含一個指針域
頭指針:鏈表中第一個結點的存儲位置
頭結點:有時會為了方便,會在單鏈表的第一個結點前附設一個節點,就是頭結點,頭結點的數據域可以不存儲任何信息。
頭指針和頭結點的區別:
頭指針是指鏈表指向第一個結點的指針,若鏈表有頭結點,則是指向頭結點的指針
頭指針具有標識作用,所以常用頭指針冠以鏈表的名字
無論鏈表是否為空,頭指針均不為空。頭指針是鏈表的必要元素
頭結點是為了操作的統一和方便而設立的,放在第一個元素的結點之前,其數據域一般無意義。
有了頭結點,對在第一個元素節點前插入結點和刪除第一個結點,其操作與其他結點的操作就統一了。
頭結點不一定是鏈表必須要素
查詢的時間復雜度 o(1)到o(n) ,查第一個就是o(1),最壞的情況是 o(n)
插入和刪除的復雜度,當知道元素的指針位置時是o(1),否則需要先查詢,復雜度則變成o(n)。 ?
插入和刪除越頻繁的操作,單鏈表的效率優勢就越是明顯。
工作指針后移
## 順序存儲結構和單鏈表存儲結構的區別
* 存儲分配方式:
* 順序存儲結構用一段連續的存儲單元依次存儲線性表的數據元素。
* 單鏈表采用鏈式存儲結構,用一組任意的存儲單元存放線性表的元素。
* 時間性能:
* 查找:
* 順序存儲結構O(1)
* 單鏈表O(n)
* 插入和刪除
* 順序存儲結構需要平均移動表長一半的元素,時間為O(n)
* 單鏈表在線出某位置的指針后,插入和刪除時間僅為O(1)
* 空間性能
* 順序存儲需要預分配存儲空間,分大了浪費,分小了易發生上溢
* 單鏈表不需要分配存儲空間,只要有就可以分配,元素個數也不受限制
結論:
**插入和刪除頻繁的使用單鏈表結構,頻繁查找的使用順序存儲結構**
**元素個數變化較大或根本無法確定可能的個數范圍,最好考慮單鏈表,這樣不需要考慮存儲空間的大小**
## 邏輯結構和物理結構

## 棧
棧是限定僅在表尾進行插入和刪除操作的線性表。
我們把允許**插入和刪除的一端稱為棧頂**(top),**另一端稱為棧底**(bottom),不含任何數據元素的棧稱為空棧。棧又稱為后進先出(Last In First Out)的線性表,簡稱LIFO結構。
棧元素也具有線性關系,棧是一種特殊的線性表。定義中說是在線性表的表尾插入和刪除操作,這里表尾是指棧頂,而不是棧底。特殊在于限制了這個線性表的插入和刪除位置,只在棧頂進行。
棧的插入操作,叫作進棧,也稱壓棧、入棧。類似子彈入彈夾。
棧的刪除操作,叫作出棧,也有的叫作彈棧。如同彈夾中的子彈出夾。
## 隊列
隊列是只允許在一端進行插入操作、而在另一端進行刪除操作的線性表。
隊列是一種先進先出(First In First Out)的線性表,簡稱FIFO,允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。
同樣是線性表,隊列也有類似線性表的各種操作,不同的就是插入數據只能在隊,尾進行,刪除數據只能在隊頭進行。
把隊列的這種頭尾相接的順序存儲結構稱為循環隊列。隊尾指針指向的位置永遠空出1位,所以隊列
最大容量比數組長度小1。
隊列的鏈式存儲結構,其實就是線性表的單鏈表,只不過它只能尾進頭出而已,我們把它簡稱為鏈隊列。
**雙端隊列:** 這種數據結構,可以說綜合了棧和隊列的優點,對雙端隊列來說,從隊頭一端可以入隊或出隊,從隊尾一端也可以入隊或出隊。盡管雙端隊列看起來似乎比棧和隊列更靈活,**但實際上在應用程序中遠不及棧和隊列有用。**
**優先隊列**: ?優先隊列已經不屬于線性數據結構的范疇了,它是基于二叉堆來實現
## hash 哈希 (散列表)
散列表也叫作哈希表 (hash table),這種數據結構提供了鍵(Key)和值(Value) 的映射關系。
底層使用數組, 通過哈希函數將 key 轉為 數組下標
當數據量大時, 容易出現哈希函數將不同的key 轉為數組下標時出現相同的值, 這就是**哈希沖突**
哈希沖突的解決:
開放尋址法:如果經過哈希函數獲得的下標所在位置已經有值,則往后移動一位,如果移動到的位置也已經有值了,就繼續往后移動,直到找到空位。開放尋址法有多種,這是最簡單的,java 的 ThreadLocal 就是這樣做的。
鏈表法(拉鏈法):如果經過哈希函數獲得的下標所在位置已經有值,則在這個位置增加一個鏈表,這個位置所有的數據以key value 的對象形式都放到鏈表里,相當于數組嵌套鏈表。java的HashMap是這樣做的(1.8以后應該是紅黑樹)
### hash 的擴容
對于JDK中的散列表實現類HashMap來說,影響其擴容的因素有兩個。
Capacity ,即HashMap的當前長度
LoadFactor ,即HashMap的負載因子,默認值為0.75f
HashMap.Size >= Capacity×LoadFactor
**hash 擴容過程**
擴容 ,創建一個新的Entry空數組,長度是原數組的2倍。
重新Hash ,遍歷原Entry數組,把所有的Entry重新Hash到新數組中。為什么要重新Hash呢?因為長度擴大以后,Hash的規則也隨之改變。
經過擴容,原本擁擠的散列表重新變得稀疏,原有的Entry也重新得到了盡可能均勻的分配。
## 樹
樹(tree)是n(n≥0)個節點的有限集。當n=0時,稱為空樹。在任意一 個非空樹中。
主要特點:
有且僅有一個特定的稱為根的節點。
當n>1時,其余節點可分為m(m>0)個互不相交的有限集,每一個集 合本身又是一個樹,并稱為根的子樹。
沒 有“孩子”的節點是葉子節點
樹的最大層級數,被稱為樹的高度或深度
### 二叉樹
這種樹 的每個節點**最多有2個**孩子節點,也可能只 有1個,或者沒有孩子節點。
二叉樹節點的兩個孩子節點,一個被稱為左孩子(left child) ,一個被 稱為右孩子(right child) 。
二叉樹還有兩種特殊形式,一個叫作滿二叉樹 ,另一個叫作完 全二叉樹 。
**滿二叉樹:**一個二叉樹的所有非葉子節點都存在左右孩子,并且所有葉子節點都在 同一層級上,那么這個樹就是滿二叉樹。
滿二叉樹要求所有分支都是 滿的;而**完全二叉樹**只需保證**最后一個節點之前的節點都齊全**即可。
二叉樹可以用哪些物理存儲結構來表達呢?
1. 鏈式存儲結構。
2. 數組。

鏈表:一個節點最多可以指向左右兩個孩子節點,所 以二叉樹的每一個節點包含3部分。 存儲數據的data變量 指向左孩子的left指針 指向右孩子的right指針

數組:按照層級順序把二叉樹的節點放到數組中對應的位 置上。如果某一個節點的左孩子或右孩子空缺,則數組的相應位置也空 出來
假設一個父節點的下標是parent,那么它的左孩子節點下標就 是2×parent + 1 ;右孩子節點下標就是2×parent + 2 。 反過來,假設一個左孩子節點的下標是leftChild,那么它的父節點下標 就是(leftChild-1)/ 2 。
### 二叉查找樹(二叉排序樹)
二叉查找樹在二叉樹的基礎上增加了以下幾個條件。
* 如果左子樹不為空,則左子樹上所有節點的值均小于根節點的值
* 如果右子樹不為空,則右子樹上所有節點的值均大于根節點的值
* 左、右子樹也都是二叉查找樹

二叉查找樹 利于查找和排序,但 9 8 7 6 5 等節點樹時會涉及二叉樹的自平衡,二叉樹自平衡的 方式有多種,如紅黑樹、AVL樹、樹堆等。
二叉樹的遍歷
1\. 深度優先遍歷 (前序遍歷、中序遍歷、后序遍歷)。
2\. 廣度優先遍歷 (層序遍歷)。
深度優先遍歷
二叉樹前序遍歷、中序遍歷、后序遍歷、層序遍歷的直觀理解 [https://blog.csdn.net/u013834525/article/details/80421684](https://blog.csdn.net/u013834525/article/details/80421684)
(前序遍歷、中序遍歷、后序遍歷) 指的是 輸出根節點的順序

二叉樹的前序遍歷,輸出順序是根節點、左子樹、右子樹。
輸出順序 根 =》左 =》右
1\. 從樹的根節點開始輸出根節點,然后一直遍歷并輸出左子樹的左節點,直到節點沒有左子樹為止,這時候再去遍歷最后一個左節點的右子樹或者父節點的右子樹
2\. 遍歷右子樹時, 有左子樹的,再按照1的流程遍歷輸出這個右子樹。

二叉樹的中序遍歷,輸出順序是左子樹、根節點、右子樹。
輸出順序 左 =》根 =》右
1\. 首先訪問根節點的左孩子,如果這個左孩子還擁有左孩子,則繼續深 入訪問下去,一直找到不再有左孩子的節點,并輸出該節點。

二叉樹的后序遍歷,輸出順序是根節點、左子樹、右子樹。
輸出順序 左 =》右 =》根

廣度優先遍歷
層序遍歷,顧名思義,就是二叉樹按照從根節點到葉子節點的層次關 系,一層一層橫向遍歷各個節點。代碼實現可以使用隊列

二叉堆
二叉堆本質上是一種完全二叉樹,它分為兩個類型。
1\. 最大堆。
最大堆的任何一個父節點的值,都大于或等于 它 左、右孩子節點的值。
2\. 最小堆。
最小堆的任何一個父節點的值,都小于或等于它左、 右孩子節點的值。
二叉堆的根節點叫作堆頂 。
最大堆的堆頂是整個堆中的最大元素 ;最小堆的堆頂是整個堆中的最小元素 。
堆的刪除操作是單一節點的“下沉”,這兩個操作的平均交換 次數都是堆高度的一半,所以時間復雜度是O(logn)。至于堆的構 建,需要所有非葉子節點依次“下沉”,所以我覺得時間復雜度應該 是O(n)
二叉堆雖然是一個完全二叉 樹,但它的存儲方式并不是鏈式存儲,而是順序存儲。換句話說,二叉 堆的所有節點都存儲在數組中。
假設父節點的下標是parent,那么它的左孩子下標就是 2×parent+1 ;右 孩子下標就是2×parent+2 。
- 學習地址
- MySQL
- 查詢優化
- SQL優化
- 關于or、in、not in、!=等走不走索引的說明
- 千萬級數據查詢優化
- MySQL 深度分頁問題
- 嵌套循環 Block Nested Loop 導致索引查詢慢
- MySQL增加日志統計表優化各種日志表的統計功能
- MySQL單機讀寫QPS(性能)優化
- sqlMode 置 select 的值可以比 group 里的多
- drop、delete、truncate的區別
- 尚硅谷MySQL數據庫高級學習筆記
- MySQL架構
- 事務部分
- MySQL知識點
- mysql索引
- Linux docker安裝 mysql 8.0.25
- docker 安裝mysql 5.7
- mysql Field ‘xxx’ doesn’t have a default value
- mysql多實例
- docker中的sql文件導入
- mysql進階知識
- mysql字符集
- 連接的原理
- redo日志
- InnoDB存儲引擎
- InnoDB的數據存儲結構
- B+樹索引
- 文件系統-表空間
- Buffer Pool
- 億級數據導入到es
- MySQL數據復制
- MySQL缺少主鍵的表數據
- mysql update 其中更新的字段根據另一個更新字段作為條件去更新
- MySQL指定字段值排序(將指定值排在前面)
- 設置MySQL連接數、時區
- Navicat15右鍵刪除數據刷新就又恢復了
- MySQL替換字段部分內容
- Java和MySQL統計本周本月本季和年
- 分頁時order by 排序數據重復,丟失
- mysql同一張表根據某個字段刪除重復數據
- mysqldump定時全量熱備
- 專題總結
- 事務
- MySQL事務
- spring事務
- spring事務本類調用
- spring事務傳播行為
- spring事務失效問題
- 鎖和Transactional注解一塊使用的問題
- 數據安全
- 敏感數據
- SQL注入
- 數據源
- XSS
- 接口設計
- 緩存設計
- 限流
- 自定義注解實現根據用戶做QPS限流
- 架構
- 高可用
- Java
- Unsatisfied dependency expressed through field ‘baseMapper‘
- mybatisplus多數據源
- 單個字母前綴的java變量
- spring
- spring循環依賴解決
- 事務@Transactional
- yml 文件配置信息綁定到java工具類的靜態變量上
- @Configuration @Component 區別
- springboot啟動yml文件報錯
- spring方法重試注解Retryable
- spring讀取yml集合數據
- spring自定義注解
- 獲取resource下的圖片資源
- 手機號和電話號的正則驗證
- 獲取字符串中的數字
- mybatis
- mybatis多參數添加數據并返回主鍵
- 統一異常處理
- 分組校驗
- Java讀取Python json.dumps 函數保存的redis數據
- springboot整合springCache
- 若依mybatis值為null的字段沒有返回
- 若依
- 接口白名單
- @JsonFormat時區問題
- RequestParam.value() was empty on parameter 0
- jdk8和hutool請求第三方的https報錯
- springMVC
- springMVC與vue使用post傳數組
- elementUI 時間組件報錯問題
- vue具名插槽slot
- springboot配置maven的profiles(配置微服務多環境切換打包)
- resources 配置文件讀取順序
- Windows的cmd部署jar注意事項
- Java基礎
- JUC(鎖-并發-線程池)
- CAS
- Java 鎖簡介
- synchronized和Logk有什么區別?用新的ock有什么好處
- synchronized鎖介紹
- CompletableFuture
- 多線程
- 線程池
- 集合類
- map見過的小問題
- 退出雙層循環
- StringBuilder和StringBuffer核心區別
- 日志打印
- 打印log日志
- log日志文件生成配置
- 日期時間
- 時間戳轉為時間
- 并發工具
- 連接池
- http調用
- 內網訪問天地圖
- 判等問題
- 數值計算
- null問題
- 異常處理
- 文件IO
- 序列化
- 內存溢出OOM
- Double轉String出現E的問題
- springboot接收前端表單提交多字段和上傳文件
- 子線程的錯誤, 全局異常處理捕獲不到
- vue同一個項目訪問多個不同ip地址接口
- Autowired注解導入為null
- shiro
- UnavailableSecurityManagerException錯誤
- Windows服務器80端口被占用
- java圖片增加水印
- springcloud
- Feign方法配置錯誤導致jar包啟動失敗
- feign調用超時
- Springcloud從Nacos的yml文件讀取出錯
- 定時任務quartz
- JavaPOI導出Excel
- 合并行和列
- 設置樣式
- 設置背景色
- docker
- Linux 安裝
- docker命令
- docker網絡
- docker數據卷
- dockerfile
- docker安裝ping命令
- docker-compose
- docker-compose文件內容介紹
- Linux關閉docker開機啟動
- jar打包為鏡像
- 遷移docker容器存儲位置
- Nginx
- Linux在線安裝Nginx
- nginx.conf 核心配置文件
- vue 和 nginx 刷新頁面會報404
- nginx 轉發給三個集群的tomcat
- ServerName匹配規則
- Nginx負載均衡策略
- location 匹配規則
- Nginx 搭建前端調用后臺接口的集群
- alias與root
- nginx 攔截 post 請求, 帶參數轉發到前端頁面
- 防盜鏈配置
- Nginx的緩存
- 通用Nginx配置
- nginx配置文件服務器
- 后臺jar包得不到正確ip,nginx代理時要處理
- 升級使用websocket協議
- 設置IP黑/白名單
- vue項目get請求Nginx返回html頁面post返回405錯誤
- Nginx限制所有接口流量
- Redis
- 緩存數據一致性
- 內存淘汰策略
- Redis數據類型
- gmt6
- Linux安裝GMT6
- GMT6配置中文
- GMT文件修改Windows版本到Linux版本
- 注意GMT不同字體導致符號不同的問題
- GMT繪制南海諸島小圖
- GMT生成中文圖例
- elasticsearch
- 安裝配置
- Linux安裝配置elasticsearch7.6.2
- Linux 安裝 kibana 7.6.2
- 安裝7.6.2中文分詞器
- docker 安裝elasticsearch7.6.2
- 安裝Logback7.6.2
- springboot使用
- 0. elasticsearch賬號密碼模式訪問
- 1. 配置連接
- 2. 索引
- 3. 批量保存更新
- Result window is too large 10000
- elasticsearch 分詞的字段做排序 fielddata, 設置fielddata=true 無效果
- elasticsearch 完全匹配查詢(精確查詢)
- 模糊搜索
- 日期區間查詢
- 6.x基礎知識
- 自定義詞庫
- elasticsearch集群
- 搜索推薦Suggester
- 查詢es保存的數組
- 億級mysql數據導入到es
- es 報錯 ORBIDDEN/12/index read-only
- es核心概念
- es的分布式架構原理
- 優化大數據量時的ES查詢性能
- canal
- 1. mysql的Binlog
- 2. Canal 的工作原理
- 3. canal同步es
- JVM
- 1 類的字節碼
- 2. 類的加載
- JVM知識點
- Maven
- 依賴沖突
- xxl-job
- docker 安裝配置 xxl-job
- idea
- springboot啟動報錯命令過長
- services統一啟動微服務各模塊
- 云服務器安裝寶塔面板
- 突然出現啟動或者運行特別慢
- 有導入依賴但是顯示紅色同時點擊進去也有依賴
- Linux
- sh文件執行報錯: command not found
- 使用vagrant安裝虛擬機
- Linux 開啟端口
- 開放端口
- 復制文件夾及其文件到另一個文件夾
- 兩個服務器之間映射端口
- TCP協議
- 分層模型
- TCP概述
- 支撐 TCP 協議的基石 —— 首部字段
- 數據包大小對網絡的影響 —— MTU 與 MSS 的奧秘
- 端口號
- 三次握手
- TCP 自連接
- 四次揮手
- TCP 頭部時間戳
- 分布式
- 分布式腦裂問題
- 分布式事務
- 基礎知識
- 實現分布式事務的方案
- 阿里分布式事務中間件seata
- 冪等性問題
- 其他工具
- webstorm git提交代碼后project目錄樹不顯示
- 消息隊列
- 如何保證消費的順序
- 數據結構
- 漫畫算法:小灰的算法之旅
- oracle