數據結構筆記--查找

靜態查找表:只進行查找操作的查找表
動態查找表:在查找過程中同時插入查找表中不存在的元素,或者刪除已存在的元素
1.順序表查找:從第一個或者最後一個記錄開始,將每個記錄的關鍵字與給定值比較,若相等則查找成功。

C實現:

# include <stdio.h>
# include <stdlib.h>

int Sequential_Search(int *arr, int key, int n);

int main()
{
	int a[5] = {2,3,5,8,7};
	int index;
	index = Sequential_Search2(a, 4, 5);
	printf("順序查找的下標爲:%d \n", index);
	system("pause");
	return 0;
}
//順序查找
int Sequential_Search(int *arr, int key, int n)
{
	for (int i = 0; i < n; i++)
	{
		if (arr[i] == key)
		{
			return i;
		}
	}
}
//有哨兵順序查找
int Sequential_Search2(int *arr, int key, int n)
{
	int i;
	if (arr[0] == key)
		return 0;
	else
		arr[0] = key; //設置a[0]爲關鍵字值,我們稱之爲“哨兵”
	i = n; //循環從數組尾部開始
	while (arr[i] != key)
	{
		i--;
	}
	if (0 == i)
	{
		printf("查找失敗\n");
		return -1;
	}
	else 
		return i; //返回-1則說明查找失敗
}

時間複雜度:

最好情況:O(1),第一次就找到

最壞情況:O(n),需要逐個比較完

平均:O(n)
2.有序表查找:元素是有序排列的,且是順序存儲的(存在數組或者vector)。主要包括二分查找,插值查找,斐波拉契查找
2.1二分查找(折半查找)
基本思想:

  • (1)與中間元素比較,其中mid=low+1/2*(low+high)
  • (2)等於中間元素,則查找成功
  • (3)大於中間元素,在它的右半區查找,重複(1);小於中間元素,在它的左半區查找,重複(1),直到找到給定值。
    時間複雜度:
    最好:O(1)
    最壞:O(logn+1)
    平均:O(logn)
    :折半查找的前提條件是需要有序表順序存儲,對於靜態查找表,一次排序後不再變化,折半查找能得到不錯的效率。但對於需要頻繁執行插入或刪除操作的數據集來說,維護有序的排序會帶來不小的工作量,那就不建議使用。——《大話數據結構》

2.2插值查找(折半查找升級版)
二分查找:mid=low+1/2*(low+high)
插值查找:mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low),也就是將上述的比例參數1/2改進了,根據關鍵字在整個有序表中所處的位置,讓mid值的變化更靠近關鍵字key,這樣也就間接地減少了比較次數

基本思想:基於二分查找算法,將查找點的選擇改進爲自適應選擇,可以提高查找效率。當然,差值查找也屬於有序查找。
因爲如果在一個有序表中找相對較小的元素(即離low更近一點),就mid向low靠近一點;找相對較大的元素(即離high更近一點),就mid向high靠近一點;這樣效率比較高。但要求表中元素分佈比較均勻。

時間複雜度:O(logn)
注:對於表長較大,而關鍵字分佈又比較均勻的查找表來說,插值查找算法的平均性能比折半查找要好的多。反之,數組中如果分佈非常不均勻,那麼插值查找未必是很合適的選擇。

2.3斐波那契查找

斐波拉契數列:0,1,1,2,3,5,8,13,21,34,F(k)

基本思想:也是二分查找的一種提升算法,通過運用黃金比例的概念在數列中選擇查找點進行查找,提高查找效率。同樣地,斐波那契查找也屬於一種有序查找算法。

  • (1)將有序數組的數值補全,使它的長度等於某個斐波拉契數F(k)-1

  • (2)取low=0,mid=low+F(k-1)-1,high=F(k)-2

  • (3)當給定值小於a[mid]值,在mid前半段查找,且前半段長度爲F(k-1)-1;當給定值大於a[mid]值,在mid後半段查找,且後半段長度爲F(k-2)-1;重複(2)

