日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2月1日学习内容整理:算法

發布時間:2025/5/22 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2月1日学习内容整理:算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、概念

一個計算過程,解決問題的方法

2、時間復雜度和空間復雜度

時間復雜度:用來表示算法的運行效率

》》》一般來說,時間復雜度高的算法比時間復雜度低的算法運行效率高,,但這不是絕對的

》》》常見的時間復雜度(按效率排序) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)

》》》判斷時間復雜度的方法:1)先要找到n;2)如果有循環減半的過程就是logn;3)幾次循環就是n的幾次方

空間復雜度:用來表示算法占用內存大小

3、列表查找

》》》順序查找:從列表第一個元素開始,順序進行搜索,直到找到為止

》》》二分法查找:從有序列表的候選區data[0:n]開始,通過對待查找的值與候選區中間值的比較,可以使候選區減少一半。

二分查找:

def bin_search(data_set, value): low = 0 high = len(data_set) - 1 while low <= high: mid = (low+high)//2 if data_set[mid] == value: return mid elif data_set[mid] > value: high = mid - 1 else: low = mid + 1

遞歸的二分查找:

def bin_search_rec(data_set, value, low, high): if low <= high: mid = (low + high) // 2 if data_set[mid] == value: return mid elif data_set[mid] > value: return bin_search_rec(data_set, value, low, mid - 1) else: return bin_search_rec(data_set, value, mid + 1, high) else: return

?

?

?

?

4、列表排序

關鍵點:有序區,無序區

一、冒泡排序

1、思路:列表每兩個相鄰的數,如果前邊的比后邊的大,那么交換這兩個數

2、代碼:關鍵點趟和無序區

import random from timewrap import *@cal_time def bubble_sort(li):for i in range(len(li) - 1):# i 表示趟數# 第 i 趟時: 無序區:(0,len(li) - i)for j in range(0, len(li) - i - 1):if li[j] > li[j+1]:li[j], li[j+1] = li[j+1], li[j] #如果冒泡排序中執行一趟而沒有交換,則列表已經是有序狀態,可以直接結束算法 @cal_time def bubble_sort_2(li):for i in range(len(li) - 1):# i 表示趟數# 第 i 趟時: 無序區:(0,len(li) - i)change = Falsefor j in range(0, len(li) - i - 1):if li[j] > li[j+1]:li[j], li[j+1] = li[j+1], li[j]change = Trueif not change:returnli = list(range(10000)) # random.shuffle(li) # print(li) bubble_sort_2(li) print(li)

3、時間復雜度:n的平方,得走n-1趟

?

二、選擇排序

1、思路:一趟遍歷記錄最小的數,放到第一個位置; 再一趟遍歷記錄剩余列表中最小的數,繼續放置;以此類推

2、代碼:關鍵點無序區和最小數的位置

import random from timewrap import *@cal_time #這是自己寫的用于計算算法運行時間的裝飾器 def select_sort(li):for i in range(len(li) - 1):# i 表示趟數,也表示無序區開始的位置min_loc = i # 最小數的位置for j in range(i + 1, len(li) - 1):if li[j] < li[min_loc]:min_loc = jli[i], li[min_loc] = li[min_loc], li[i]li = list(range(10000)) random.shuffle(li) print(li) select_sort(li) print(li)

3、時間復雜度:n的平方

?

三、插入排序

1、思路:列表被分為有序區和無序區兩個部分。最初有序區只有一個元素。 每次從無序區選擇一個元素,插入到有序區的位置,直到無序區變空。

2、代碼:關鍵點摸到的牌和手里的牌,也就是無序區的元素怎么插入到有序區合適的位置

import random from timewrap import *@cal_time def insert_sort(li):for i in range(1, len(li)):# i 表示無序區第一個數tmp = li[i] # 摸到的牌j = i - 1 # j 指向有序區最后位置while li[j] > tmp and j >= 0:#循環終止條件: 1. li[j] <= tmp; 2. j == -1li[j+1] = li[j]j -= 1li[j+1] = tmpli = list(range(10000)) random.shuffle(li) print(li) insert_sort(li) print(li)

3、時間復雜度:n的平方

?

LOWB三人組就是以上排序,必須會默認代碼,冒泡,選擇,插入,時間復雜度都是n的平方,空間復雜度都是1

