查找和排序的基本操做:查找排序算法大集合

重點

查找算法着重掌握:順序查找、二分查找、哈希表查找、二叉排序樹查找。算法

排序算法着重掌握:冒泡排序、插入排序、歸併排序、快速排序。數組

順序查找

算法說明

順序查找適合於存儲結構爲順序存儲或連接存儲的線性表。數據結構

算法思想

順序查找也稱爲線形查找,屬於無序查找算法。從數據結構線形表的一端開始,順序掃描,依次將掃描到的結點關鍵字與給定值k相比較,若相等則表示查找成功;若掃描結束仍沒有找到關鍵字等於k的結點,表示查找失敗。函數

算法實現

int sequenceSearch(int a[], int value, int len)
{
    int i;
    for(i=0; i<len; i++)
        if(a[i]==value)
            return i;
    return -1;
}

算法分析

查找成功時的平均查找長度爲:(假設每一個數據元素的機率相等) ASL = 1/n(1+2+3+…+n) = (n+1)/2 ;查找不成功時,須要n+1次比較,時間複雜度爲O(n);因此,順序查找的時間複雜度爲O(n)ui


二分查找

算法說明

元素必須是有序的,若是是無序的則要先進行排序操做。spa

算法思想

也稱爲是折半查找,屬於有序查找算法。用給定值k先與中間結點的關鍵字比較,中間結點把線形表分紅兩個子表,若相等則查找成功;若不相等,再根據k與該中間結點關鍵字的比較結果肯定下一步查找哪一個子表,這樣遞歸進行,直到查找到或查找結束髮現表中沒有這樣的結點。注:折半查找的前提條件是須要有序表順序存儲,對於靜態查找表,一次排序後再也不變化,折半查找能獲得不錯的效率。但對於須要頻繁執行插入或刪除操做的數據集來講,維護有序的排序會帶來不小的工做量,那就不建議使用。code

算法實現

//二分查找,常規版
int binarySearch1(int a[], int value, int len)
{
    int low, high, mid;
    low = 0;
    high = len-1;
    while(low<=high)
    {
        mid = low+(high-low)/2;    //防止溢出
        if(a[mid]==value)
            return mid;
        if(a[mid]>value)
            high = mid-1;
        if(a[mid]<value)
            low = mid+1;
    }
    return -1;
}
 
//二分查找,遞歸版
int binarySearch2(int a[], int value, int low, int high)
{
    int mid = low+(high-low)/2;
    if(a[mid]==value)
        return mid;
    if(a[mid]>value)
        return BinarySearch2(a, value, low, mid-1);
    if(a[mid]<value)
        return BinarySearch2(a, value, mid+1, high);
}

算法分析

最壞狀況下,關鍵詞比較次數爲log2(n+1),故時間複雜度爲O(log2n);blog


 

冒泡排序

算法說明

屬於交換類排序,穩定排序排序

算法思想

比較相鄰的兩個數的大小,將最大的數放在右邊,計數器i++;遞歸

繼續重複操做1,直到a[n-2]和a[n-1]比較結束,數組a中最大的值已在a[n-1];

將進行排序的數組長度n減1,重複操做1和操做2,直到n爲1,排序完畢。

算法實現

void bubbleSort(int* array, int length)
{
    for (int i = 0; i < length - 1; ++i)
    {
        //bool is_Swap=false;
        for (int j = 0; j < length - 1 - i; ++j)
        {
            if (array[j] > array[j + 1])
            {
                //is_Swap=true;
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
                /*
                交換還可以使用以下方式
                a = a + b;
                b = a - b;
                a = a - b;
                交換還可以使用以下方式
                a=a^b;
                b=b^a;
                a=a^b;
                */
            }
        }
        //if(is_Swap==false)
            //return;
    }
}

算法分析

平均時間複雜度:O(n^2)。最好的狀況:若是待排序數據序列爲正序,則一趟冒泡就可完成排序,排序的比較次數爲n-1次,且沒有移動,時間複雜度爲O(n)。要實現O(n)的複雜度,代碼裏須要加一個標誌位(Bool變量)。最壞的狀況:若是待排序數據序列爲逆序,則冒泡排序須要n-1次趟,每趟進行n-i次排序的比較和移動,即比較和移動次數均達到最大值:比較次數=n(n−1)/2=O(n^2),移動次數等於比較次數,所以最壞時間複雜度爲O(n^2)。


 

插入排序

算法說明

 屬於插入類排序,穩定排序。

算法思想

 從待排序的數組的第二個元素開始,將其與前面的數進行大小比較,尋找合適的位置並插入,直到所有元素都已插入。

算法實現

void insertSort(int* array,int length) 
{
    int i = 0, j = 0, temp = 0;
    for (i = 1; i < length; ++i) 
    {
        //若是該元素小於前面的元素,大於該元素的元素所有後移一位,
        //直到找到該元素要插入的位置並插入之。
        if (array[i] < array[i-1])
        {
            temp = array[i];
            for (j = i-1; temp < array[j] && j >= 0 ; --j) 
            {
                array[j+1] = array[j];
            }
            array[j + 1] = temp;
        }
    }
}

