文章目錄
一. 數組
1. 數組結構的特點
(1) 數組元素數目不變,一旦定義了一個數組結構,數組元素個數就不會發生改變
(2) 數組元素具有相同的數據類型
(3) 數組元素的下標關係具有上下界的約束且下標有序
2. 數組的兩個基本運算
(1) 給定一組下標,存取相應的數據元素
(2) 給定一組下標,修改相應的數組元素中某個數據項的值
3. 數組的存儲
根據數組結構的特點知道數組一般不做插入和刪除操作,數組的存儲適合採用順序存儲結構,二維數組存儲結構可分爲按行爲主序和按列爲主序兩種存儲方法。
4. 數組存儲地址的計算
數組類型 | 存儲地址的計算(a是數組首地址,len是每個數組元素所佔長度) |
---|---|
一維數組 | a[i]的存儲地址:a+i*len |
二維數組:a[m][n] | 按行存儲:a+(i*n+j) *len;按列存儲:a+(j *m+i) *len |
數組存儲地址的計算示例:
1)已知一維數組a中每個元素佔用2個字節,求a[10]的存儲地址?
答:a[10]的存儲地址爲:a+10*2=a+20
2)已知4行5列的二維數組a中的每個元素佔用2個字節,求元素a[3][2]按行爲主序存儲的存儲地址和按列爲主序存儲的存儲地址?
答:
按行存儲:a+(3*5+2)2 = a+34
按列存儲:a+(24+3)*2 = a+22
二. 矩陣
1. 稀疏矩陣的定義
在一個矩陣中,非零的元素的個數遠遠多於零元素的個數,並且非零元素的分佈沒有規律,稱爲稀疏矩陣。
2. 稀疏矩陣的存儲
存儲稀疏矩陣中非零元素時,必須存儲其位置。三元組(i,j,aij)可唯一確定矩陣中的一個元素。稀疏矩陣的三元組表的順序存儲稱爲三元組順序表,常用的三元組表的鏈式存儲結構是十字鏈表。
3.上三角矩陣與下三角矩陣
主對角線以下都是零的方陣稱爲上三角矩陣,主對角線以上都是零的方陣稱爲下三角矩陣。稀疏矩陣大量元素是零,存儲一部分內容就已經把有效數據存儲了,這可以節省很多空間。存儲稀疏矩陣一般存儲上三角矩陣或下三角矩陣,如在上三角矩陣或者下三角矩陣中,遇到上半部分和下半部分數據可能重複的情況下,只需要存儲上半部分的數據或者下半部分的數據即可。
4. 求三角矩陣中某一個元素對應一維數組的下標
稀疏矩陣 | 計算方法 |
---|---|
上三角矩陣 | 下標分別爲i和j的元素對應的一維數組的下標計算公式是:(2 n - i + 1) * i / 2 + j |
下三角矩陣 | 下標分別爲i和j的元素對應的一維數組的下標計算公式是:(i + 1) * i / 2 + j |
示例:
設有如下所示的下三角矩陣 A [ 0…8 ,0…8 ],將該三角矩陣的非0元素(即:行下標不小於列下標的所有元素)以行優先壓縮存儲到 M [ 1…m ]中,則元素 A [ i , j ] (0<=i<8,j<=i)存儲在數組M中的( )中?
A(0,0)
A(1,0) A(1,1)
A(2,0) A(2,1) A(2,2)
A(2,0) A(2,1) A(2,2) A(2,3)
. . .
. . .
A(8,0) A(8,1) A(8,2) A(8,3) A(8,4) . . . . . A(8,8)
答案: M [ (i + 1) * i / 2 + j+1 ]
分析:
將A(0,0)即:i=0,j=0代入 (i + 1) * i / 2 + j 中,查看結果是不是M [ 1 ]中的1。很明顯,計算結果是0。這裏將0加1後的結果纔是1,所以我們考慮M中的結果是 (i + 1) * i / 2 + j+1。將A [2,1]中i=2,j=1代入推算的公式: (i + 1) * i / 2 + j+1,發現A[1,2]對應M [5 ],滿足條件。通過代入矩陣中的其它元素後,發現我們推導的公式: (i + 1) * i / 2 + j+1是滿足題意的。所以,答案是:M [ (i + 1) * i / 2 + j+1 ]
三. 數據結構的定義
1. 數據結構的概念
計算機存儲以及組織數據的方式。
2. 爲什麼去研究數據結構
選擇不同的數據結構,可能帶來的運行效率差異比較大。
3. 數據邏輯結構
- 線性結構
線性結構類似一個個元素連接成一條線 - 非線性結構
非線性結構可以分爲:樹形結構和圖。樹形結構和圖的區別是:樹形結構裏面沒有環路,而圖中有環路。廣義的圖既包括樹,也包括線性結構,而廣義的樹還包括線性結構。
四. 順序表與鏈表
1. 順序表概述
順序表開闢了連續的空間,順次將數據存儲。
2. 鏈表概述
- 單鏈表
單鏈表中指針是單向的,頭節點指向第一個元素,第一個元素指向第二個元素,第二個元素指向第三個元素……以此類推。 - 循環鏈表
把尾元素的指針指向了頭節點,指向頭節點的好處是:如果當前指針是在尾元素,要定位在其它任何一個元素的時候,可以next,定位到它。而不用重新定位到頭節點纔開始。 - 雙向鏈表
單鏈表只能指向一個方向,而雙鏈表兩個方向都可以指向。
3. 鏈表的操作
- 單鏈表刪除節點
q->nest = p->next
- 單鏈表插入節點
s->next = p->nest
p->next = s
- 雙鏈表刪除節點
- 雙鏈表插入節點
單鏈表是分有頭節點和沒有頭節點的,頭節點不存任何信息, 頭節點下一個元素才存儲信息。有頭節點的好處是:引入的頭節點可以讓所有節點的操作方式變成一致的。如果頭節點存有別的元素即存儲具體內容,往往需要採取不同的處理方式。
五. 算法的基本特性
- 有窮性
執行有窮步之後結束。 - 確定性
算法中每一條指令都必須有確切的含義,不能含糊不清。 - 輸入
0個或0個以上的輸入。 - 輸出
至少有一個輸出。 - 有效性
算法中的每一個步驟都能得到有效地執行並且能得到確定的結果。如:a = 0,c = b/9這一步就是無效的
六. 查找
1. 順序查找
- 順序查找的思想
將待查找的關鍵字爲key的元素從頭到尾與表中元素進行比較,如果中間存在關鍵字爲key的元素,則返回查找成功;否則返回查找失敗。
| 1 |2 |3| 4 |5 |6| 7 |8 |
|–|--|–|--|–|--|–|--| - 順序查找的平均查找長度
ASL = (n+1)/ 2
時間複雜度:O(n)
2. 折半查找(二分查找)
- 折半查找的思想
不是所有的序列都可以用折半查找法,折半查找的前提是:查找的序列中的數是有序(從大到小或者從小到大)排列的。 - 查找過程
【例題】請給出在含有12個元素的有序表{1,4,10,16,17,18,23,29,33,40,50,51}中查找關鍵字17的過程:
將12個元素按照順序排序(正序和逆序都可以):
1 | 4 | 10 | 16 | 17 | 18 | 23 | 29 | 33 | 40 | 50 | 51 |
---|
第一輪查找:將第一個元素的位置下標與最後一個元素的位置下標相加,然後除以2向下取整,得到17第一次要比較的數值。(1+12)/2 =6.5,向下取整就是6。所以,17要與下標爲6的數值做比較,下標6對應的數值是18。因爲17<18,所以17必然在下標爲6的左邊部分,把查找的範圍縮小一半。
第二輪查找:(1+5)/2 = 3,所以17要與3對應的數值進行比較。因爲17>10,所以17應該在4的左邊部分。
第三輪查找:範圍縮小到4~5之間,(4+5)/2 = 4.5,則17要與下標4所在位置的值做比較。因爲17>16,所以17在座標爲4的右邊部分
第四輪查找:(5+5)/2 = 5,17與下標爲5的值做比較,17=17,所以只有下標爲5符合題意。
- 折半查找的時間複雜度
折半查找在查找成功時,關鍵字的比較次數最多爲:log2n +1次
折半查找的時間複雜度:O(log2n)
七. 散列表
1. 散列表查找的基本思想
已知關鍵字集合U,最大關鍵字爲m。設計一個hash函數,它一關鍵字爲變量,關鍵字的存儲地址爲因變量,將關鍵字映射到一個有限的、地址連續的區間中。這個區間就是散列表,散列查找中使用的轉換函數稱爲散列函數。
2. 散列表查找實例
【例】記錄關鍵碼爲(3,8,12,17,9),取m=10(存儲空間爲10),p = 5,散列函數 h = key%p。
- 3 % 5 = 3,將關鍵碼3放置到位置爲3的存儲空間。
- 8 % 5 = 3,再放在存儲空間3的位置就會發生衝突,使用開放定址法的思想,可將關鍵字8存放在存儲空間3的下一個位置存儲空間4。
開放定址法:當構造散列表發生衝突時,使用某種探測手段,產生一個探測的散列地址序列,並且逐個查找此地址中是否存儲數據元素。如果沒有存儲,則稱該散列地址開放,並將關鍵字存入,否則繼續查找下一個地址。只要散列表足夠大,總能找到空的散列地址將數據元素存入。
-
12 % 5 = 2,將關鍵碼12放置在存儲空間2的位置中。
-
17 % 5 = 2,存儲空間2的位置已經存有元素,根據開放定址法的思想,需要向下查找,需要找到空的散列地址將元素存入。查找到存儲空間5的位置是空的,所以將17存入存儲空間5的位置。
-
9 % 5 = 4,存儲空間4已經存在元素,向下查找,存儲空間5也存在元素。繼續向下查找,存儲空間6是空的,所以將關鍵碼9存入存儲空間6的位置上。
八. 排序
1. 排序的概念
- 穩定的排序:原來的兩數中第一個數大於第二個數,排序之後第一個數還是大於第二個數。兩數的順序不會因爲排序之後發生順序的改變。
- 不穩定的排序:兩數的順序會因爲排序之後發生順序的改變。
2. 內排序與外排序
內排序:在內存裏面進行排序
外排序:涉及外部存儲空間
3. 排序方法的分類
- 插入類排序
插入排序:直接插入排序、希爾排序
直接插入排序思路簡單、操作容易,但是效率沒有希爾排序高。 - 交換類排序
交換類排序:冒泡排序、快速排序
快速排序效率比較高,過程複雜一些。 - 選擇類排序
選擇類排序:簡單選擇排序、堆排序
堆排序效率非常高,但處理過程複雜。 - 歸併排序
- 基數排序
4. 直接插入排序
- 直接插入排序的思路
當插入第i個記錄時,R1,R2,……,Ri-1均已經排好序。因此,將第i個記錄Ri依次與Ri-1,……,R2,R1進行比較,找到合適的位置插入。
【例】使用插入排序對57 68 59 52進行排序
(1)第一步:比較57、68兩數,因爲57<68,所以位置不發生改變
(2)第二步:將59與68做比較,59<69,所以59應該在68的前面(左邊),但不確定將59插入在57的前邊,還是插入到57的後面。所以,59需要與57再做比較。
(3)第三步:因爲59>57,所以59在57的後面(右邊),將59插入在57的後面的位置(也即68的前的位置)上。
(4)第四步:將52與68做比較,52<68,所以52必在68的前面。
(5)第五步:68的前面位置有59和57,所以需要將52與59比較。因爲52<59,所以52在59的前面位置。
(6)第六步:因爲59的前面位置還有57,所以需要將52與57比較。因爲52<57,所以52要插入到57的前面位置。至此,完成排序。
直接插入排序的優點:簡單明瞭
直接插入排序的缺點:速度很慢