1. 程式人生 > >經常使用排序算法總結

經常使用排序算法總結

i+1 下標 del sta end else return trac false

#include<iostream>
using namespace std;

//show array
void show(int *ar, int len)
{
	for(int i=0; i<len; ++i)
	{
		cout<<ar[i]<<" ";
	}
	cout<<endl;
}
//bubbleSort
//冒泡排序是一種穩定的排序算法
//最好時間復雜度為O(n)平均時間復雜度為O(n^2)最壞時間復雜度為O(n^2)
//空間復雜度為O(1)
void bubbleSort(int *ar, int len)
{
	bool flag = true;//使用標記能夠是有序序列排序時間復雜度為O(n)
	for(int i=0; i<len-1&&flag; ++i)
	{
		for(int j=0; j<len-1-i; ++j)
		{
			flag = false;
			if(ar[j] > ar[j+1]) 
			{
				ar[j] ^= ar[j+1];
				ar[j+1] ^= ar[j];
				ar[j] ^= ar[j+1];
				flag = true;
			}
		}
	}
}

//selectSort
//直接選擇排序不穩定 最好最壞平均時間復雜度都是O(n^2) 空間復雜度O(1) 
void selectSort(int *ar, int len)
{
	for(int i=0; i<len-1; ++i)
	{
		//如果第i個元素最小,以此類推
		int min = i;
		for(int j=i+1; j<len; ++j)
		{
			if(ar[j] < ar[min])
			{
				min = j;
			}
		}

		//如果第i個不是最小,把最小的交換到第一個 以此類推
		if(i != min)
		{
			ar[i] ^= ar[min];
			ar[min] ^= ar[i];
			ar[i] ^= ar[min];
		}
	}
}

//insertSort 
//直接插入排序為穩定排序
//最好時間復雜度O(n) 最壞時間復雜度O(n^2) 平均時間復雜度O(n^2)
//直接插入排序的特點是待排序數組越有序速度越快
//空間復雜度為O(1)
void insertSort(int *ar, int len)
{
	for(int i=1; i<len; ++i)
	{
		int temp = ar[i];

		//從後向前比較(有序數組能夠保證時間復雜度為O(n)) 在合適的位置插入 
		int j = i-1;
		for(j; j>=0; --j)
		{
			if(ar[j] > temp)
			{
				ar[j+1] = ar[j];
			}
			else
			{
				break;
			}
		}

		ar[j+1] = temp;
	}
}

//shellSort
void shell(int *ar, int len, int size)
{
	for(int i=size; i<len; ++i)
	{
		int temp = ar[i];
		int j = i-size;
		for(j; j>=0; j-=size)
		{
			if(ar[j] > temp)
			{
				ar[j+size] = ar[j];
			}
			else
			{
				break;
			}
		}
		ar[j+size] = temp;
	}
}
void shellSort(int *ar, int len)
{
	int d[] = {5,3,1};//size
	for(int i=0; i<sizeof(d)/sizeof(d[0]); ++i)
	{
		shell(ar, len, d[i]);
	}
}

//quickSort(recursion)
int partition(int *ar, int low, int high)
{
	int temp = ar[low];

	while(low < high)
	{
		while(low<high && ar[high] >= temp)
		{
			--high;
		}
		if(low == high)
		{
			break;
		}
		else
		{
			ar[low] = ar[high];
		}

		while(low<high && ar[low] <= temp)
		{
			++low;
		}
		if(low == high)
		{
			break;
		}
		else
		{
			ar[high] = ar[low];
		}
	}

	ar[low] = temp;
	return low;
}
void quick(int *ar, int low, int high)
{
	int par = partition(ar, low, high);

	if(par > low+1)
	{
		quick(ar, low, par-1);
	}
	if(par < high-1)
	{
		quick(ar, par+1, high);
	}
}
void quickSort(int *ar, int len)
{
	quick(ar, 0, len-1);
}


