常见的几种排序算法

#include <iostream>

using namespace std;

/*排序过程都是直接在内存中完成,统称为内排序*/
//=======================交换排序================
/*冒泡排序:时间复杂度为O(n^2),空间复杂度为O(1)
依次比较相邻两个元素,首先比较第1个位置和第2个位置的数,大的放后面,小的放前面,然后比较第2个位置第3个位置的数,重复进行到第n个位置,经过这一轮,数组中最大元素交换到第n个位置;
重复上一步骤,直到第n-1个位置;依次重复执行,直到第1个位置*/

void bubbleSort(int arr[], int len)
{
	int temp;
	for (int i = len - 1; i > 0; i--)
	{
		for (int j = 0; j < i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

/*鸡尾酒排序: 冒泡排序改进算法
双向冒泡排序*/
void cocktailSort(int arr[], int len)
{
	int head = 0, tail = len - 1;
	int temp, k;
	while (head < tail)
	{
		for (k = head; k < tail; k++)
		{
			if (arr[k] < arr[k + 1])
			{
				temp = arr[k];
				arr[k] = arr[k + 1];
				arr[k + 1] = temp;
			}
			tail--;
			for (k = tail; k>head;k--)
			{
				if (arr[k - 1]>arr[k])
				{
					temp = arr[k-1];
					arr[k - 1] = arr[k];
					arr[k] = temp;
				}
			}
			head++;
		}
	}
}

/*改进冒泡排序,设置标志:
若在一轮扫描过程中没有交换元素,则表示已经排序完成,没必要继续执行*/
void bubbleFlagSort(int arr[], int len)
{
	int temp, flag = 1;
	for (int i = len - 1; i > 0 && flag; i--)
	{
		flag = 0;
		for (int j = 0; j < i; i++)
		{
			if (arr[j] < arr[j + 1])
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				flag = 1;
			}
		}
	}
}

/*快速排序:O(N*log2N)
首先数组根据中枢值分成两个部分,左边元素小于等于中枢值,右边元素都大于中枢值;然后每个部分被递归的排序。
优化:消除递归;
          选择基于三中值分区的中枢值;
          设定一个切分数组长度的最小值,如果小于这个值就直接使用插入排序;*/
void qSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	int zsv = a[left];//选取第一个元素为中枢值
	int last = left, temp;
	for (int p = left + 1; p <= right; p++)
	{
		if (a[p] < zsv)
		{
			++last;
			temp = a[p];
			a[p] = a[last];
			a[last] = temp;
		}
	}
	a[left] = a[last];
	a[last] = zsv;

	//递归
	qSort(a, left, last - 1);
	qSort(a, last + 1, right);
}
void quickSort(int* a, int len)
{
	qSort(a, 0, len - 1);
}

//============================选择排序===================
/*选择排序:每次从未排序的序列中挑选出最大(最小)的元素,重复这个过程直到所有元素都被挑完。O(n^2)*/
void selectSort(int* a, int len)
{
	int minpos, min;
	for (int i = 0; i < len; i++)
	{
		min = a[i];
		minpos = i;
		for (int j = i; j < len; j++)
		{
			if (a[j] < min)
			{
				min = a[j];
				minpos = j;
			}
		}
		a[minpos] = a[i];
		a[i] = min;
	}
}

/*堆排序:堆实际上是一棵完全二叉树
堆的基本操作分为向上调整和向下调整,利用向上调整操作构建堆,堆顶元素和堆尾交换后,堆长度减1,
利用向下调整操作从堆顶开始调整生成新堆。*/
inline void swap(int* arr, int a, int b)
{
	int temp = arr[a];
	arr[a] = arr[b];
	arr[b] = temp;
}
void HeapAdjust(int* L, int s, int m)//构建大顶堆
{
	int temp, j;
	temp = L[s];
	for (j = 2 * s; j < m; j *= 2)//沿关键字较大的孩子结点向下筛选
	{
		if (j < m && L[j] < L[j + 1])//lchild<rchild
			++j;    //j为关键字中较大的记录的小标
		if (temp>=L[j])//parent>=rchild
			break;
		L[s] = L[j];
		s = j;
	}
	L[s] = temp;//交换parent与lchild
}
//对顺序表L进行堆排序
void HeapSort(int* L,int len)
{
	int i;
	for (i = len/ 2; i > 0; i--)//把L构建成一个大顶堆
		HeapAdjust(L, i-1, len);

	/*for (i = 0; i < len; i++)
		cout << L[i] << " ";
		cout << endl;*/

	for (i = len-1; i > 0; i--)
	{
		swap(L, 0, i);//将堆顶记录和当前未经排序子序列的最后一个记录交换
		HeapAdjust(L, 0, i - 1);//将L[0--i-1]重新调整为大顶堆
	}
	/*for (i = 0; i < len; i++)
		cout << L[i] << " ";
		cout << endl;*/
}

//================插入排序===============
/*插入排序:O(n^2)
将一个数组分为两个部分,前一部分为已排序,后一部分为乱序,
每次将乱序部分第一个元素插入到有序部分中,从插入点开始有序部分元素依次后移,
如此重复直至乱序元素个数为0,则完成整个排序过程。*/
void insertSort(int* arr, int len)
{
	for (int i = 1; i < len; i++)
	{
		int pos = i - 1;
		int temp = arr[i];
		while (pos >= 0 && arr[pos]>temp)
		{
			arr[pos + 1] = arr[pos];
			pos--;
		}
		arr[pos + 1] = temp;
	}
}

/*希尔(Shell)排序 :一种递减增量分组插入排序
将比较的全部元素分为几个区域来提升插入排序的性能*/
void ShellSort(int* arr, int len)
{
	// 以 N/2^k(k从1开始)为步长,直至步长为1  
	for (int step = len / 2; step > 0;step/=2)
	{
		// 各组内简单插入排序  
		for (int i = step; i < len;i++)
		{
			int temp = arr[i];
			int j = i - step;
			for (; j >= 0 && arr[j]>temp; j -= step)
				arr[j + step] = arr[j];
			
			arr[j + step] = temp;
		}
	}
}

//=======================合并排序=====================
/*归并排序:
假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,
然后两两归并,得到[n/2]([x]表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,.......,
如此重复,直到得到一个长度为n的有序序列为止,即2路归并排序*/
//合并两个有序部分
void mergeArray(int a[], int first, int mid, int last, int temp[]) {
	if (first >= last) {
		return;
	}
	int i = first, j = mid + 1;
	int k = first;
	while (i <= mid && j <= last) {
		if (a[i] > a[j]) {
			temp[k++] = a[j++];
		}
		else {
			temp[k++] = a[i++];
		}
	}
	while (i <= mid) {
		temp[k++] = a[i++];
	}
	while (j <= last) {
		temp[k++] = a[j++];
	}

	// 回写到原来数组中  
	for (k = first; k <= last; k++) {
		a[k] = temp[k];
	}
}
//递归调用归并
void mSort(int* a, int first, int last, int *temp) {
	if (first < last) {
		int mid = (first + last) >> 1;
		mSort(a, first, mid, temp);
		mSort(a, mid + 1, last, temp);
		mergeArray(a, first, mid, last, temp);
	}
}
//归并排序算法
void MergeSort(int* a, int len)
{
	int* temp = new int[len];
	mSort(a, 0, len - 1, temp);
	delete[] temp;
}

int main()
{
	int a[] = {50,10,90,30,70,40,80,60,20};
	MergeSort(a, 9);

	for (int i = 0; i < 9; i++)
		cout << a[i] << " ";
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/cat1992/article/details/76736194