十大排序算法C++实现

1、插入排序:和玩纸牌游戏一样,抓牌时小的插在前边,后边牌往后移动

void insertSort(int* arr, int len){
   if(!arr || len<2)
       return;
   int preIndex=0, curVal=0;
   for(int i=1; i<len; i++){
       preIndex = i - 1;
       curVal = arr[i];
       while(preIndex>=0 && arr[preIndex]>curVal){
          arr[preIndex+1] = arr[preIndex];
          preIndex--;
       }
       arr[preIndex+1] = curVal;
   }
}

2、冒泡排序:它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成

void bubbleSort(size_t size, int* arr) {
	if (!arr || size <= 1) {
		return;
	}

	bool bComplete = false;
	for (size_t i = 0; i < size; i++) {
		bComplete = true;
		for (size_t j = 0; j < size - i - 1; j++) {
			if (arr[j] > arr[j + 1])
			{
				std::swap(arr[j], arr[j + 1]);
				bComplete = false;
			}
		}
		if (bComplete) {
			return;
		}
	}
}

3、选择排序:选择排序是一种简单直观的排序算法
首先,在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
以此类推,直到所有元素均排序完毕

void selectSort(size_t size, int* arr) {
	if (!arr || size <= 1) {
		return;
	}

	size_t minIndex = 0;
	for (size_t i = 0; i < size - 1; i++) {
		minIndex = i;
		for (size_t j = i + 1; j < size; j++) {
			if (arr[j] < arr[minIndex]) {
				minIndex = j;
			}
		}
		std::swap(arr[i], arr[minIndex]);
	}
}

4、希尔排序:是简单插入排序的改进版,它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

void shellSort(size_t size, int*arr) {
	if (!arr || size <= 1) {
		return;
	}

	size_t gap = 1;
	size_t j = 0;

	//固定增量变化
	for (gap = size / 2; gap > 0; gap /= 2) {
		for (size_t i = gap; i < size; ++i) {
			//int()转换类型,避免溢出,相当于分组的插入排序
			for (j = i; int(j - gap) >= 0 && arr[j - gap] > arr[j]; j -= gap) {
				std::swap(arr[j - gap], arr[j]);
			}
		}
	}
}

5、归并排序

void merge(int*arr, size_t left, size_t mid, size_t right) {
	int len = right - left + 1;
	int *temp = new int[len];  //数组较长时请用new,不然栈空间容易溢出
	size_t index = 0;
	size_t i = left, j = mid + 1;
	while (i <= mid && j <= right){
		temp[index++] = arr[i] <= arr[j] ? arr[i++] : arr[j++]; //对两边的数组从小到大放入临时空间
	}
	while (i <= mid){
		temp[index++] = arr[i++];//比较完后,左半边有没放进去的,直接写入
	}
	while (j <= right)	{
		temp[index++] = arr[j++];//比较完后,右半边有没有放进去的,直接写入
	}

	for (int k = 0; k < len; ++k){
		arr[left++] = temp[k];  //把有序的临时数组写入原来数组的起始位置
	}
	delete[] temp;  //释放空间
	temp = NULL;  //指针置空
}

void divide(int* arr, size_t left, size_t right) {
	//递归出口
	if (left == right){
		return;
	}
	size_t mid = (left + right) / 2; //找出区间中部的数,将数组分段
	divide(arr, left, mid);//递归调用,对左边继续分段;
	divide(arr, mid + 1, right);//递归调用,对左边继续分段;
	merge(arr, left, mid, right); //对左右两半进行排序合并成一小段有序的数组
}


void mergeSort(size_t size, int* arr) {
	if (!arr || size <= 1) {
		return;
	}

	size_t left = 0, right = size - 1;
	divide(arr, left, right);
}

6、快速排序:每次都取数组的第一个元素作为基准元素,凡是大于这个基准元素的都放在右边,凡是小于这个基准元素的都放在它的左边。

  • 设置两个变量i,j(称为哨兵),令序列的第一个元素为基准元素。
  • i指向序列的最左边, j指向序列的最右边,j从右往左试探,i从左往右试探,直到j找到小于基准的数就停止,i找到大于基准的数就停止,交换i和j指向的两个数,j继续往左试探,i继续往右试探
  • 如果i和j相遇,则i或j上的元素与基准元素交换,一轮排序结束
  • 对基准元素两边的序列重复上述步骤
