【八大排序算法】插入排序、希爾排序、選擇排序、堆排序、冒泡排序、快速排序、歸并排序、計數排序

文章目錄

  • 一、排序的相關概念
  • 二、排序類型
  • 三、排序算法實現
    • 插入排序
      • 1.直接插入排序
      • 2.希爾排序
    • 選擇排序
      • 3.簡單選擇排序
      • 4.堆排序
    • 交換排序
      • 5.冒泡排序
      • 6.快速排序
        • 遞歸實現
        • 非遞歸實現
    • 7.歸并排序
      • 遞歸實現
      • 非遞歸實現
    • 8.計數排序
  • 四、總結

一、排序的相關概念

排序:根據數據中關鍵字的大小,來進行升序或者降序排列。比如按照英文字母順序排序,按照商品價格或者銷量來排序等。

穩定性:如果存在兩個或多個相同的數據,若經過排序后,它們的相對次序保持不變,則稱這種排序算法是穩定的;否則就是不穩定的。

內部排序:數據元素全部放在內存中的排序。

外部排序:數據元素太多,不能同時放在內存中,根據排序過程的要求不能在內外存之間移動數據的排序。

本篇介紹的是內部排序

二、排序類型

在這里插入圖片描述

三、排序算法實現

可用各種排序算法跑這個OJ—>排序OJ鏈接

插入排序

1.直接插入排序

基本思想:將待排序的元素逐個插入到一個已經排好序的有序序列中,直到所有元素插入完為止,得到一個新的有序序列 。

初始序列是無序的,怎么將待排元素插入有序序列呢?

第一個元素本身可以看做一個有序序列,所以從第二個元素開始,從后往前遍歷比較,插入前面已經排好的有序序列中。將大于該元素的所有元素位置向后挪動一位,在比較的過程中邊比較邊挪動。

以升序為例
在這里插入圖片描述

可以發現,假設待排序的序列長度為n,插入排序需要進行n-1趟。

時間復雜度:O(N2)趟數為n-1,每趟待排序元素需要在前面的有序序列中從后往前比較挪動數據。

最好情況:O(N);有序,判斷一次直接break出來,總共n-1趟,每趟不用挪動數據,量級為。
最壞情況:O(N2);逆序,每趟都頭插,次數1+2+3+…N-1,所以時間復雜度量級是。

元素集合越接近有序,直接插入排序算法的效率越高。

空間復雜度:O(1)。 沒有使用額外空間。

穩定性:穩定。 如果是大于等于某個位置的元素,則在其后面插入,相對位置不變。

