算法圖解第二章筆記與習題(選擇排序)

算法圖解第二章筆記與習題(選擇排序)



2.2 數組和鏈表

2.2.1 鏈表

  • 鏈表在內存中通過每個元素存儲下一個元素的地址,使得一系列隨機的內存地址串在一起。

想要在鏈表中插入新的元素,只需要隨機在內存中獲取地址即可。

想要在鏈表中刪除一個元素,只需要修改前一個元素指向的地址,使其跳過要刪除的元素即可。

因此,鏈表易於插入刪除,而不易於讀取。


2.2.2 數組

  • 數組在內存中直接獲取一塊連續的地址,來存儲數據。當數據量超過已有地址時,將無法繼續存儲,需要搬遷整個數組。

由於數組的內存地址是連續的,所以十分易於讀取。但並不容易插入和刪除。


2.2.3 數組和鏈表的讀取、插入和刪除操作的時間複雜度

- 數組 鏈表
讀取 O(1)O(1) O(n)O(n)
插入 O(n)O(n) O(1)O(1)
刪除 O(n)O(n) O(1)O(1)

2.3 選擇排序

# 找出數組中的最小元素
def findSmallest(arr):
  # 存儲最小的值
  smallest = arr[0]
  # 存儲最小元素的索引
  smallest_index = 0
  for i in range(1, len(arr)):
    if arr[i] < smallest:
      smallest_index = i
      smallest = arr[i]      
  return smallest_index

# 排序算法
def selectionSort(arr):
  newArr = []
  for i in range(len(arr)):
      # 找出數組中最小的元素,並將其加入到新的數組中
      smallest = findSmallest(arr)
      newArr.append(arr.pop(smallest))
  return newArr


2.4 小結

  • 需要存儲多個元素時,可使用數組或鏈表。
  • 數組的元素都是連在一起的,就像一節節車廂。
  • 鏈表的元素是分散開的,其中每個元素都存儲了下一個元素的地址。
  • 數組的讀取速度很快。
  • 鏈表的插入和刪除的速度很快。
  • 在同一個數組中,所有元素的類型都必須相同(都爲int、double等)。

練習

習題2.1

  • 假設你要編寫一個記賬的應用程序。你每天都將所有支出記錄下來,並在月底統計支出,算算當月花了多少錢。因此,你執行的插入操作很多,但讀取操作很少。該使用數組還是鏈表呢?

插入操作很多,但讀取操作很少。因此更適合用鏈表。


習題2.2

  • 假設你要爲飯店創建一個接受顧客點菜單的應用程序。這個應用程序存儲一系列點菜單。服務員添加點菜單,而廚師去除點菜單並製作菜餚。這是一個點菜單隊列:服務員在隊尾添加點菜單,廚師取出隊列開頭的點菜單並製作菜餚。

  • 你使用數組還是鏈表來實現這個隊列呢?(提示:鏈表擅長插入和刪除,而數組擅長隨機訪問。在這個應用程序中,你要執行的是哪些操作呢?)

鏈表,在這個應用程序中,使用的更多是插入和刪除,因此選擇鏈表。


習題2.3

  • 我們來做一個思考實驗。假設Facebook記錄一系列用戶名,每當有用戶試圖登錄Facebook時,都查找其用戶名,如果找到就允許用戶登錄。由於經常有用戶登錄Facebook,因此需要執行大量的用戶名查找操作。假設Facebook使用二分查找算法,而這種算法要求能隨機訪問——立即獲取中間的用戶名。考慮到這一點,應使用數組還是鏈表來存儲用戶名呢?

數組,在這個思考實驗中,需求是能夠隨機訪問。而數組相比起鏈表來說,更易於查詢。


習題2.4

  • 經常有用戶在Facebook註冊。假設你已決定使用數組來存儲用戶名,在插入方面數組有何缺點呢?具體地說,在數組中添加新用戶將出現什麼情況?

在插入方面,數組容易內存不足,需要的操作也比較複雜,時間複雜度爲O(n)O(n)

具體地說,在數組中添加新用戶時,首先需要判斷剩餘的內存空間是否富足,如果不足,則需要整體搬遷數組在內存中的地址,其次需要查找元素在數組中的位置,並將在它後面的所有元素後移一位,最多需要移動 nn 位,這也是爲什麼在數組中添加新用戶時其時間複雜度位O(n)O(n)的原因。


習題2.5

  • 實際上,Facebook存儲用戶信息使用的既不是數組也不是鏈表。假設Facebook使用的是一種混合數據:鏈表數組。這個數組包含有26個元素,每個元素都指向一個鏈表。例如,該數組的第一個元素指向的鏈表包含所有以A打頭的用戶名,第二個元素指向的鏈表包含所有以B打頭的用戶名,以此類推。

  • 假設Adit B在Facebook註冊,而你需要將其加入前述的數據結構中。因此,你訪問數組的第一個元素,在訪問該元素指向的鏈表,並將Adit B添加到這個鏈表的結尾。現在你要查找Zakhir H。因此你訪問第26個元素,再在它指向的鏈表(該鏈表包含所有以z打頭的用戶名)中查找Zahkir H。
  • 請問,相比於數組和鏈表,這種混合數據結構的查找和插入速度更慢還是更快?你不必給出大OO運行時間,只需指出這種新數據結構的查找和插入速度更快還是更慢。

插入爲常數時間O(1)O(1),實際爲O(2)O(2)(在兩個鏈表中插入)。因此比數組​O(n)O(n)快,比鏈表$O(1) $稍慢,但區別不大。

查詢爲O(n)O(n),但實際上是O(126n)O(\frac1{26}n) ,因此比數組O(1)O(1)慢,但比鏈表O(n)O(n)快。


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