void qSort(int* arr, int left, int right) {
	int i = left;
	int j = right;
	int temp = arr[left]; //基准元素

	//递归结束条件
	if (left >= right) {
		return;
	}

	while (i != j) {
		while (arr[j] >= temp && i < j) { //从右往左,找到小于基准的数
			j--;
		}
		while (arr[i] <= temp && i < j) { //从左往右,找到大于基准的数
			i++;
		}
		//交换i和j指向的两个数,然后继续,知道i,j相遇
		if (i < j) {
			std::swap(arr[i], arr[j]); 
		}
	}
	//i和j相遇,i 或 j上的元素与基准元素交换,一轮排序结束
	arr[left] = arr[i]; 
	arr[i] = temp;
	//再分别对两边数据递归快排
	qSort(arr, left, i - 1);
	qSort(arr, i + 1, right);
}

void quickSort(size_t size, int* arr) {
	if (!arr || size <= 1) {
		return;
	}

	qSort(arr, 0, size - 1);
}

7、堆排序

//建立大堆(1、完全二叉树;2、父节点的值始终大于子节点)
void heapify(int* tree, int n, int i) {
	//递归结束出口
	if (i >= n) {
		return;
	}
	int left = 2 * i + 1;
	int right = 2 * i + 2;
	int maxIndex = i;
	maxIndex = (left < n && tree[left] > tree[maxIndex]) ? left : maxIndex;
	maxIndex = (right < n && tree[right] > tree[maxIndex]) ? right : maxIndex;
	if (maxIndex != i) {
		std::swap(tree[i], tree[maxIndex]);
		heapify(tree, n, maxIndex);
	}
}

void heapSort(int size, int* arr) {
	if (!arr || size <= 1) {
		return;
	}

	int lastNodeIndex = size - 1; //最后一个子节点
	int lastParentIndex = (lastNodeIndex - 1) / 2; //最后一个子节点的父节点
	//从最后一个子节点的父节点开始对所有父节点建立大堆
	for (int i = lastParentIndex; i >= 0; i--){
		heapify(arr, size, i);
	}

	//经过上一步骤处理后根节点必然是最大的值
	//将根节点和最后一个子节点交换位置后截取掉树的最后一个节点,也就是最大的值,这时大堆被打乱,再对树中剩下的值heapify
	for (int i = size - 1; i >= 0; i--) {
		std::swap(arr[i], arr[0]);
		heapify(arr, i, 0);
	}
}

8、计数排序

void countSort(int size, int* arr) {
	if (!arr || size <= 1) {
		return;
	}

	int index = 0, min, max;
	min = max = arr[0];

	//遍历数组找出最小和最大的数  5  3  4  7  2  4  3  4  7
	for (size_t i = 1; i < size; i++) {
		min = arr[i] < min ? arr[i] : min;
		max = arr[i] > max ? arr[i] : max;
	}

	int len = max - min + 1;
	int* temp = new int[len](); //初始化为0

	for (int i = 0; i < size; i++) {
		temp[arr[i] - min]++;
	}

	//打印下计数数组
	for (int i = 0; i < len; i++)
	{
		std::cout << temp[i] << " ";
	}
	std::cout << std::endl;


	for (int i = min; i <= max; i++)
	{
		int count = temp[i - min];
		for (int j = 0; j < count; ++j)	//存放元素个数不为0的,才进入循环
		{
			arr[index++] = i;  //把元素值写回数组
		}
	}
	delete[] temp;
	temp = nullptr;
}

9、桶排序,将数据按规则分组,对各小组再分别排序

  • 数组长度一定的,只申请一次内存,避免内存碎片化,提高效率
  •  给定桶的个数,程序运行状况在不同环境下可控
