各种常用排序算法学习

#include<time.h>
#include<stdlib.h>
#include<iostream>
using std::cout;
using std::endl;
#define ARRLEN 10
#define MAX 100

void Bubble_Sort(int arr[], int len);
void Select_Sort(int arr[], int len);
void Insert_Sort(int arr[], int len);
void Shell_Sort(int arr[], int len);
void Quik_Sort(int arr[], int low, int high);
int FindPos(int arr[], int low, int high);
void Radix_Sort(int arr[], int len);
void Bucket_Sort(int arr[], size_t len);
void Merge_Sort(int arr[], size_t len);
void _merge(int arr[], int low, int high);
void _merge_in_arr(int arr[], int low, int mid, int high);
int Binary_Search(int arr[], size_t len, int findVal);		//二分查找
int main()
{	
	int arr[10];
	srand((unsigned)time(NULL));
	for (int i = 0; i < ARRLEN; i++)
	{
		arr[i] = rand() % MAX;
	}
	cout << "生成的随机数:" << endl;
	for (int i = 0; i < ARRLEN; i++)
	{
		cout << arr[i] << "   ";
	}
	cout << endl;
	//int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	//Bubble_Sort(arr, ARRLEN);
	//Select_Sort(arr, ARRLEN);
	Insert_Sort(arr, ARRLEN);
	//Sheel_Sort(arr, ARRLEN);
	//Quik_Sort(arr, 0, ARRLEN-1);
	//Radix_Sort(arr, ARRLEN);       //基数排序
	//Bucket_Sort(arr, ARRLEN);         //桶排序
	//Merge_Sort(arr, ARRLEN);			//归并排序
	//int i=Binary_Search(arr, 10, 11);
	cout << "排序之后:" << endl;
	for (int i = 0; i < ARRLEN; i++)
	{
		cout << arr[i] << "   ";
	}
	cout << endl;
	system("pause");
	getchar();
    return 0;
}
//==========================================冒泡排序
void Bubble_Sort(int arr[], int len)
{
	bool flag = true;		//使用标志位来过滤极端情况的产生
	//例如:9 2 3 4 5 6 7 8这样的在执行第一次冒泡之后将9排到最后面,实际上已经有序了
	//那么就根据看是否还有没有交换数据,如果没有出现交换数据,那么证明所有的已经排好序了
	//因为冒泡就是对相邻的两个数据进行比较的嘛,没有出现交换数据,那么肯定是已序了
	int tempVal;
	for (int i = 0; i < len&&flag; i++)
	{
		flag = false;
		for (int j = 0; j < len-1-i; j++)	
		{
			if (arr[j] > arr[j+1])		//两两比较
			{
				flag = true;
				tempVal = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tempVal;
			}
		}
	}
	//for (int i = 0; i < len; i++)
	//{
	//	for (int j = len - 2; j >= i; j--)
	//	{
	//		if (arr[j] > arr[j + 1])
	//		{
	//			tempVal = arr[j];
	//			arr[j] = arr[j + 1];
	//			arr[j + 1] = tempVal;
	//		}
	//	}
	//}
}
//===========================================选择排序
//选择排序和冒泡的不同之处就是,选择排序是首先找到所有的最小的之后吗,然后直接放在正确位置
//比冒泡少了很多交换操作
void Select_Sort(int arr[], int len)
{
	int index = 0;
	int tempVal=0;
	for (int i = 0; i < len-1; i++)
	{
		index = i;	//记录当前要放元素的位置下标
		for (int j = i + 1; j < len; j++)	//和后面的数据进行比较,如果有小于当前位置的数据,那么首先记录下来,直到
		{									//和后面所有的数据比较过来一遍,那么index就是保存的最小元素的下标,然后进行交换就可以了
			if (arr[j]<arr[index])
				index = j;
		}
		if (index != i)						//如果index被改变了,那么直接进行交换就可以了,执行完毕之后第一个位置是序列中最小值
		{
			tempVal = arr[i];
			arr[i] = arr[index];
			arr[index] = tempVal;
		}
	}
}
//===================================插入排序
//所谓插入排序就是将数据一个个插入到一个已经排列好序的序列中去
void Insert_Sort(int arr[], int len)
{
	int tempVal=0;
	int j = 0;
	for (int i = 1; i < len; i++)
	{
		j = i - 1;
		tempVal = arr[i];
		while (j>=0&&arr[j]>tempVal)
		{
			arr[j + 1] = arr[j];		//将比要插入的数大的元素都往后移动位置,给要插入的数空出一个位置,这样插入数据之后前面的元素还是有序的
			j--;
		}
		arr[j + 1] = tempVal;
	}
}
//=======================================希尔排序
//时间复杂度终于突破了n的平方,希尔排序的时间复杂度是n的3/2次方
//而且空间复杂度也是很普通,所有希尔排序是非常好的排序算法
//在插入排序的基础上进行改进,然而效率比插入排序效率要高的多
//因为插入排序最适合的情况就是:序列基本有序,元素个数较少的情况
//所以出现了希尔排序将序列进行分组的方式,但是分组并不是按照连续的序列来进行分的
//而是跳跃式的进行分组,这样就又做到了将每一组数据按照插入排序操作之后就实现了序列基本有序
//然后当按照一个个进行分组的时候就完全是插入排序一样的了,但是只需要简单的几个插入操作就实现了
//整体有序,所有效率比直接使用插入排序效率高的多
void Shell_Sort(int arr[], int len)
{
	int tempVal;
	int j;
	int jump = len / 2;		//不一定都是除以2
	while (jump != 0)
	{
		//下面的操作就是将按照跳跃式分好的组进行插入排序操作
		for (int i = jump; i < len; i++)
		{
			tempVal = arr[i];
			j = i - jump;
			while (j >= 0 && arr[j] > tempVal)
			{
				arr[j+jump] = arr[j];
				j -= jump;
			}
			arr[j + jump] = tempVal;
		}
		jump = jump >> 1;
	}
}
//=============================================快速排序
//通过给元素找合适的位置来达到排序的一种方式
void Quik_Sort(int arr[],int low,int high)
{
	int pos;
	if (low < high)
	{
		pos = FindPos(arr, low, high);
		Quik_Sort(arr, low, pos - 1);
		Quik_Sort(arr, pos + 1, high);
	}
}
int FindPos(int arr[], int low, int high)
{
	int tempVal = arr[low];
	while (low < high)
	{
		while (high>low && arr[high]>=tempVal)
		{
			high--;
		}
		arr[low] = arr[high];
		while (low < high && arr[low] <= tempVal)
		{
			low++;
		}
		arr[high] = arr[low];
	}
	arr[low] = tempVal;
	return low;
}
//基数排序
//原理:利用数组下标天然有序的原理,用空间换时间
void Radix_Sort(int arr[], int len)
{
	//max:是排序元素中最大元素值+1
	//要求:不重复的正整数(可以通过加值解决掉)
	//		不能重复
	//		临时数组内存大小有最大的数决定  空间换时间		
	int tempArr[10000] = { 0};          //这样写要求要排序的数不能大于9999,且必须全为正整数
	for (int i = 0; i < len; i++)
	{
		tempArr[arr[i]] = arr[i];					//将arr中的数据作为tempArr的下标就直接相当于排序了
	}
	int index = 0;
	for (int i = 0; i < 10000; i++)
	{
		if (tempArr[i] != 0)
		{
			arr[index++] = i;        //将tempArr中数据不为0的小标取出来依次赋值给arr数组,就相当于将arr排好了
		}
	}

}
//桶排序
// 108		087		007		060		099
//构建临时数组:
//		0		1		2		3		4		5		6		7		8		9       (我下面的写法j就相当于0~9)
//0                                                                   108
//1														      087
//2                                                           007
//3   060
//4                                                                           099
//5
//6
//下面的写法i相当于0~6
//可以看出如果有5个数只需要定义10*5的二维数组就可以存放了