?

?

四、快速排序

1、思路:取一個元素p(第一個元素),使元素p歸位; 列表被p分成兩部分,左邊都比p小,右邊都比p大; 遞歸完成排序。

歸位的意思是左邊都比它小,右邊的都比它大

2、代碼:

import random from timewrap import * import copy import syssys.setrecursionlimit(100000)def partition(li, left, right):# ri = random.randint(left, right)# li[left], li[ri] = li[ri], li[left]tmp = li[left]while left < right:while left < right and li[right] >= tmp:right -= 1li[left] = li[right]while left < right and li[left] <= tmp:left += 1li[right] = li[left]li[left] = tmpreturn leftdef _quick_sort(li, left, right):if left < right: # 至少有兩個元素mid = partition(li, left, right)_quick_sort(li, left, mid-1)_quick_sort(li, mid+1, right)@cal_time def quick_sort(li):return _quick_sort(li, 0, len(li)-1)@cal_time def sys_sort(li):li.sort()li = list(range(10000)) random.shuffle(li)#sys_sort(li1) quick_sort(li)

》》》注意:最壞的情況就是9 8 7 6 5 4 3 2 1 這種序列,復雜度就變為n的平方

?

五、堆排序

1、樹與二叉樹

》》》樹:樹是一種數據結構 比如:目錄結構 樹是一種可以遞歸定義的數據結構

》》》樹是由n個節點組成的集合: 如果n=0,那這是一棵空樹; 如果n>0,那存在1個節點作為樹的根節點,其他節點可以分為m個集合,每個集合本身又是一棵樹

》》》幾個概念:

?

根節點、葉子節點:根就是A,葉子就是A的分支

樹的深度(高度):就是層數

樹的度:就是每個父節點的分支節點數就是度,這其中最大的就是樹的度

孩子節點/父節點

子樹

?

》》》二叉樹:樹的特殊結構,指的是所有節點的度最大為2的樹

》》》兩種特殊的二叉樹

滿二叉樹:度全為2,一個二叉樹,如果每一個層的結點數都達到最大值,則這個二叉樹就是滿二叉樹

完全二叉樹:葉節點只能出現在最下層和次下層,并且最下面一層的結點都集中在該層最左邊的若干位置的二叉樹

?

》》》二叉樹的存儲方式

鏈式

順序

父節點和左孩子節點的編號下標有什么關系? 0-1 1-3 2-5 3-7 4-9

i --> 2i+1

父節點和右孩子節點的編號下標有什么關系? 0-2 1-4 2-6 3-8 4-10

i --> 2i+2

?

》》》小結:(完全)二叉樹可以用列表來存儲,通過規律可以從父親找到孩子或從孩子找到父親。

?

2、堆排序

(1)兩個概念

大根堆:一棵完全二叉樹,滿足任一節點都比其孩子節點大

小根堆:一棵完全二叉樹,滿足任一節點都比其孩子節點小

大根堆:

小根堆:

(2)堆的向下調整性質

當根節點的左右子樹都是堆時,可以通過一次向下的調整來將其變換成一個堆。

(3)堆排序過程

》建立堆

》得到堆頂元素,為最大元素

》去掉堆頂,將堆最后一個元素放到堆頂,此時可通過一次調整重新使堆有序

》堆頂元素為第二大元素

》重復步驟3,直到堆變空

(4)代碼

from timewrap import * import randomdef _sift(li, low, high):""":param li::param low: 堆根節點的位置:param high: 堆最有一個節點的位置:return:"""i = low # 父親的位置j = 2 * i + 1 # 孩子的位置tmp = li[low] # 原省長while j <= high:if j + 1 <= high and li[j + 1] > li[j]: # 如果右孩子存在并且右孩子更大j += 1if tmp < li[j]: # 如果原省長比孩子小li[i] = li[j] # 把孩子向上移動一層i = jj = 2 * i + 1else:li[i] = tmp # 省長放到對應的位置上(干部)breakelse:li[i] = tmp # 省長放到對應的位置上(村民/葉子節點)def sift(li, low, high):""":param li::param low: 堆根節點的位置:param high: 堆最有一個節點的位置:return:"""i = low # 父親的位置j = 2 * i + 1 # 孩子的位置tmp = li[low] # 原省長while j <= high:if j + 1 <= high and li[j+1] > li[j]: # 如果右孩子存在并且右孩子更大j += 1if tmp < li[j]: # 如果原省長比孩子小li[i] = li[j] # 把孩子向上移動一層i = jj = 2 * i + 1else:breakli[i] = tmp@cal_time def heap_sort(li):n = len(li)# 1. 建堆for i in range(n//2-1, -1, -1):sift(li, i, n-1)# 2. 挨個出數for j in range(n-1, -1, -1): # j表示堆最后一個元素的位置li[0], li[j] = li[j], li[0]# 堆的大小少了一個元素 (j-1)sift(li, 0, j-1)li = list(range(10000)) random.shuffle(li) heap_sort(li) print(li)# li=[2,9,7,8,5,0,1,6,4,3] # sift(li, 0, len(li)-1) # print(li)