void bucketSort(size_t size, int *arr, int bucketCount = 10)
{
	if (!arr || size <= 1) {
		return;
	}

	int maxval = arr[0];
	int minval = arr[0];
	//遍历数组,找出最大最小元素
	for (int i = 0; i != size; ++i)	{
		maxval = maxval > arr[i] ? maxval : arr[i];
		minval = minval < arr[i] ? minval : arr[i];
	}
	//如果最大等于最小,数组不需要排序
	if (maxval == minval){
		return;
	}

	int div = /*1000*/bucketCount; //桶的个数
	int space = (maxval - minval) / div + 1; //每个桶的数值跨度,+1放大一点包住
	int *numsofeachbucket = new int[div](); //开辟数组,存放每个桶内的元素个数,()初始化为0
	int *endpositionofeachbucket = new int[div]();
	for (size_t i = 0; i != size; ++i){
		//把元素按大小分到不同的桶,并增加该桶元素个数
		numsofeachbucket[(arr[i] - minval) / space]++;
		endpositionofeachbucket[(arr[i] - minval) / space]++;
	}
	for (int i = 1; i != div; ++i){
		endpositionofeachbucket[i] += endpositionofeachbucket[i - 1];
		//每个桶区间的最大下标+1的值
	}
	int *temp = new int[size];	//开辟堆空间,存放临时数组
	for (size_t i = 0; i != size; ++i){
		temp[--endpositionofeachbucket[(arr[i] - minval) / space]] = arr[i];
		//遍历数组,把每个元素写入对应的桶中,从每个桶的后部往前写
		//--运行完成后endpositionofeachbucket[i]就是该桶的首位
	}
	for (size_t i = 0; i != div; ++i)
	{
		if (numsofeachbucket[i] > 1)	//桶元素2个或以上才排序
		{
			//对每个桶的数组进行快速排序(元素个数,每个桶数组首位的地址)
			quickSort(numsofeachbucket[i], &temp[endpositionofeachbucket[i]]);
		}
	}

	//对排序后的数组,写入原数组
	for (size_t i = 0; i != size; ++i){
		arr[i] = temp[i];
	}
	delete[] numsofeachbucket;
	delete[] endpositionofeachbucket;
	delete[] temp;
	numsofeachbucket = nullptr;
	endpositionofeachbucket = nullptr;
	temp = nullptr;

}

10、基数排序

void radix_countsort(size_t size, int *arr, int exp)
{
	int numofeachbucket[10] = { 0 };  //十个数位,每个桶上有0个元素
	for (int i = 0; i != size; ++i) {
		++numofeachbucket[(arr[i] / exp) % 10];	//记录该数位上相同的元素个数
	}

	for (int i = 1; i < 10; ++i) {
		numofeachbucket[i] += numofeachbucket[i - 1];
	}

	int *temp = new int[size];
	for (int i = size - 1; i >= 0; --i) {
		int k = (arr[i] / exp) % 10;
		temp[numofeachbucket[k]] = arr[i]; //把数组放在不同的区间位置上
		numofeachbucket[k]--;
	}

	for (int i = 0; i != size; ++i) {
		arr[i] = temp[i];  //一个数位排好后,写回原数组,开始下一位数的装桶排序
	}

	delete[] temp;
	temp = nullptr;
}

void radixSort(size_t size, int *arr)
{
	if (!arr || size <= 1) {
		return;
	}

	int max = arr[0];
	//找出最大的数
	for (size_t i = 0; i != size; ++i) {
		max = arr[i] > max ? arr[i] : max;
	}
	//从最低位开始对每个数位进行排序
	for (int exp = 1; max / exp > 0; exp *= 10) {
		radix_countsort(size, arr, exp);
	}
}

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于十大排序算法中的堆排序、选择排序和冒泡排序算法的C语言实现,可以参考如下代码: 堆排序: ```c void heapify(int *vec, int i, int len) { int left = i * 2 + 1; int right = i * 2 + 2; int largest = i; if (left < len && vec[left > vec[largest]) { largest = left; } if (right < len && vec[right > vec[largest]) { largest = right; } if (largest != i) { int temp = vec[i]; vec[i = vec[largest]; vec[largest = temp; heapify(vec, largest, len); } } void heapSort(int *vec, int len) { for (int i = len / 2 - 1; i >= 0; i--) { heapify(vec, i, len); } for (int j = len - 1; j > 0; j--) { int temp = vec = vec[j]; vec[j = temp; heapify(vec, 0, j); } } ``` 选择排序: ```c void selectionSort(int *vec, int len) { for (int i = 0; i < len - 1; i++) { int minIndex = i; for (int j = i + 1; j < len; j++) { if (vec[j < vec[minIndex]) { minIndex = j; } } if (minIndex != i) { int temp = vec[i]; vec[i = vec[minIndex]; vec[minIndex = temp; } } } ``` 冒泡排序: ```c void bubbleSort(int *vec, int len) { for (int i = 1; i < len; i++) { for (int j = 0; j < len - i; j++) { if (vec[j > vec[j + 1]) { int temp = vec[j]; vec[j = vec[j + 1]; vec[j + 1 = temp; } } } } ``` 这些代码分别实现了堆排序、选择排序和冒泡排序算法,可以通过传入一个整型组和组长度来对组进行排序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [用C++实现十大经典排序算法](https://blog.csdn.net/qq_34139994/article/details/128217009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.239^v12^insert_chatgpt"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值