// 108		087		007		060		099
//第一次按照个位进行排序:
// 060		087		007		108		099
//第二次按照十位进行排序:
// 007		108		060		087		099
//第三次按照百位进行排序:
// 007		060		087		099		108
//这样将个位排序十位排序百位排序完毕之后整个数组就是有序的了
void Bucket_Sort(int arr[], size_t len)
{
	int tempArr[10][10];                     //这样写最多可以排10个数
	for (size_t n = 1; n < 1000; n *= 10)    //这样写表示要求数组中的最大数不能大于1000
	{
		//将临时数组全部初始化为-1
		for (size_t i = 0; i < 10; i++)
		{
			for (size_t j = 0; j < 10; j++)
			{
				tempArr[i][j] = -1;
			}
		}
		//循环取出数组中每个数的个十百千..单个数字
		//根据取出的个十百...的单个数字,将数组元素放在临时二维数组中去(临时数组
		//的行是i值,列是个十百千..的单个数组)
		int m = 0;
		for (size_t i = 0; i < len; i++)
		{
			m = arr[i] / n % 10;						
			tempArr[i][m] = arr[i];																	
		}
		//将临时二维数组中的元素重新放回原来数组arr中
		
		int index = 0;
		for (size_t i = 0; i < 10; i++)
		{
			for (size_t j = 0; j < 10; j++)
			{
				if (tempArr[j][i] != -1)         //需要注意的是从二维数组中去数据的时候是根据0列,1列,2列的顺序来取出的
				{                                //不能一行一行的取出(因为我上面放数据的时候是将分离的个十百..得数作为了二维数组的列了)
					arr[index++] = tempArr[j][i];
				}
			}
		}
	}
	
}
//归并排序
void _merge_in_arr(int arr[], int low, int mid, int high)
{
	int length = high - low + 1;
	int *pDate = new int[length];
	memset(pDate, 0, sizeof(int)* length);
	int left = low;
	int right = mid + 1;
	int index = 0;

	while (right <= high)
	{
		while (arr[left] <= arr[right] && left <= mid)
		{
			pDate[index] = arr[left];
			left++;
			index++;
		}
		if (left > mid)
		{
			break;
		}
		while (arr[left] > arr[right] && right <= high)
		{
			pDate[index] = arr[right];
			right++;
			index++;
		}
	}
	if (left <= mid)
		memmove(&pDate[index], &arr[left], sizeof(int)* (mid - left + 1));
	if (right <= high)
		memmove(&pDate[index], &arr[right], sizeof(int)* (high - right + 1));

	memmove(&arr[low], pDate, sizeof(int)* length);
	delete[]pDate;
}

void _merge(int arr[], int low, int high)
{
	if (low >= high)
		return;
	int mid = (high + low) >> 1;
	_merge(arr, low, mid);
	_merge(arr, mid + 1, high);
	_merge_in_arr(arr, low, mid, high);
}
void Merge_Sort(int arr[], size_t len)
{
	_merge(arr, 0,len - 1);
}
int Binary_Search(int arr[], size_t len,int findVal)
{
	if (arr[0] <= findVal && findVal <= arr[len - 1])     //首先保证能够查找到,如果直接没有在序列中,就不进行二分查找了
	{
		size_t low = 0;
		size_t high = len - 1;
		size_t mid = 0;
		while (low<=high)
		{
			mid = (low + high) >> 1;
			if (arr[mid] == findVal)       //如果找到了,返回下标mid
				return mid;
			else
			{
				if (arr[mid] > findVal)
				{
					high = mid - 1;
				}
				else
				{
					low = mid + 1;
				}
			}
		}
	}
		return -1;
}

猜你喜欢

转载自blog.csdn.net/qq_36769722/article/details/80713478