天天看點

floyd算法_常見算法總結

複雜度分類
floyd算法_常見算法總結

無需額外記憶體的基礎交換函數

void swap(int& temp1, int& temp2)
{
    temp1 = temp1 ^ temp2;
    temp2 = temp1 ^ temp2;
    temp1 = temp1 ^ temp2;
}
           

1. 冒泡排序

void bubbleSort(int array[], int len) 
{
    // 需要循環比較 len-1 輪ß
    for (int i = 0; i<len-1; i++) 
    {
        // 每論比較都隻需要len-1-i個,i是輪數,也是已排序的數字個數。
        for (int j = 0; j < len -1 -i; j++) 
        {
            if (array[j] > array[j+1])
            {
                swap(array[j], array[i]);
            }
        }
    }
}
           

選擇排序

void selectSort(int array[], int len) {
    int minIndex;
    // 需要選擇 len-1 輪
    for (int i = 0; i < len - 1; i++) { 
        // 初始化每輪最小值下标,取第一位
        minIndex = i;   
        // 從未排序位置,開始找最小數
        for (int j = i + 1; j < len; j++) {  
            if ( array[j] < array[minIndex] ) {  
                // 儲存最小數下标,循環結束後交換。 
                minIndex = j;                       
            }
        }
        swap(array[i], array[minIndex]);
    }
}
           

插入排序

// 類似鬥地主疊排,預設第一個已經排好,待插入的值與前面的比較,若滿足要求則插入。
void insertSort(int array[], int len)
{
    int index, current;
    // 預設第一個數有序,從第二個數開始插入。
    for (int i = 1; i < len; i++) {
        index = i - 1;      // 已排序數組用于比較的下标
        current = array[i];     // 帶插入的數值
        // 向前尋找插入位置,
        while (index >= 0 && array[index] > current) {
            // 不滿足插入條件的時候,需要将比較過的數後移
            array[index + 1] = array[index];
            // 代比較的位置前移
            index--;
        }
        // 找到插入位置,插入
        array[index + 1] = current;
    }
}
           

希爾排序

// 分組排序思想
void  shellSort(int array[], int len)
{
    // 定義分組間隔,可以手動輸入。
    int gap = 1;
    while (gap < len / 3) { 
        gap = gap * 3 + 1;              
    }

    // gap不斷下降成為1,進行多次間隔不同的直接插入排序。
    for ( ; gap > 0; gap = floor(gap / 3 ) ) {
        // 同插入排序
        int index, current; 
        // 從間隔長度開始,每個數都需要與之前的數比較,插入,隻是間隔不為1.
        for (int i = gap; i < len; i++) {
            current = array[i];
            index = i - gap;
            // 注意取值範圍
            while (index >= 0 && array[index] > current) {
                array[index + gap] = array[index];
                index = index - gap;
            }
            array[index + gap] = current;
        }
    }

}
           

歸并排序

// 空間換時間的排序算法,采用了分而治之的思想。
void merge(int array[], int start, int middle, int end) {
    int len1 = middle - start + 1;
    int len2 = end - middle;
    int i, j;
    // 定義中間變量
    int *arr1 = new int[len1 + 1];
    int *arr2 = new int[len2 + 1];

    // 賦初值
    for (i = 0; i < len1; i++)
    {
        *(arr1 + i) = array[start + i];
    }
    for (j = 0; j < len2; j++)
    {
        *(arr2 + j) = array[middle + j + 1];
    }
    // 設定哨兵
    arr1[len1] = 10000;
    arr2[len2] = 10000;

    // 從最前面周遊
    i = 0;
    j = 0;
    for (int k = start; k <= end; k++)
    {
        if (arr1[i] < arr2[j])
        {
            array[k] = arr1[i];
            i++;
        }
        else
        {
            array[k] = arr2[j];
            j++;
        }
    }

    delete arr1;
    delete arr2;
}

// 拆分比較
void mergeSort(int array[], int start, int end)
{
    int middle = (end + start) / 2;
    if (start < end) {
        // 拆分左邊部分
        mergeSort(array, start, middle); 
        // 拆分右邊部分
        mergeSort(array, middle + 1, end);
        // 合并
        merge(array, start, middle, end);
    }

}
           

快速排序

void quickSort(int array[], int left, int right)
{

    if (left < right) {
        int base = array[left];
        int indexL = left;
        int indexR = right;
        while (indexR > indexL)
        {
            // 右振蕩
            while (indexR > indexL && array[indexR] >= base)
            {
                indexR--;
            }
            // 確定不是因為 indexR <= indexL 結束。 
            if(indexR > indexL)
                array[indexL++] = array[indexR];

            // 左振蕩
            while (indexR > indexL  && array[indexL] < base)
            {
                indexL++;
            }
            // 確定不是因為 indexR <= indexL 結束。 
            if (indexR > indexL)
                array[indexR--] = array[indexL];
        }

        // 計算完後 indexR = indexL = 最中間的下标 
        array[indexR] = base;

        // 遞歸
        quickSort(array, left, indexR - 1);
        quickSort(array, indexR + 1, right);
    }

}
           

堆排序

void adjustHeap(int array[], int len)
{
    int maxIndex, rootIndex, subLeftIndex, subRightIndex;
    // 從1/2節點處開始調整。
    for (int i = len / 2; i > 0; i--){
        // 計算真實下标
        rootIndex = i - 1;
        subLeftIndex = 2 * i -1;  
        subRightIndex = 2 * i;
        maxIndex = rootIndex;
        if (array[maxIndex] < array[subLeftIndex])
            maxIndex = subLeftIndex;
        // 右子節點需要判斷是否越界
        if ( subRightIndex< len && array[maxIndex] < array[subRightIndex])
            maxIndex = subRightIndex;
        // 根節點與最大節點交換
        if( maxIndex != rootIndex)
            swap(array[rootIndex], array[maxIndex]);
    }
}

