1. 程式人生 > >幾大常用排序,冒泡,選擇,插入,希爾,堆排,歸併,快排以及相關改進

幾大常用排序,冒泡,選擇,插入,希爾,堆排,歸併,快排以及相關改進

#include <stdio.h>
#define MAX 10

typedef int  ElementType;

typedef ElementType ARR[MAX];

void swap(ARR arr,int i,int j)
{
	ElementType temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

void print(ARR arr)
{
	int i;
	for(i = 0;i < MAX;i++)
		printf("%d ",arr[i]);
	printf("\n");
}

void bubble1(ARR arr);
void bubble2(ARR arr);
void select(ARR arr);
void insert(ARR arr);
void shell(ARR arr);
void heap(ARR arr);
void merge(ARR arr,int left,int mid,int right);
void mergesort1(ARR arr);
void mergesort2(ARR arr,int left,int right);
int pivotkey1(ARR arr,int low,int high);
int pivotkey2(ARR arr,int low,int high);
void quicksort1(ARR arr,int low,int high);
void quicksort2(ARR arr,int low,int high);
ElementType getpivot(ARR arr,int low,int high);


int main()
{
	ARR arr1 = {8,7,5,6,4,10,9,1,2,3};
	ARR arr2 = {8,7,5,6,4,10,9,1,2,3};
	ARR arr3 = {8,7,5,6,4,10,9,1,2,3};
	ARR arr4 = {6,3,9,8,4,2,7,5,1,10};
	ARR arr5 = {6,4,2,5,10,7,1,8,3,9};
	ARR arr6 = {6,4,2,5,10,7,1,8,3,9};
	ARR arr7 = {6,4,2,5,10,7,1,8,3,9};
	//ARR arr7 = {10,9,8,7,6,5,4,3,2,1};

	//bubble1(arr1);
	//bubble2(arr1);
	//select(arr2);
	//insert(arr3);
	//shell(arr4);
	//heap(arr5);
	//mergesort1(arr6);
	//mergesort2(arr6,0,MAX-1);
	//quicksort1(arr7,0,9);
	quicksort2(arr7,0,9);

    return 0;
}

void bubble1(ARR arr)//氣泡排序
{
	int i,j;
	for(i = 0;i < MAX - 1;i++)
	{
		for(j = 0;j < MAX - 1 - i;j++)
		{
			if(arr[j] > arr[j+1])
				swap(arr,j,j+1);
		}
		print(arr);
	}
}

void bubble2(ARR arr)//氣泡排序改進
{
	int i,j;
	int flag = 0;
	for(i = 0;i < MAX - 1;i++)
	{
		flag = 0;
		for(j = 0;j < MAX - 1 - i;j++)
		{
			if(arr[j] > arr[j+1])
			{
				flag = 1;
				swap(arr,j,j+1);
			}
		}
		if(flag == 0)
			break;
		print(arr);
	}
}

void select(ARR arr)
{
	int i,j;
	int min;
	for(i = 0;i < MAX - 1;i++)
	{
		min = i;
		for(j = i+1;j < MAX;j++)
			if(arr[min] > arr[j])
				min = j;
		if(min != i)
			swap(arr,i,min);
		print(arr);
	}
}

void insert(ARR arr)//插入排序
{
	int i,j;
	for(i = 1;i < MAX;i++)
	{
		if(arr[i-1] > arr[i])
		{
			ElementType temp = arr[i];
			for(j = i-1;j >= 0;j--)
			{
				if(arr[j] > temp)
					arr[j+1] = arr[j];
				else
					break;
			}
			arr[j+1] = temp;
			print(arr);
		}
	}
}
//希爾排序
void shell(ARR arr)
{
	int a[] = {1,3,5};//增量
	int k = 2;
	int step = a[k];
	int i,j;
	while(k >= 0)
	{
		for(i = step;i < MAX;i++)
		{
			if(arr[i-step] > arr[i])
			{
				ElementType temp = arr[i];
				for(j = i-step;j >= 0;j -= step)
					if(arr[j] > temp)
						arr[j+step] = arr[j];
					else
						break;
				arr[j+step] = temp;
			}
		}
		step = a[--k];
		print(arr);
	}
}

//堆調整
void heapadjust(ARR arr,int n,int m)
{
	ElementType temp = arr[n];
	int i;
	for(i = 2*n+1;i <= m;i = 2*i+1)
	{
		if(i < m && arr[i] < arr[i+1])
			i++;
		if(arr[i] < temp)
			break;
		arr[n] = arr[i];
		n = i;
	}
	arr[n] = temp;
}
//堆排序
void heap(ARR arr)
{
	int i;
	for(i = (MAX-2)/2;i >= 0;i--)//初始化堆
		heapadjust(arr,i,MAX-1);//進行堆調整
	for(i = MAX - 1;i > 0;i--)
	{
		swap(arr,0,i);
		heapadjust(arr,0,i-1);
		print(arr);
	}
}
//進行歸併
void merge(ARR arr,int left,int mid,int right)
{
	int len = right-left+1;
	ElementType temp[len];
	int k = 0;
	int i = left;
	int j = mid+1;
	while(i<=mid && j<=right)
	{
		if(arr[i] < arr[j])
			temp[k++] = arr[i++];
		else
			temp[k++] = arr[j++];
	}
	while(i<=mid)
		temp[k++] = arr[i++];
	while(j<=right)
		temp[k++] = arr[j++];
	for(i = 0;i < len;i++)
		arr[left+i] = temp[i];
}

//歸併排序1
void mergesort1(ARR arr)//非遞迴的歸併排序
{
	int left,right,mid;
	int i;
	for(i = 1;i < MAX;i *= 2)//i為步長
	{
		left = 0;
		while(left+i < MAX)
		{
			mid = left+i-1;
			right = (mid+i)<(MAX-1)?(mid+i):(MAX-1);
			merge(arr,left,mid,right);
			left = right+1;
		}
		print(arr);
	}
}
//歸併排序2
void mergesort2(ARR arr,int left,int right)//遞迴的歸併排序
{
	if(left == right)
		return;
	int mid = (left+right)/2;
	mergesort2(arr,left,mid);
	mergesort2(arr,mid+1,right);
	merge(arr,left,mid,right);
	print(arr);
}

//方法一:獲得樞軸的位置
int pivotkey1(ARR arr,int low,int high)
{
	//int pivot = arr[low];//選取樞軸的初始化位置
	int pivot = getpivot(arr,low,high);
	while(low < high)
	{													//3 4 2 5 7 1 6 8 10 9
		while(low<high && arr[high] > pivot)			//3 4 2 5 1 6 7 8 10 9
			high--;										//3 4 2 5 7 1 6 8 10 9 
		arr[low] = arr[high];
		while(low<high && arr[low] < pivot)
			low++;
		arr[high] = arr[low];
	}
	arr[low] = pivot;
	print(arr);
	return low;
}
//方法二:獲得樞軸的位置
int pivotkey2(ARR arr,int low,int high)
{
	//int pivot = arr[low];//選取樞軸的初始化位置
	int pivot = getpivot(arr,low,high);
	int tail = low+1;
	int i;
	for(i = low+1;i <= high;i++)
	{
		if(arr[i] <= pivot)
		{
			if(i != tail)
				swap(arr,i,tail);
			tail++;
		}
	}
	swap(arr,low,--tail);
	print(arr);
	return tail;
}

//快速排序
void quicksort1(ARR arr,int low,int high)
{
	if(low < high)
	{
		int pivot = pivotkey2(arr,low,high);
		quicksort1(arr,low,pivot-1);
		quicksort1(arr,pivot+1,high);
	}
}
//獲得樞軸的改進
ElementType getpivot(ARR arr,int low,int high)
{
	int mid = (low + high) / 2;
	if(arr[high] < arr[low])
		swap(arr,low,high);
	if(arr[high] < arr[mid])
		swap(arr,high,mid);
	if(arr[mid] > arr[low])
		swap(arr,mid,low);
	return arr[low];
}
//快速排序改進
void quicksort2(ARR arr,int low,int high)
{
	while(low < high)
	{
		int pivot = pivotkey2(arr,low,high);
		quicksort2(arr,low,pivot-1);
		low = pivot+1;//尾遞迴
	}
}