c/c++再學習:查找算法瞭解

1.順序查找

  說明:順序查找適合於存儲結構爲順序存儲或連接存儲的線性表。
  基本思想:順序查找也稱爲線形查找,屬於無序查找算法。從數據結構線形表的一端開始,順序掃描,依次將掃描到的結點關鍵字與給定值k相比較,若相等則表示查找成功;若掃描結束仍沒有找到關鍵字等於k的結點,表示查找失敗。算法

複雜度分析: 

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

int sequence_search(vector<int>& nums, int val)
{
    int len = nums.size();

    for (int i = 0; i < len; i++)
    {
        if (nums[i] == val)
        {
            return i;
        }
    }

    return -1;
}

2.二分查找

  說明:元素必須是有序的,若是是無序的則要先進行排序操做。
基本思想:也稱爲是折半查找,屬於有序查找算法。用給定值k先與中間結點的關鍵字比較,中間結點把線形表分紅兩個子表,若相等則查找成功;若不相等,再根據k與該中間結點關鍵字的比較結果肯定下一步查找哪一個子表,這樣遞歸進行,直到查找到或查找結束髮現表中沒有這樣的結點。數據結構

複雜度分析

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

int binary_search_recurse(vector<int>&nums, int val, int low, int high)
{
    if (low == high)
    {
        if (nums[low] != val)
        {
            return -1;
        }
        else
        {
            return low;
        }
    }

    int mid = low + (high - low) / 2;
    
    if (nums[mid] == val) {
        return mid;
    }
    else if (nums[mid] > val) {
        return binary_search_recurse(nums, val, low, mid - 1);
    }
    else if (nums[mid] < val) {
        return binary_search_recurse(nums, val, mid + 1, high);
    }
    return -1;
}

int binary_search(vector<int>&nums, int val)
{
    quick_sort(nums, 0, nums.size() - 1);
    return binary_search_recurse(nums, val, 0, nums.size() - 1);
}

3.插值查找

在介紹插值查找以前,首先考慮一個新問題,爲何上述算法必定要是折半,而不是折四分之一或者折更多呢?打個比方,在英文字典裏面查「apple」,你下意識翻開字典是翻前面的書頁仍是後面的書頁呢?若是再讓你查「zoo」,你又怎麼查?很顯然,這裏你絕對不會是從中間開始查起,而是有必定目的的往前或日後翻。一樣的,好比要在取值範圍1 ~ 10000 之間 100 個元素從小到大均勻分佈的數組中查找5, 咱們天然會考慮從數組下標較小的開始查找。
  通過以上分析,折半查找這種查找方式,不是自適應的(也就是說是傻瓜式的)。二分查找中查找點計算以下:
  mid=(low+high)/2, 即mid=low+1/2(high-low);
  經過類比,咱們能夠將查找的點改進爲以下:
  mid=low+(key-a[low])/(a[high]-a[low])
(high-low)。

  也就是將上述的比例參數1/2改進爲自適應的,根據關鍵字在整個有序表中所處的位置,讓mid值的變化更靠近關鍵字key,這樣也就間接地減小了比較次數。性能

基本思想

基於二分查找算法,將查找點的選擇改進爲自適應選擇,能夠提升查找效率。固然,差值查找也屬於有序查找。
對於表長較大,而關鍵字分佈又比較均勻的查找表來講,插值查找算法的平均性能比折半查找要好的多。反之,數組中若是分佈很是不均勻,那麼插值查找未必是很合適的選擇。ui

複雜度分析

查找成功或者失敗的時間複雜度均爲O(log2(log2n))code

int insert_search_recurse(vector<int>&nums, int val, int low, int high)
{
    if (low == high)
    {
        if (nums[low] != val)
        {
            return -1;
        }
        else
        {
            return low;
        }
    }

    int mid = low + (high - low) * (val - nums[low]) / (nums[high] - nums[low]);

    if (nums[mid] == val) {
        return mid;
    }
    else if (nums[mid] > val) {
        return insert_search_recurse(nums, val, low, mid - 1);
    }
    else if (nums[mid] < val) {
        return insert_search_recurse(nums, val, mid + 1, high);
    }
    return -1;
}

int insert_search(vector<int>&nums, int val)
{
    quick_sort(nums, 0, nums.size() - 1);
    return binary_search_recurse(nums, val, 0, nums.size() - 1);
}
相關文章
相關標籤/搜索