1. 程式人生 > >排序演算法的一點點小結

排序演算法的一點點小結

一轉眼2月過去了,秋招快結束了,趁現在這段時間對之前面試中問到的排序演算法做一個小結,怕背熟練的又忘記了。。。

#include<Windows.h>
#include<iostream>
#include<vector>
#include<stdio.h>
#include<stack>
using namespace std;
void maopao(vector<int> &a)//時間複雜度O(n^2),空間複雜度O(1),穩定排序
{
	if (a.empty()) return;
	int n = a.size();
	for (int i = 0; i < n; i++)
	{
		for (int j = i + 1; j < n; j++)
		{
			if (a[i] > a[j])
			{
				swap(a[i], a[j]);
			}
		}
	}
}
void maopao1(vector<int> &a)//變種1 設立標誌位,當標誌位在一輪迴圈中不變時說明陣列已經有序
{
	if (a.empty()) return;
	int n = a.size();
	for (int i = 0; i < n; i++)
	{
		bool flag = false;
		for (int j = i + 1; j < n; j++)
		{
			if (a[i] > a[j])
			{
				swap(a[i], a[j]);
				flag = true;
			}
		}
		if (!flag) break;
	}
}
void kuaipai(vector<int> &a,int left,int right)//遞迴版本,時間複雜度O(nlongn),最好情況O(n),最差情況O(n^2),輔助情況(O(n)) 非穩定排序
{
	if (left > right) return;
	int i = left; int j = right; int k = a[i];
	while (i < j)
	{
		while (i < j&&a[j] >= k)
		{
			j--;
		}
		if (i < j) a[i++] = a[j];
		while (i < j&&a[i] < k)
		{
			i++;
		}
		if (i < j) a[j--] = a[i];
	}
	a[i] = k;
	kuaipai(a, left, i-1);
	kuaipai(a, i + 1, right);
}
int post(vector<int> &a, int left, int right)//非遞迴版本
{
	int i = left; int j = right; int k = a[i];
	while (i < j)
	{
		while (i < j&&a[j] >= k)
		{
			j--;
		}
		if (i < j) a[i++] = a[j];
		while (i < j&&a[i] < k)
		{
			i++;
		}
		if (i < j) a[j--] = a[i];
	}
	a[i] = k;
	return i;
}
void kuaipai1(vector<int> &a,int i ,int j)
{
	stack<int> t;
	t.push(i);
	t.push(j);	
	int k;
	while (!t.empty())
	{
		int r = t.top(); t.pop();
		int l = t.top(); t.pop();
		k = post(a, l, r);
		if (k-1 > l)
		{
			t.push(l);
			t.push(k - 1);
		}
		if (k + 1 < r)
		{
			t.push(k + 1);
			t.push(r);
		}
	}
}
void xuanpai(vector<int> &a)//時間複雜度O(n^2),額外空間O(1),不穩定排序
{
	for (int i = 0; i < a.size(); i++)
	{
		int min = i;
		for (int j = i+1; j < a.size(); j++)
		{
			if (a[j] < a[min])
			{
				min = j;
			}
		}
		if(min!=i)swap(a[i], a[min]);		
	}
}
void charu(vector<int> &a)//直接插入排序,時間複雜度O(N^2),空間複雜度O(1),穩定排序
{
	for (int i = 1; i < a.size(); i++)
	{
		int j = i;
		while (j > 0 && a[j] < a[j - 1])
		{
			swap(a[j], a[j - 1]);
			j--;
		}
	}
}
void xier(vector<int> &a)//空間複雜度O(nlongn)~O(n^2),空間複雜度O(1),不穩定排序
{
	for (int gap = a.size() / 2; gap > 0; gap /= 2)
	{
		for (int i = gap; i < a.size(); i++)
		{
			int j = i;
			while (j - gap >= 0 && a[j] < a[j - gap])
			{
				swap(a[j], a[j - gap]);
				j--;
			}
		}
	}
}
void merge(vector<int> &a, int l, int mid, int r)
{
	int i = l;
	int j = mid + 1;
	int t = 0;
	vector<int> temp(r - l + 1, 0);
	while(i <= mid&&j <= r)
	{
		if (a[i] <= a[j])
		{
			temp[t++] = a[i++];
		}
		else {
			temp[t++] = a[j++];
		}
	}
	while (i <= mid) { temp[t++] = a[i++]; }
	while (j <= r) { temp[t++] = a[j++]; }
	t = 0;
	while (t < (r - l + 1)) { a[l+t] = temp[t]; t++; }//a[l+t]=temp[t++] 陣列下標訪問越界?

}

void guibin(vector<int> &a,int l,int r)//時間複雜度O(nlogn),空間複雜度O(n),穩定排序
{
	if (l < r)
	{
		int mid = (r+l) / 2;
		guibin(a, l, mid);
		guibin(a, mid + 1, r);
		merge(a, l, mid, r);
	}

}
void adjustHeap(vector<int> &a, int i, int length)
{
	int temp = a[i];
	for (int k = 2 * i + 1; k < length; k = 2 * k + 1)//從i結點的左子結點開始,2*i+1開始
	{
		if (k + 1 < length&&a[k] < a[k + 1])//如果左子節點小於右子節點,k指向右子節點
		{
			k++;
		}
		if (a[k] > temp)//如果子節點的值大於父節點,將子節點的值賦給父節點
		{
			a[i] = a[k];
			i = k;
		}
		else break;
	}
	a[i] = temp;
}
void duipai(vector<int> &a)//時間複雜度O(nlogn),空間複雜度O(1),不穩定排序
{
	//建立大頂堆
	for (int i = a.size() / 2 - 1; i >= 0; i--)
	{
		//從第一個非葉子結點從下至上,從右至左調整結構
		adjustHeap(a, i, a.size());
	}
	//調整堆結構+交換堆頂元素與末尾元素
	for (int j = a.size() - 1; j > 0; j--)
	{
		swap(a[0],a[j]);//將堆頂元素與末尾元素交換
		adjustHeap(a, 0, j);//重新對堆調整
	}
}
int main(void)
{
	vector<int> a = { 2,6,3,1,5,8,4,2,0 };
	duipai(a);
	for (int i = 0; i < a.size(); i++)
	{
		cout << a[i] ;
	}
	cout << endl;
	system("pause");
	return 0;
}

以上程式碼均在vs2015下跑過,親證可用。