1. 程式人生 > >資料結構查詢章節總結之一

資料結構查詢章節總結之一

查詢章節總結之一

1.前言

花了一上午的時間來從頭開始學習查詢,來總結下自己所學到的一點點東西。

2.關於靜態查詢表

就是很簡單的陣列的線性查詢,需要從頭開始一個個去找(即為遍歷)那麼這種查詢方法的平均查詢長度在查詢概率相同的情況下為
A S S s

= 1 n i = 1
n
( n i + 1 ) ASS_s=\frac{1}{n}\sum_{i=1}^n(n-i+1)

A S S s = n + 1 2 ASS_s=\frac{n+1}{2}
關於查詢的一個小技巧

typedef struct list 
{
	int length;
	int *elem;
}list;

int search(list test, int key)
{
	test.elem[0] = key;//最開始用list的時候0位置處置空不用
    //這一個語句的作用是設定一個哨兵,當表中沒有元素的時候直接返回0
	for(int i = test.elem.length; i >= 0; i--)
	{
		if (test.elem[i] == key)
		return i;
	}
}

3.有序表的查詢

對於有序表我們肯定是十分熟悉的了,我們可以採用二分查詢的方式去找,其實就是我們平時用的二分法

typedef struct list 
{
	int *elem;//沿用上次的結構
	//不過此時請注意,這個時候的陣列為有序陣列
	int length;
}list;

int search(list test,int left, int right, int key) 
{
	if (key<test.elem[left] || key>test.elem[right])
		return ERROR;
	else 
	{
		int mid = left + (right - left) / 2;//也表示的是求平均值的意思,不過可以防止爆精度
		if (key > test.elem[mid]) 
		{
			search(test, mid + 1, right, key);
		}
		else if(key==test.elem[mid])
		{
			return mid;
		}
		else 
		{
			search(test, left, mid - 1, key);
		}
	}
}

那麼折半的平均查詢長度為多少呢?我們可以將整個查詢的過程視為一個在二叉樹上搜索的過程,二叉樹的根節點為這個有序陣列的中點.對整個二叉樹進行中序遍歷,可以得到我們原來的有序陣列.假設查詢每一個節點的概率相同,假設是一個滿二叉樹,那麼第一層節點有一個,第二層有兩個…第n層有2(n-1)個,那麼查詢第一個點的次數為1次,查詢第二層節點的次數為兩次,個數為2…查詢第n層的節點次數為n次,一共有2n-1個.我們假設一共有k個節點,那麼這k個節點所能生成二叉樹的層數至多為

n=log2(k+1).

那麼平均查詢長度就為
A S L s = 1 k i = 1 n i 2 i 1 ASL_s=\frac{1}{k}\sum_{i=1}^{n}i*2^{i-1}

A S L s = k + 1 k l o g 2 ( k + 1 ) 1 ; ASL_s=\frac{k+1}{k}log_2(k+1)-1;
k比較大的時候我們可以近似認為
A S L s = l o g 2 ( n + 1 ) 1 A S L s = l o g 2 ( n + 1 ) 1 ASL_s=log_2(n+1)-1ASL_s=log_2(n+1)-1
所以線性折半查詢的效率要遠遠高於順序查詢,但它只能適用於順序儲存結構,和有序表.

前面較為簡單的部分就先總結到這裡,之後會更新更後面的章節,感覺都是硬骨頭.