(5)內置模塊

優先隊列:一些元素的集合,POP操作每次執行都會從優先隊列中彈出最大(或最小)的元素。

堆——優先隊列

Python內置模塊——heapq heapify(x) heappush(heap, item) heappop(heap)

利用heapq模塊實現堆排序:

def heapsort(li): h = [] for value in li: heappush(h, value) return [heappop(h) for i in range(len(h))]

?

六、歸并排序

假設現在的列表分兩段有序,如何將其合成為一個有序列表,這種操作稱為一次歸并

import random from timewrap import * import copy import sysdef merge(li, low, mid, high):i = lowj = mid + 1ltmp = []while i <= mid and j <= high:if li[i] < li[j]:ltmp.append(li[i])i += 1else:ltmp.append(li[j])j += 1while i <= mid:ltmp.append(li[i])i += 1while j <= high:ltmp.append(li[j])j += 1li[low:high+1] = ltmpdef _merge_sort(li, low, high):if low < high: # 至少兩個元素mid = (low + high) // 2_merge_sort(li, low, mid)_merge_sort(li, mid+1, high)merge(li, low, mid, high)print(li[low:high+1])def merge_sort(li):return _merge_sort(li, 0, len(li)-1)li = list(range(16)) random.shuffle(li) print(li) merge_sort(li)print(li)

?

?

?

NB三人組:快速,堆,歸并

小結:

》三種排序算法的時間復雜度都是O(nlogn)

》一般情況下,就運行時間而言: 快速排序 < 歸并排序 < 堆排序

》三種排序算法的缺點:

快速排序:極端情況下排序效率低

歸并排序:需要額外的內存開銷

堆排序:在快的排序算法中相對較慢

?

?

?

七、希爾排序

希爾排序是一種分組插入排序算法。

首先取一個整數d1=n/2,將元素分為d1個組,每組相鄰量元素之間距離為d1,在各組內進行直接插入排序;

取第二個整數d2=d1/2,重復上述分組排序過程,直到di=1,即所有元素在同一組內進行直接插入排序。

希爾排序每趟并不使某些元素有序,而是使整體數據越來越接近有序;最后一趟排序使得所有數據有序。

def insert_sort(li):for i in range(1, len(li)):# i 表示無序區第一個數tmp = li[i] # 摸到的牌j = i - 1 # j 指向有序區最后位置while li[j] > tmp and j >= 0:#循環終止條件: 1. li[j] <= tmp; 2. j == -1li[j+1] = li[j]j -= 1li[j+1] = tmpdef shell_sort(li):d = len(li) // 2while d > 0:for i in range(d, len(li)):tmp = li[i]j = i - dwhile li[j] > tmp and j >= 0:li[j+d] = li[j]j -= dli[j+d] = tmpd = d >> 1

?

八、計數排序

# 0 0 1 1 2 4 3 3 1 4 5 5 import random import copy from timewrap import *@cal_time def count_sort(li, max_num = 100):count = [0 for i in range(max_num+1)]for num in li:count[num]+=1li.clear()for i, val in enumerate(count):for _ in range(val):li.append(i)@cal_time def sys_sort(li):li.sort()li = [random.randint(0,100) for i in range(100000)] li1 = copy.deepcopy(li) count_sort(li) sys_sort(li1)

?

轉載于:https://www.cnblogs.com/wanghl1011/articles/8400665.html

總結

以上是生活随笔為你收集整理的2月1日学习内容整理:算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。