時間複雜度:O(logn)

因爲斐波拉契查找求mid=low+F(k-1)-1,只有加減法,沒有乘法,這種細微差別相比較前兩種方法要好一些。

# include <stdio.h>
# include <stdlib.h>
# define MAXN 20

int Binary_Search(int *arr, int n, int key);
int BinaryInsert_Search(int *arr, int n, int key);
void Fibonacci(int *f);
int Fibonacci_Search(int *arr, int n, int key);

int main(void)
{
	int a[11] = { 0, 1, 16, 24, 35, 47, 59, 62, 73, 88, 99 };
	int index;  // -1表示失敗
	index = Binary_Search(a, 11, 35);
	printf("折半查找的結果爲: %d \n", index);
	index = BinaryInsert_Search(a, 11, 35);
	printf("插值查找的結果爲: %d \n", index);
	index = Fibonacci_Search(a, 11, 35);
	printf("斐波那契查找的結果爲: %d \n", index);
	system("pause");
	return 0;
}

//折半查找
int Binary_Search(int *arr, int n, int key)
{
	int low, high, mid;
	low = 0; //定義最低下標爲記錄首位
	high = n-1; //定義最高下標爲記錄末位
	while (low <= high)
	{
		mid = low + (high - low) / 2; //折半
		if (key < arr[mid])
		{
			high = mid - 1;
		}
		else if (key > arr[mid])
		{
			low = mid + 1;
		}
		else
			return mid;
	}
	return -1;
}

//插值查找
//基本思路:二分查找的改進版 只需改一行代碼 
//			mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low)
int BinaryInsert_Search(int *arr, int n, int key)
{
	int low, high, mid;
	low = 0;
	high = n - 1;
	while (low <= high)
	{
		mid = low + (key - arr[low]) / (arr[high] - arr[low]) * (high - low);
		if (key < arr[mid])
		{
			high = mid - 1;
		}
		else if (key > arr[mid])
		{
			low = mid + 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}

//產生斐波那契數列
void Fibonacci(int *f)
{
	f[0] = 1;
	f[1] = 1;
	for (int i = 2; i < MAXN; ++i)
		f[i] = f[i - 2] + f[i - 1];
}

//斐波那契查找
int Fibonacci_Search(int *arr, int n, int key)
{
	int i, mid, low = 0, high = n - 1, k = 0;
	int F[MAXN];
	Fibonacci(F);
	while (n > F[k] - 1) //計算出n在斐波那契中的位置
		k++;
	for (i = n; i < F[k] - 1; ++i) //把數組補全
		arr[i] = arr[high];
	while (low <= high)
	{
		mid = low + F[k - 1] - 1; //計算當前分隔的下標 根據fibonacci數列進行黃金分割
		if (arr[mid] > key) // 若查找記錄小於當前分割記錄
		{
			high = mid - 1; //最高下標調整到分割下標的mid-1處 
			k = k - 1; // 斐波那契數列下標減一位
		}
		else if (arr[mid] < key) //若查找記錄大於當前分割記錄
		{
			low = mid + 1; //最低下標調整到分割下標mid+1處
			k = k - 2; //斐波那契數列下標減兩位
		}
		else
		{
			if (mid <= n) //如果真則找到相應的位置
			{
				return mid;
			}
			else
			{
				return n; //若mid>n說明是補全數值 返回n
			}
		}
	}
	return -1;
}


  • 二叉排序樹 ( Binary Sort Tree),又稱爲二叉查找樹。它或者是一棵空樹,或者
    是具有下列性質的二叉樹。
    若它的左子樹不空,則左子樹上所有結點的值均小於它的根結構的值 ;
    若它的右子樹不空 ,則右子樹上所有結點的值均大於宮的根結點的值;
    它的左、右子樹也分別爲二叉排序樹。
    待更新。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章