//插入排序 穩定 時間復雜度O(N^2) 空間復雜度O(1)
void InsertSort(int* a, int n)
{for (int i = 1; i < n; i++){int end = i - 1;//有序序列的末尾位置int x = a[i];//待排序元素//將x插入到[0, end]區間中,并保持有序while (end >= 0){if (x < a[end]){a[end + 1] = a[end];//往后挪一個位置end--;}else{break;}}//while循環結束有兩種情況://1.end = -1也即x比前面所有數都小;//2.x >= a[end] 這兩種都是在end后面插入a[end + 1] = x;}
}

2.希爾排序

希爾排序法又稱縮小增量法。是對插入排序的優化方案,效率比直接插入排序要高。

基本思想:將待排序列以間隔gap劃分為gap個不同的組,對同組內的元素進行直接插入排序,然后縮小gap,重復上述分組和排序,直到gap=1,也就是直接插入排序,就會得到一個有序序列。

在這里插入圖片描述

gap取多少合適?

gap初始值一般取n / 2,每趟排序完gap / 2,直到gap=1,即直接插入排序,此時序列接近有序,直接插入效率O(N)。gap也可以每次 ÷ 3,只要保證gap最后一次能取到1。

排升序,gap越大,大的數更快到后面,小的數更快到前面,但是越不接近有序;gap越小,越接近有序,gap=1時,就是直接插入排序。

時間復雜度:平均為O(N1.3)希爾排序的時間復雜度至今還沒有精確的分析結果,經過大量的實驗推出,n在某個特定范圍內,希爾排序的比較和移動次數約為N1.3

空間復雜度:O(1)。 沒有使用額外空間。

穩定性:不穩定。 希爾排序是分組排序的,且每個組內的數據不連續,無法保證相同數據的相對位置不被改變。比如上圖中紫色4和橙色4在第一趟排序后,相對位置就發生了變化,所以希爾排序是不穩定排序。

//希爾排序 不穩定  效率比直接插入排序高 
void ShellSort(int* a, int n)
{//gap > 1 預排序//gap == 1 直接插入排序int gap = n;while (gap > 1){//gap = gap / 3 + 1;//也可以,除3后別忘了+1,否則gap為2時除3結果為0gap /= 2;for (int i = gap; i < n; i++){int end = i - gap;int tmp = a[i];//將x插入到[0, end]區間中,保持有序while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];//往后挪一個位置,方便x插入end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

選擇排序

3.簡單選擇排序

基本思想:每次從剩下的待排序列中標記最小(最大)值的下標位置,遍歷完后存放到未排序列的起始位置(也是已排好的序列的下一個位置),直到全部待排序的數據排完。

實際上,我們每趟可以選出兩個值,一個最大值,一個最小值,然后分別與序列的起始和末尾元素交換。這樣排序的趟數可以減少一半,但比較和交換的次數會×2,整體效率沒有太大變化。
在這里插入圖片描述
時間復雜度:O(N2)一共選擇n趟,每趟與n-1個數進行比較;如果是每次同時選出最大值和最小值,一共需要n/2趟,每趟比較2×(n-1)次,量級都是O(N2)。

選擇排序沒有最好情況和最壞情況,不管有序還是逆序,都需要進行O(N2)次比較。所以選擇排序的性能很差。因為不管是有序還是逆序,選擇排序的效率都是最差的O(N2)。

空間復雜度:O(1)。 沒有使用額外空間。

穩定性:不穩定。 因為每次是將待排序列的起始位置與序列中最小值(或最大值)進行交換,只保證了最小值的穩定性,但起始位置的穩定性可能會被破壞。(如果同時找出最大值并交換,例如圖中一樣,最小值表示的元素的穩定性也可能會被破壞,比如上圖中第二趟排序4的相對位置就發生了變化)

//選擇排序 不穩定 時間復雜度O(N^2) 空間復雜度O(1)
void SelectSort(int* a, int n)
{int l = 0, r = n - 1;while (l < r){int minPos = l, maxPos = l;//標記最小值和最大值的下標for (int i = l + 1; i <= r; i++){if (a[i] < a[minPos])minPos = i;if (a[i] > a[maxPos])maxPos = i;}//C語言沒有庫函數,交換函數需要自己寫Swap(&a[l], &a[minPos]);//如果最大值maxPos與左邊界l重合,在l與minPos交換后,最大值轉移到了minPos位置if (l == maxPos)maxPos = minPos;Swap(&a[r], &a[maxPos]);l++;r--;}
}

4.堆排序

堆排序在數據結構——堆中已經詳細講過了,這里可能講的沒有那么細致。想詳細了解堆的具體原理和使用可以看看這篇博客。

堆排序是利用數據結構堆(Heap)的特性所設計的一種算法,是選擇排序的一種。它是通過堆來選擇數據。

基本思想: 依次將將堆頂的數據與堆尾的數據交換,然后向下調整成堆,重復上述步驟直到數據完全有序。比如一個大根堆,我們取出堆頂元素(最大數)與最后一個數交換,交換后的最大數不看作在堆里面,那么堆頂元素的左右子樹仍滿足堆的性質,堆的結構并沒有被破壞,然后堆頂元素向下調整成堆,即可選出第二大的數,以此類推到最后一個元素,就可以成功實現堆排序了。

升序:建大堆
降序:建小堆

時間復雜度:O(N*logN)向下調整建堆的時間復雜度為O(N)(過程在數據結構堆篇),堆頂元素一共進行n-1次交換,每次交換后向下調整為O(logN),所以最大量級是O(N*logN)。

堆排序也沒有最好情況和最壞情況,堆排序不受初始序列順序的影響,有序或者逆序時間復雜度都是O(N*logN)。

空間復雜度:O(1)。 沒有使用額外空間。

穩定性:不穩定。 建堆時數據的相對順序就可能被改變,在選數時堆頂與堆尾數據交換也可能導致穩定性被破壞。

//C語言沒有庫函數,交換函數需要自己寫
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
//堆排序向下調整(排升序建大堆)
void AdjustDown(int* a, int n, int parent)
{int child = 2 * parent + 1;//先賦值左孩子while (child < n){//右孩子存在且右孩子比左孩子更大if (child + 1 < n && a[child + 1] > a[child]){child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}//堆排序 不穩定 時間復雜度O(N*logN)
void HeapSort(int* a, int n)
{//倒著調整,從最后一個非葉子結點開始向下調整建堆 效率O(N)for (int i = (n - 2) / 2; i >= 0; i--){AdjustDown(a, n, i);}//O(N*logN)int end = n - 1;//堆的有效長度while (end > 0){Swap(&a[0], &a[end]);//堆頂與堆尾元素交換AdjustDown(a, end, 0);//堆頂再向下調整,范圍[1,end]end--;}
}

交換排序

5.冒泡排序

基本思想:從前往后遍歷序列,每相鄰兩個數比較大小,前一個比后一個大就交換,直到將最大元素交換到末尾位置,繼續從前往后遍歷,重復上述操作,直到所有元素有序。

冒泡排序和選擇排序一樣都非常容易理解,也不上圖演示了(畫圖太費時間),一切都在代碼中。

時間復雜度:O(N2)一共n趟,每趟比較交換次數遞減,總共比較1+2+3+…+n-1次,量級為O(N2)。

最好情況:O(N) ;有序情況下只用進行一趟比較(flag標記),就退出循環。
最壞情況:O(N2);每趟都進行交換。

空間復雜度:O(1)。 沒有使用額外空間。

穩定性:穩定。 前后兩個元素相同則不用交換,相對位置沒有改變。

//冒泡(交換)排序 穩定 時間復雜度O(N^2)
void BubbleSort(int* a, int n)
{for (int i = 0; i < n; i++){bool flag = false;//判斷是否交換過for (int j = 0; j < n - 1 - i; j++){if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);flag = true;}}if (flag == false)//一趟下來沒有交換說明已經有序{break;}}
}

6.快速排序

快速排序整體的綜合性能和使用場景都是比較好的,這也是大多數人使用快排的原因。
快速排序算法應該算是排序算法中的重點了。

快速排序是一種二叉樹結構的交換排序方法。

基本思想:任取待排序的序列中的某元素作為key值,按照key值將待排序集合分割成兩個子序列,左子序列中所有元素均小于key,右子序列中所有元素均大于key,然后最左右子序列重復該過程,直到所有元素有序。

快速排序的過程與二叉樹的前序遍歷相似,因此可以采用遞歸的方式。但在某些極端情況下可能會出現棧溢出,因此有時也會使用非遞歸的形式實現。

遞歸實現

快速排序的細節問題有很多,區間問題、key值的選取、交換細節等等,這些細節不注意很容易會造成超時(無限循環)、排序出錯等問題。因此也衍生了很多版本:hoare版本、挖坑法、前后指針版本等,還有一些優化key值選取的方法例如“三數取中法”,這些代碼有些地方不是那么容易理解,并且冗長,有的版本在排序OJ會跑不過。

上述所有版本這里不再總結,其他博主有更詳細的介紹。下面介紹一種AcWing上大佬總結的快排模板,非常厲害,代碼簡潔易懂,在排序OJ也能跑過。

思路

我們選取一個key值,使用雙指針ij分別從區間左右兩邊往中間走,將>=key的數換到右區間,將<=key的數換到左邊界,當i>=j時,j(或i)的左邊區間都<=key,右邊區間都>=key,然后再遞歸左區間和右區間按照此方法排序。

void QuickSort(int* a, int l, int r)
{//遞歸的終止情況if (l >= r) return;//最好不選左右端點作key,否則有序或逆序情況下效率很差int key = a[(l + r) / 2];int i = l - 1, j = r + 1;while (i < j){while (a[++i] < key);//左邊找大while (a[--j] > key);//右邊找小if (i < j)Swap(&a[i], &a[j]);}QuickSort(a, l, j);QuickSort(a, j + 1 , r);
}

下面需要證明兩個問題:無限循環和無限遞歸的邊界問題。

在這里插入圖片描述

key的取值會影響后面遞歸的區間,下面四種寫法都是正確的。

上面代碼是右邊第一種寫法。

在這里插入圖片描述

我們先分析遞歸區間的取法

在這里插入圖片描述

再來分析key的取法
雖然下面這兩種區間劃分都可以,但具體哪種要看key的取法:

在這里插入圖片描述

這四種寫法取一種即可

但建議寫左邊兩種,因為key取到邊界的話,有序或逆序情況下效率很差。
在這里插入圖片描述總結

1.key取a[l]或者a[(l+r)/2]遞歸區間為QuickSort(a,l,j)QuickSort(a,j+1,r);
2.key取a[r]或者a[(l+r+1)/2]遞歸區間為QuickSort(a,l,i-1)QuickSort(a,i,r);
3.key不建議取邊界,最好從中間選取,否則有序或者逆序情況下,效率很差。

在這里插入圖片描述
時間復雜度:O(N*logN)時間復雜度=每層的操作次數×樹的深度=nlogn

最好情況:O(N*logN) ;有序,只判斷不進行交換。
最壞情況:O(N2);并非逆序,每次劃分,key都是最小(最大)的。

空間復雜度:O(logN)。 遞歸的棧幀開銷。

穩定性:不穩定。 快排前后交換數據會導致相對位置 發生改變。

非遞歸實現

快排的遞歸過程是將大區間劃分為兩個小區間,這兩個小區間再分別劃分成兩個更小區間,直到遞歸到邊界條件,結束然后回退到上一層。

所以快排的非遞歸可以借助隊列或者的方式來實現。

隊列的話可以參考二叉樹的層序遍歷。

思路:先取隊頭區間排序處理,再將隊頭的左右子區間入隊,再取隊頭區間,再將左右區間入隊,重復直到隊列為空。

下面介紹快排非遞歸采用棧的實現方法。類似二叉樹的前序遍歷。

思路:每次取棧頂區間進行快排的單趟排序,然后將該區間的左右子區間入棧,再取棧頂區間處理,重復直到棧空。

//非遞歸快排
void QuickSortNonRe(int* a, int left, int right)
{ST st;STInit(&st);STPush(&st, left);//左端點入棧STPush(&st, right);//右端點入棧while (!STEmpty(&st)){//注意順序,和入棧順序相反int r = STTop(&st);STPop(&st);int l = STTop(&st);STPop(&st);//單趟排序int key = a[(l + r) / 2];int i = l - 1, j = r + 1;while (i < j){while (a[++i] < key);//左邊找大while (a[--j] > key);//右邊找小if (i < j)Swap(&a[i], &a[j]);}//分為[l, j]和[j + 1, r]區間if (l < j)//l == j 說明該區間只有一個值,無需入棧{STPush(&st, l);STPush(&st, j);}if (j + 1 < r){STPush(&st, j + 1);STPush(&st, r);}}STDestroy(&st);
}

7.歸并排序

遞歸實現

歸并排序的遞歸實現屬于分治算法,分治算法都有三步:

1.分成子問題;
2.遞歸處理子問題;
3.子問題合并。

歸并排序是不斷將區間分解成子區間,一分二,二分四…,直到每個區間只有一個元素,然后開始向上合并有序區間,分而治之。實現過程與二叉樹的后序遍歷類似,先遞歸再合并處理元素。

在這里插入圖片描述

時間復雜度:O(N*logN)與快排一樣,時間復雜度=每層的操作次數×樹的深度=nlogn

歸并排序不受初始數據順序的影響,不管有序還是無序,時間復雜度都是O(N*logN)。因為每次都遞歸到最小區間開始合并區間。

空間復雜度:O(N)。 需要額外開辟數組空間。

穩定性:穩定。 歸并過程左右區間有兩個數相同時,先從左區間取數據。

//歸并排序 穩定 時間復雜度O(N*logN) 空間復雜度O(N)
void Merge(int* a, int l, int r, int* tmp)//tmp臨時存放合并好的數據
{//遞歸的終止情況if (l >= r)return;//第一步:分成子問題int mid = (l + r) / 2;//第二步:遞歸處理子問題Merge(a, l, mid, tmp);Merge(a, mid + 1, r, tmp);//第三步:合并子問題;將[l, mid]和[mid + 1, r]區間歸并int i = l, j = mid + 1;int k = 0;while (i <= mid && j <= r){if (a[i] <= a[j])//可見穩定性tmp[k++] = a[i++];elsetmp[k++] = a[j++];}//左區間剩余while (i <= mid)tmp[k++] = a[i++];//右區間剩余while (j <= r)tmp[k++] = a[j++];//將歸并好的tmp數組的內容交給數組a的[l,r]區間memcpy(a + l, tmp, sizeof(int) * k);// k == r - l + 1//i = l, k = 0;//while (i <= r)//	a[i++] = tmp[k++];
}//歸并排序
void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (NULL == tmp){perror("malloc");return;}Merge(a, 0, n - 1, tmp);free(tmp);
}

非遞歸實現

歸并排序的非遞歸是可以直接從最小區間開始合并的,所以省去了遞歸劃分子區間的過程,使用一個gap值來實現區間的跨度,gap從1開始每循環一次乘2,;區間的跨度從1到2,再到4…以2的指數增長。如果數據個數不滿足2n個,則左右區間可能會發生越界,這就是需要處理的細節問題。

修正區間邊界:(左區間的左端點一定不會越界,不用考慮)當左區間的右端點越界,或者右區間的左端點越界,則后面的元素(有序)不再合并,等待下一輪。
否則如果右區間的右端點越界,則使右端點=n-1,進行修正。
在這里插入圖片描述

//非遞歸
void MergeSortNonRe(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (NULL == tmp){perror("malloc");return;}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){int left1 = i, right1 = i + gap - 1;int left2 = i + gap, right2 = i + 2 * gap - 1;if (right1 >= n || left2 >= n)//不再歸并{break;}if (right2 >= n)//第二區間右端點越界{right2 = n - 1;}//合并子區間int k = i;while (left1 <= right1 && left2 <= right2){if (a[left1] <= a[left2])tmp[k++] = a[left1++];elsetmp[k++] = a[left2++];}while (left1 <= right1)tmp[k++] = a[left1++];while (left2 <= right2)tmp[k++] = a[left2++];//合并一次,拷貝一次memcpy(a + i, tmp + i, sizeof(int) * (right2 - i));}gap *= 2;}free(tmp);
}

8.計數排序

前面七種排序算法都屬于比較排序,而計數排序是一種非比較排序。并不是通過兩個數相比來進行排序的。

計數排序本質就是用數組存儲一個映射關系把它的位置保存起來,然后再遍歷原先的數組從位置數組中把它拿出來進行排序。

基本思想:統計相同元素出現次數,然后根據統計的結果將序列回收到原來的序列中。

遍歷一邊序列,元素每出現一次,就將以該元素為下標的數組的值+1,類似哈希表。

但是,如果序列中只有幾個數,但這幾個數并不算很小,例如{100, 100,101};我們就需要開辟101個空間來存儲,會造成空間的大量浪費。所以對此可以進行優化,利用序列中最大值和最小值的差值來開辟空間。這樣只需開辟2個整型空間即可。

時間復雜度:O(N+range)只需要遍歷幾遍數組。

歸并排序不受初始數據順序的影響,不管有序還是無序,時間復雜度都是O(N*logN)。因為每次都遞歸到最小區間開始合并區間。

空間復雜度:O(range)。 需要額外開辟空間。range=最大值-最小值+1

穩定性:不穩定。 沒有進行數據交換,本質上是修改了原始數據。

計數排序在數據范圍集中時,效率很高,但是適用范圍及場景有限。

//計數排序 時間復雜度O(N+range) 空間復雜度O(range)
void CountSort(int* a, int n)
{//第一遍,找出最大值和最小值int maxVal = a[0], minVal = a[0];for (int i = 1; i < n; i++){if (a[i] > maxVal)maxVal = a[i];if (a[i] < minVal)minVal = a[i];}//開辟數組空間int range = maxVal - minVal + 1;//calloc自動初始化為0int* count = (int*)calloc(sizeof(int), range);if (NULL == count){perror("malloc");return;}//第二遍,計數for (int i = 0; i < n; i++)count[a[i] - minVal]++;//排序int i = 0;for (int x = minVal; x <= maxVal; x++){while (count[x - minVal]-- > 0)a[i++] = x;}free(count);
}

四、總結

對這八種算法進行性能測試,隨機生成10萬個數據,統計排序所消耗時間如下:

在這里插入圖片描述可以看出,三種基本排序:插入排序、選擇排序、冒泡排序所花費的時間明顯更多。它們的時間效率都是O(N2),但是它們的效率卻有明顯差別。

插入排序最快;選擇排序掃描一遍數組,只需要換兩次位置;而冒泡排序需要不斷交換相鄰的元素。因此,選擇排序在大型數據集中的性能比冒泡排序更好。

剩下五種排序算法跟它們不是一個量級,數據量太小看不出明顯差別,我們單獨用100萬個數據來測試這五種排序算法的性能。

在這里插入圖片描述
計數排序最快,但是計數排序的使用場景也有限,本質是拿空間換時間,而且當空間效率O(range)>O(nlog(n))的時候其效率反而不如基于比較的排序;所以計數排序不歸在常見的排序算法中。

剩下四種常見算法中,希爾排序、堆排序、歸并排序是相差不大的;快速排序是比較突出的,要比其余算法(除了計數排序)都快,快速排序整體的綜合性能和使用場景都是比較好的。

排序算法復雜度及穩定度分析


排序方法時間復雜度空間復雜度穩定性
平均情況最好情況最壞情況
插入排序插入排序O(n2)O(n)O(n2)O(1)穩定
希爾排序平均 O(n1.3)O(1)不穩定
選擇排序選擇排序O(n2)O(n2)O(n2)O(1)不穩定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不穩定
交換排序冒泡排序O(n2)O(n)O(n2)O(1)穩定
快速排序O(nlogn)O(nlogn)O(n2)O(nlogn)不穩定
歸并排序O(nlogn)O(nlogn)O(nlogn)O(n)穩定
計數排序O(n+range)O(n+range)O(n+range)O(range)不穩定

快速排序:一般情況時排序速度最塊,但是不穩定,當有序時,反而不好;
歸并排序:效率非常不錯,在數據規模較大的情況下,比希爾排序和堆排序要好;
堆排序:適合Tok-K問題;例:找出一千萬個數中最小的前一百個數;

算法的時間復雜度與初始序列初態無關的算法有:選擇排序、堆排序、歸并排序。

完整代碼:八大排序算法

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/11991.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/11991.shtml
英文地址,請注明出處:http://en.pswp.cn/web/11991.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WebLogic問題集

console登錄后&#xff0c;頁面顯示卡頓 解決方法&#xff1a; 將Java的配置文件JAVA_HOME\jre\lib\securetty\java.security中的 securerandom.sourcefile:/dev/random修改為 securerandom.sourcefile:/dev/./random修改后&#xff0c;重啟WLS即可。

【LAMMPS學習】八、基礎知識(6.5)PyLammps 教程

8. 基礎知識 此部分描述了如何使用 LAMMPS 為用戶和開發人員執行各種任務。術語表頁面還列出了 MD 術語&#xff0c;以及相應 LAMMPS 手冊頁的鏈接。 LAMMPS 源代碼分發的 examples 目錄中包含的示例輸入腳本以及示例腳本頁面上突出顯示的示例輸入腳本還展示了如何設置和運行各…

[JAVASE] 類和對象(二)

目錄 一. 封裝 1.1 面向對象的三大法寶 1.2 封裝的基本定義與實現 二. 包 2.1 包的定義 2.2 包的作用 2.3 包的使用 2.3.1 導入類 2.3.2 導入靜態方法 三. static 關鍵字 (重要) 3.1 static 的使用 (代碼例子) 3.1.1 3.1.2 3.1.3 3.1.4 四. 總結 一. 封裝 1.1 面向對象…

推薦網站(9)pixabay免費可商用的圖片、視頻、插畫、矢量圖、音樂

今天推薦一款可以免費可商用的圖片、視頻、插畫、矢量圖、音樂的資源網站&#xff0c;這里面的所以東西都是免費的&#xff0c;并且可以商用。對那些做視頻剪輯的人來說幫助非常大。它里面的資源非常的豐富&#xff0c;質量也高。 比如搜索下雨 鏈接直達&#xff1a;https://pi…

遇到Docker容器無法上網的問題時如何排查

當遇到Docker容器無法上網的問題時&#xff0c;可以通過以下步驟排查和解決&#xff1a; 檢查Docker容器的網絡模式&#xff1a; 確認容器的網絡模式是否符合您的需求&#xff0c;使用 docker inspect <container_id> 查看網絡配置。 檢查Docker守護進程和容器的日志&am…

如何安裝在系統中安裝make命令

文章目錄 WindowsMacUbuntuCentOS/Red Hat make是系統比較基礎的命令&#xff0c;一般會自己攜帶&#xff0c;如果沒有就手動安裝一下吧。 Windows 從官網下載 make.exe Make for Windows 官網首頁&#xff1a;https://www.gnu.org/software/make/ 下載地址&#xff1a;htt…

IT行業的革新力量:技術進步與未來展望

在當今時代&#xff0c;信息技術&#xff08;IT&#xff09;行業無疑是全球經濟的重要推動力之一。隨著數字化轉型的不斷深入&#xff0c;IT行業的邊界正在擴大&#xff0c;它不僅包括傳統的軟硬件開發、網絡建設和運維服務&#xff0c;還涵蓋了云計算、大數據、人工智能&#…

我希望未來十年,Java可以變成這樣的

ava&#xff0c;這位編程界的常青樹&#xff0c;自1995年問世以來&#xff0c;一直是全球開發者的寵兒。隨著技術的飛速發展&#xff0c;Java也在持續地自我革新。接下來&#xff0c;讓我們來聊聊&#xff0c;未來十年Java可能會有哪些令人興奮的變化。&#xff08;最重要的一點…

常用的啟發式算法:探索問題解決的智慧之道

啟發式算法是一種通過啟發式信息來引導搜索的算法&#xff0c;常用于解決那些在合理時間內難以找到最優解的問題。本文將介紹幾種常用的啟發式算法&#xff0c;包括貪心算法、遺傳算法和模擬退火算法&#xff0c;并提供Java代碼實現及測試&#xff0c;幫助讀者深入理解這些算法…

android設計模式-單例模式

轉&#xff1a;https://www.jianshu.com/p/9c32aea34b6d 單例模式是運用最廣泛的設計模式之一&#xff0c;在應用這個模式時&#xff0c;單例模式的類必須保證只有一個實例存在。多用于整個程序只需要有一個實例&#xff0c;通常很消耗資源的類&#xff0c;比如線程池&#xf…

如何申請免費一年SSL證書

申請免費一年的SSL證書可以通過以下幾個步驟進行&#xff0c;這里以JoySSL為例&#xff0c;因為它是目前提供此類服務的流行平臺之一&#xff0c;同時也提到了寶塔面板中的TrustAsia SSL證書。請根據您的具體需求選擇合適的方式&#xff1a; 申請免費一年SSL證書&#xff1a; …

2024年為什么很多電商商家,都想涌入視頻號,究竟是什么原因?

大家好&#xff0c;我是電商糖果 對電商有了解的朋友&#xff0c;在今年肯定發現一個現象&#xff0c;那就是很多商家對視頻號比較青睞。 視頻號究竟有何魔力&#xff0c;讓越來越多的商家都想要入駐。 其實很簡單&#xff0c;它讓商家看到了市場。 視頻號背后是誰&#xf…

【Vue】Vue指令與生命周期以及組件化編碼

目錄 常用內置指令v-text與v-htmlv-text : 更新元素的 textContentv-html : 更新元素的 innerHTML注意&#xff1a;v-html有安全性問題&#xff01;&#xff01;&#xff01;&#xff01; v-once與v-prev-oncev-pre ref與v-cloakrefv-cloak 自定義指令案例定義語法配置對象中常…

兩數相加 - (LeetCode)

前言 今天無意間看到LeetCode的一道“兩數相加”的算法題&#xff0c;第一次接觸鏈表ListNode&#xff0c;ListNode結構如下&#xff1a; public class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) {this.val val;}ListNode(int val, ListNode next) {…

使用openssl生成自簽名證書

使用openssl生成自簽名證書 1. 交互式生成2. 一步生成參考 1. 交互式生成 自簽名 SSL 證書的生成涉及一個簡單的 3 步過程&#xff1a; 步驟 1&#xff1a;創建服務器私鑰 openssl genrsa -out cert.key 2048步驟 2&#xff1a;創建證書簽名請求 (CSR) openssl req -new -k…

Sectigo SSL證書申請的流程是怎樣的?

在當今數字化時代&#xff0c;網絡安全成為了一個不可忽視的問題。為了保護網站和用戶數據的安全&#xff0c;SSL證書成為了網站運營的重要組成部分。Sectigo作為全球領先的數字證書頒發機構之一&#xff0c;提供了一系列的證書解決方案來滿足不同類型網站的需求。以下是對Sect…

2024年算法建模與計算機通信國際學術會議(ICAMCC 2024)

2024年算法建模與計算機通信國際學術會議(ICAMCC 2024) 2024 International Conference on Algorithm Modeling and Computer Communication(ICAMCC 2024) 會議簡介&#xff1a; 2024年算法建模與計算機通信國際學術會議(ICAMCC 2024)將于中國南昌市盛大開幕。這次會議的目的是…

IP應用場景查詢API接口

IP應用場景查詢API接口指的是輸入IP地址&#xff0c;查詢IP應用場景信息。那么IP地址應用場景查詢接口如何對接呢&#xff1f; 首先我們找到一家有IP地址應用場景查詢API的服務商數脈API,然后注冊賬號&#xff0c;購買免費套餐 接下來就需要技術同學把IP應用場景查詢接口對接到…

數學符號大全

目錄 高數數學符號 科研論文常見數學符號極其含義 圓中間有個點代表點乘 高數數學符號 高數數學符號and數學運算符號及含義 - 知乎 科研論文常見數學符號極其含義 科研中論文常見數學符號及其含義&#xff08;科研必備&#xff0c;建議收藏&#xff09;_數學論文中的:-CSDN…

python GUI庫 EEL + VUE.js 開發環境配置 聯調

eel開發環境啟動的服務器默認端口是8000&#xff0c;如果前端界面的開發也是直接在EEL開發環境中進行&#xff0c;一切好辦。但如果前端用vue&#xff0c;則需要另外啟動專用的vue開發環境的服務器&#xff08;Vue CLI (npm run serve)默認端口是8080&#xff0c;Vite (npm run…