數據結構與算法基礎

一. 數組
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+(2
4+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的前面位置。至此,完成排序。
在這裏插入圖片描述
在這裏插入圖片描述
直接插入排序的優點:簡單明瞭
直接插入排序的缺點:速度很慢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章