算法導論: 第7章

7.4-5 快速排序+插入排序node

粗略證實以下:ios

從書中證實可知,只要劃分是常數比,那麼最後指望都是同樣的。故假設每次劃分都是均勻的。假設劃分深度爲h時,每一個塊的規模都不超過k,則有k*2^h = n,h = lg(n/k)。又由於在最底層,規模不超過k的子序列有n/k個,因此每一個子序列內部插入排序時間爲O(k^2),總的插入排序時間爲O(nk)。(注意:這一步證實不嚴格,每一個都是O(K^2),加起來可能比O(nk)要大。)數組

每一次劃分爲O(n),總共有lg(n/k)層,因此劃分的複雜度爲O(nlg(n/k)),因此,總的時間爲O(nk + nlg(n/k))。dom

7-4 快速排序的堆棧深度優化

優化的尾遞歸:
QUICKSORT (A, p, r )
    while p < r
        do Partition and sort the small subarray Þrst
        q ← PARTITION(A, p, r )
        if q − p < r − q
            then QUICKSORT (A, p, q − 1)
                    p ← q + 1
        else QUICKSORT (A, q + 1, r )
                    r ← q − 1ui

7-6 模糊排序spa

快速排序能夠當作區間大小爲1的模糊排序。模糊排序的關鍵在於如何充分利用重疊區間,解決思路是在調用Partion()劃分時,區間若是重疊的部分,就把它們看作是相等的,並提取公共部分繼續劃分。.net

轉載代碼來源http://blog.csdn.net/mishifangxiangdefeng/article/details/7681109blog

#include <iostream>
using namespace std;

struct node
{
	int start;
	int end;
	bool operator<(const node & b)const
	{
		return end < b.start;
	}
	bool operator==(const node & b)const
	{
		return (end >= b .start) && (start <= b.end);
	}
	bool operator>(const node & b)const
	{
		return start > b.end;
	}
};

//劃分結果:0 -> a小於主元,a+1 -> b-1等於主元,b -> length_A大於主元
struct divid
{
	int a;
	int b;
};

node A[11];
int length_A = 10;

//按劃分結果分三行顯示
void Print(divid d)
{
	int i = 1;
	if(d.a > 0)
	{
		for(i = 1; i <= d.a; i++)
			cout<<'('<<A[i].start<<','<<A[i].end<<") ";
		cout<<endl;
		i = d.a + 1;
	}
	if(d.b > 0)
	{
		for(; i < d.b; i++)
			cout<<'('<<A[i].start<<','<<A[i].end<<") ";
		cout<<endl;
		i = d.b;
	}
	if(i <= length_A)
	{
		for(; i <= length_A; i++)
			cout<<'('<<A[i].start<<','<<A[i].end<<") ";
		cout<<endl;
	}
	cout<<endl;
}
//交換
void Exchange(node &a, node &b)
{
	node temp;
	temp = a;
	a = b;
	b = temp;
}
//劃分是重點
divid Partition(node *A, int p, int r)
{
	//先取任意一個元素爲主元
	node x = A[r];
	int i = p-1, j = r+1, k = p;
	while(k <=r && k < j)
	{
		//若是小於主元,交換到前面
		if(A[k] < x)
		{
			i++;
			Exchange(A[i], A[k]);
			k++;
		}
		//若是大於,交換到後面
		else if(A[k] > x)
		{
			j--;
			Exchange(A[j], A[k]);
			//這裏不能k++,由於交換過來的元素也可能大於主元
		}
		else
		{
			//若是相等,不交換,可是要提取公因子
			x.end = min(x.end, A[k].end);
			x.start = max(x.start, A[k].start);
			k++;
		}
	}
	//返回劃分結果
	divid ret = {i, j};
	if(ret.a < p)ret.a = -1;
	if(ret.b > r)ret.b = -1;
	Print(ret);
	return ret;
}

void QuickSort(node *A, int p, int r)
{
	if(p >= r)
		return;
	//把數組劃分爲三段
	divid q = Partition(A, p, r);
	//若是存在第一段,對第一段排序
	if(q.a > 0)
		QuickSort(A, p, q.a);
	//若是存在第三段,對第三段排序
	if(q.b > 0)
		QuickSort(A, q.b, r);
}

int main()
{
	int i, n;
	cin>>n;
	length_A = n;
	//init data by random
	for(i = 1; i <= length_A; i++)
	{
		A[i].start = rand() % 100;
		A[i].end = rand() % 100;
		if(A[i].start > A[i].end)
			swap(A[i].start, A[i].end);
	}
	divid d = {-1, -1};
	Print(d);
	//sort
	QuickSort(A, 1, length_A);
	return 0;
}
相關文章
相關標籤/搜索