//quickSort2(norecursion)
void quickSort2(int *ar, int len)
{
	int *stack = new (nothrow) int[len];
	int top = 0;
	int low = 0;
	int high = len-1;

	stack[top++] = low;
	stack[top++] = high;
	do
	{
		high = stack[--top];
		low = stack[--top];
		int par = partition(ar, low, high);
		if(par > low+1)
		{
			stack[top++] = low;
			stack[top++] = par-1;
		}
		if(par < high-1)
		{
			stack[top++] = par+1;
			stack[top++] = high;
		}
	}while(top > 0);

	delete []stack;
}

//mergeSort(recursion)
void sort(int *ar, int low, int mid, int high)
{
	int i = low, j = mid+1, k = 0;
	int *temp = new (nothrow) int[high-low+1];

	while(i<=mid && j<=high)
	{
		if(ar[i] < ar[j])
		{
			temp[k++] = ar[i++];
		}
		else
		{
			temp[k++] = ar[j++];
		}
	}

	while(i<=mid)
	{
		temp[k++] = ar[i++];
	}
	while(j<=high)
	{
		temp[k++] = ar[j++];
	}

	for(int i=low, k=0; i<=high; ++i, ++k)
	{
		ar[i] = temp[k];
	}
	delete []temp;
}
void merge(int *ar, int low,  int high)
{
	if(low < high)
	{
		int mid = (low+high)/2;
		merge(ar, low, mid);
		merge(ar, mid+1, high);
		sort(ar, low, mid, high);
	}
}
void mergeSort(int *ar, int len)
{
	merge(ar, 0, len-1);
}

//mergeSort2(norecursion)
void mergeSort2(int *ar, int len)
{
	int size = 1, low, mid, high;

	while(size < len-1)
	{
		low = 0;
		while( low+size < len)//low+size-1 < len-1
		{
			mid = low+size-1;
			high = mid+size;
			if(high > len-1)
			{
				high = len-1;
			}
			sort(ar, low, mid, high);
			low = high+1;
		}
		size *= 2;
	}
}
//堆排序為不穩定排序 時間復雜度為O(nlog2n) 空間復雜度為O(1)
void adjustFromUp(int *ar, int start, int end)//調整最大堆 end下標可取
{
	int i=start, j=2*i+1;//記錄雙親結點和孩子結點
	int temp = ar[i];

	while(j<=end)
	{
		if(j+1<=end && ar[j+1]>ar[j])//在不越界的情況下,j為值最大的孩子結點
		{
			++j;
		}
		if(temp >= ar[j])//start結點比孩子結點大
		{
			break;
		}		
		ar[i] = ar[j];//將大的孩子結點賦值個雙親結點
		//調整下標
		i = j;
		j = 2*i+1;		
	}
	ar[i] = temp;
}
void makeMaxHeap(int *ar, int len)//建立最大堆
{
	for(int i=(len-1)/2; i>=0;--i)
	{
		adjustFromUp(ar, i, len-1);//擴大的調整範圍
	}
}
void heapSort(int *ar, int len)
{
	//建立最大堆
	makeMaxHeap(ar,len);
	for(int i=0;i<len-1; ++i)
	{
		//將最大的元素和最後一個元素交換
		int temp = ar[0];
		ar[0] = ar[len-i-1];
		ar[len-i-1] = temp;
		adjustFromUp(ar, 0, (len-1-i)-1); //len-1-i保證下標可取, 再減1表示最後一個元素已經有序,不須要再調整
	}
}

int main(void)
{
	int ia[] = {45,56,78,9,23,45,12,99,82,65,3000,};
	int len =sizeof(ia)/sizeof(ia[0]);
	//heapSort(ia, len);	

	//bubbleSort(ia, len);
	//selectSort(ia, len);
	//insertSort(ia, len);
	//shellSort(ia, len);
	quickSort(ia, len);
	//quickSort2(ia, len);
	//mergeSort(ia, len);
	//mergeSort2(ia, len);
	show(ia, len);

	return 0;
}

經常使用排序算法總結