算法分析

 平均時間複雜度:O(n^2)。最好的狀況:當待排序記錄已經有序,這時須要比較的次數爲n-1=O(n)。最壞的狀況:若是待排序記錄爲逆序,則最多的比較次數爲n*(n-1)/2=O(n^2)


歸併排序

算法說明

 應用較廣,穩定排序。

算法思想

歸併排序是分治法的一個典型的應用,先使每一個子序列有序,再使每一個子序列間有序。將兩個有序子序列合併成一個有序表,稱爲二路歸併。 步驟:首先將有序數列一分二,二分四……直到每一個區都只有一個數據,此時每一個子序列均可看作有序序列。而後進行合併,每次合併都是有序序列在合併,

算法實現

 

void MergeArray(int* array, int first, int mid, int last, int* temp)
{
    //將a[first...mid]和a[mid+1...last]合併
    int i = first, j = mid + 1, k = 0;
    int lengthA = mid+1, lengthB = last+1;
    while (i < lengthA&&j < lengthB) 
    {
        if (array[i] < array[j])
            temp[k++] = array[i++];
        else
            temp[k++] = array[j++];
    }
    while (i < lengthA) 
    {
        temp[k++] = array[i++];
    }
    while (j < lengthB) 
    {
        temp[k++] = array[j++];
    }
    for (i = 0; i < k; ++i) 
    {
        array[first + i] = temp[i];
    }
}

void MergeSort(int* array, int first, int last, int* temp) 
{
    if (first >= last)
        return;
    int mid = (first + last) / 2;
    MergeSort(array, first, mid, temp);//左邊有序
    MergeSort(array, mid + 1, last, temp);//右邊有序
    MergeArray(array, first, mid, last, temp);//合併兩個有序的子序列
}

算法分析

平均、最好、最壞的時間複雜度都爲:O(n*log n)

能夠這樣理解:合併須要O(log n)步操做,每步將排好序的子序列合併須要O(n)的操做。那時間複雜度確定是O(n*log n)。


快速排序

算法說明

 在交換類排序算法中,快排是速度最快的。採用分治的思想,不穩定排序。

算法思想

從n個元素中選擇一個元素做爲分區的標準,通常選第一個元素;

把小於該元素的放在左邊,把大於等於該元素的放在右邊,中間就放該元素;

再分別對左右子序列重複操做1和2,直到每一個子序列裏只有一個元素,排序完畢。

算法實現

 

//版本1
void QuickSort(int* array,int low,int high) 
{
    if (low >= high)
        return;
    int left = low;
    int right = high;
    int key = array[left];//選擇第一個元素做爲區分元素,固然也能夠選最後一個元素。
    while (left != right)
    {
        while (left != right&&array[right] >= key)//從右往左,把小於key的元素放到key的左邊
            --right;
        array[left] = array[right];
        while (left != right&&array[left] <= key)//從左往右,把大於key的元素放到key的右邊
            ++left;
        array[right] = array[left];
    }
    array[left] = key;//此時left等於right

    //一分爲二,分治思想,遞歸調用。
    QuickSort(array, low, left - 1);
    QuickSort(array, left + 1, high);
}

衆所周知,Partition函數無論是在快速排序中,仍是在找第K大這類問題中,都有很重要的地位,故而分開寫,就有了版本2。

int Partition(int* array,int left,int right)
{
    int key = array[left];
    while (left != right)
    {
        while (left != right&&array[right] >= key)//從右往左,把小於key的元素放到key的左邊
            --right;
        array[left] = array[right];
        while (left != right&&array[left] <= key)//從左往右,把大於key的元素放到key的右邊
            ++left;
        array[right] = array[left];
    }
    array[left] = key;
    return left;//返回區分函數
}

//快排主函數
void quicksort(int* arr, int left, int right)
{
    if(left< right)
    {
        int middle = mypartition(arr, left, right);
        quicksort(arr, left, middle-1);
        quicksort(arr, middle+1, right);
    }
}

算法分析

 

平均時間複雜度:O(n*log n)。緣由:快排是將數組一分爲二到底,因此須要O(log n)次此操做,每次操做須要排序n次,因此,大多數狀況下,時間複雜度都是O(n*log n)。最好的狀況:是每趟排序結束後,每次劃分使兩個子文件的長度大體相等,時間複雜度爲O(n*log n)。最壞的狀況:是待排序元素已經排好序。第一趟通過n-1次比較後第一個元素保持位置不變,並獲得一個n-1個元素的子序列;第二趟通過n-2次比較,將第二個元素定位在原來的位置上,並獲得一個包括n-2個元素的子序列,依次類推,這樣總的比較次數是:n(n-1)/2=O(n^2)。

相關文章
相關標籤/搜索