void heapSort(int array[], int len)
{
    for (int i = 0; i < len - 1 ; i++) {
        adjustHeap(array, len - i);
        // 将最大值,移動到最後
        swap(array[0], array[len - i - 1]);
    }

}
           

計數排序

void countSort(int array[], int len)
{

    int minValue = array[0];
    int maxValue = array[0];
    // 獲得最小最大值,确定排序邊界
    for (int i = 1; i < len; i++) {
        if (array[i] < minValue)
            minValue = array[i];
        if (array[i] > maxValue)
            maxValue = array[i];
    }

    int countLen = maxValue - minValue + 1;
    int * countArray = new int[countLen];
    // 清0
    for (int i = 0; i < countLen; i++) {
        countArray[i] = 0;
    }
    // 計算數目
    for (int i = 0; i < len; i++) { 
        countArray[array[i] - minValue] ++;
    }

    // 排序
    int j = 0;
    for (int i = 0; i < countLen; i++) {
        while ( countArray[i] != 0 )
        {
            array[j++] = i + minValue;
            countArray[i]--;
        }
    }

    delete countArray;
}
           

其他推薦算法:

必知的資料結構

1. 連結清單
2. 樹
3. 最小堆,最大堆
4. 棧
5. 隊列
6. Hash結構與基礎算法
           

圖相關:

  • 圖的存儲: 鄰接矩陣(稠密網),鄰接表(連結清單,稀疏圖),圖的表示反而是難點
  • 圖的周遊算法

1 深度優先周遊算法:遞歸算法 VS 非遞歸算法

2 廣度優先周遊算法

圖的周遊 - Matrix海子 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結
  • 最短路徑算法

    單源最短路徑: Dijkstra算法, 核心:最優子結構性質 O(n^2))

Dijkstra算法(單源最短路徑) - Matrix海子 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結

多源最短路徑: 1.多次調用Dijkstra算法 (O(n^3)) 2.Floyd算法

Floyd算法(二)之 C++詳解 - 如果天空不死 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結
  • 最小生成樹算法

    Prim算法: 将頂點歸并,與邊數無關,适于稠密網。

Prim算法(一)之 C語言詳解 - 如果天空不死 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結

Kruskal算法: 将邊歸并,适于求稀疏網的最小生成樹。

Kruskal算法​www.cnblogs.com

floyd算法_常見算法總結

樹相關:

  • 二叉樹

二叉查找樹(一)之 圖文解析 和 C語言的實作​www.cnblogs.com

floyd算法_常見算法總結
  • 平衡二叉樹,算法非重點,但必須知道其定義

AVL樹(一)之 圖文解析 和 C語言的實作​www.cnblogs.com

floyd算法_常見算法總結
  • 紅黑樹,是一種非嚴格的AVL數,出自算法導論,在Linux中被實作,以提高資料的查找效率。

紅黑樹(一)之 原理和算法詳細介紹 - 如果天空不死 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結
  • B樹,B+樹。

    首先說明一個概念,如果看到文章提到B-樹,一般就是指的B數,而B+樹是B樹的一種變形。

    B樹結構使得一個節點上可以儲存多個資料,提高了對于運作速度慢的外部存儲的通路能力,同時緩解了大量資料下,樹的深度過深的問題。是為了儲存設備或者磁盤而設計的一種平衡查找樹。常見于資料庫,檔案系統中(B+樹更适用于檔案系統)。

B樹族​www.cnblogs.com

  • 哈夫曼樹

哈夫曼樹(一)之 C語言詳解 - 如果天空不死 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結

字元串算法:

  • 暴力比較算法(BP算法):
  • KMP算法:

(原創)詳解KMP算法 - 孤~影 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結

這裡我印象最深刻的一句話就是:“我不能說你錯,隻能說你不對”。是以,不是行業現狀中的最優解的解,不是真的解。

斐波那契數列

青蛙跳台階問題,可以參考劍指Offer中的幾個變形。

大數計算算法

數字轉字元串計算。

+,-: 逆序計算
           

布隆過濾器

大資料中,緩解記憶體不夠用的算法,但存在一定的誤判率。

布隆過濾器 - Matrix海子 - 部落格園​www.cnblogs.com

floyd算法_常見算法總結

平方根 --- 二分法和牛頓法

平方根算法​www.cnblogs.com

top K 問題

可以刷一下劍指Offer,重點學習最大最小堆的應用。

算法必學:經典的 Top K 問題​www.jianshu.com

floyd算法_常見算法總結

神秘算法————平方根倒數速算法

神秘數字:0x5f3759df,浮點數在計算機中的表示,數學近似等,該算法肯定不會被面試考到,但是如此神一般的算法,建議大家自行Google學習,以下貼代碼。

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck? 
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//    y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}
           

劍指Offer 第二版

常見資料結構以及算法的應用,66道題。

1. 通過讀課本了解算法原理。

2. 通過牛客網刷題提升代碼能力。
           

LeetCode

分為:難,中等,容易三種級别的題目,适合希望在算法能有更多進步的人進一步刷題,我沒怎麼刷過,不過多的評價。

常見算法思想

五大常用算法之一:分治算法 - 紅臉書生 - 部落格園​www.cnblogs.com 五大常用算法之二:動态規劃算法 - 紅臉書生 - 部落格園​www.cnblogs.com 五大常用算法之三:貪心算法 - 紅臉書生 - 部落格園​www.cnblogs.com 五大常用算法之四:回溯法 - 紅臉書生 - 部落格園​www.cnblogs.com