十大排序算法(c++)

本文详细介绍了十大排序算法(C++),包括冒泡、插入、希尔、选择、归并、快速、堆、计数、桶和基数排序。阐述了各算法的思路,如冒泡排序通过相邻数比较交换,归并排序采用分治思想等。强调理解排序思想对掌握算法很重要,还提及写博客方便复习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

十大排序算法(c++)

1. 冒泡排序
每一轮都从头开始比较, 比较当前数与后一位数,若当前数大于后一位数则进行交换,每一轮都会在末尾得到一位排序正确的数,因此每一轮比较结束,下一轮的比较范围将缩小(j<n-1-i)

void BubbleSort(int *a,int n)
{
	if (n <=1)
		return;
	for (int i = 0; i<n; i++)
	{
		bool isChange = false;  //判断某一次排序是否有元素交换,若无元素交换,则数组已经有序,可以提前退出
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (a[j] > a[j + 1])
			{
				int temp = a[j + 1];
				a[j + 1] = a[j];
				a[j] = temp;
				isChange = true;
			}
		}
		if (!isChange)
			break;
	}
}

2. 插入排序
每一轮将当前数(a[i])插入到前面已经排序好的合适位置,因此关键是如何找到该合适位置通过不断比较以及移动来找到合适的位置

void InsertionSort(int *a, int n)
{
	for (int i = 1; i < n; i++)
	{
		int value = a[i];
		int j = i - 1;
		for (j; j >= 0; j--)
		{
			if (a[j] > value)
				a[j + 1] = a[j];
			else
			{
				break;
			}
		}
		a[j + 1] = value;
	}

}

3.希尔排序
插入排序的改进

void shellSort(int* a,int n)
{
	int d = n / 2;
	while (d>=1)
	{
		for (int i = d; i <n; i ++)
		{
			int value = a[i];
			int j = i - d;
			for (j; j >= 0; j -= d)
			{
				if (a[j] > value)
					a[j + d] = a[j];
				else
					break;
			}
			a[j + d] = value;
		}
		d = d / 2;
	}
}

4. 选择排序
每一轮从未排序的数组中,选择最小的数放在排序数组的后面,有n个数,需要进行n-1次选择,第一次选出最小的数,第二次选择第2小的数,第三次选出第3小的数。。。。

void SelectionSort(int *a,int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int min = i;
		for (int j = i+1; j < n; j++)
		{
			if (a[j] < a[min])
				min = j;
		}
		if (i != min)
		{
			int temp = a[i];
			a[i] = a[min];
			a[min] =temp;
		}
	}

}

5.归并排序
分治思想,从下而上进行排序

void merge(int *a, int l, int mid, int r)
{
	int *L = new int[mid - l + 1]; //左边数组
	int *R = new int[r - mid];  //右边数组
	for (int i = l; i <= mid; i++)
	{
		L[i - l] = a[i];  //得到左半数组
	}
	for (int j = mid + 1; j <= r; j++)
	{
		R[j - mid - 1] = a[j];  //得到右半部分数组
	}
	int m = 0, n = 0, t = l;
	while (m < (mid - l + 1) && n < (r - mid))  //循环比较左边和右边数组,选出最小的数并重新放回原数组(t++)
	{
		while (m < (mid - l + 1) && L[m] <= R[n])
			a[t++] = L[m++];    
		while (n < (r - mid) && R[n] < L[m])
			a[t++] = R[n++];
	}
	while(m < (mid - l + 1))  //判断左边数组是否有剩余,若有则直接放在原数组a的后面
		a[t++] = L[m++];
	while(n < (r - mid))
		a[t++] = R[n++];

	delete[] L, R;  //释放内存
}

void mergeSort(int *a, int l, int r)
{
	if (l >= r) return;  //递归结束条件
	int mid = l + (r - l) / 2;
	mergeSort(a, l, mid);  //对左边递归
	mergeSort(a, mid + 1, r);  //对右边递归
	merge(a, l, mid, r);  //合并左,右数组   (从下而上排序)
}

6. 快速排序
分治思想,从上而下排序

int findPivot(int *a, int start, int end)
{
	int pivot = a[start];  //令第一个数为分区点,将小于分区点数放在左边,大于分区点的数放在右边
	while (start < end)
	{
		while (start < end&&a[end] >= pivot) //从末尾开始,若大于分区点,则左移一位继续判断,
			end--;
		a[start] = a[end];  //直到找到第一个小于分区点的数,并与start交换放在左边
		while (start < end&&a[start] <= pivot) //同理,再从左边start开始,若小于分区点,则右移继续判断
			start++;
		a[end] = a[start];  //直到找到大于分区点的数,并且与end交换放在右边,
	}
	a[start] = pivot; //此时start=end,
	return start;
}

void quickSort(int *a, int start, int end)
{
	if (start >= end) return;
	int pivot = findPivot(a, start, end);  //(从上而下排序)
	quickSort(a, start, pivot);
	quickSort(a, pivot + 1, end);
}

7. 堆排序
堆排序的思路为:先建立一个大顶堆,然后循环交换堆顶元素和最后一个元素,并且重新调整大顶堆

void makeHeap(int *a, int i, int n)  //大顶堆建立方法(从上而下调整堆结构)
{
	while (i < n)
	{
       int max = i;  //根节点,并假设根节点为最大值
	   int lchild = 2 * i + 1;   //左孩子
	   int rchild = 2 * i + 2; //右孩子
	   if (lchild<n&&a[lchild]>a[max])    //寻找根节点,左,右孩子中的最大值,将最大值放在根节点处
		   max = lchild;
	   if (rchild<n&&a[rchild]>a[max])
		   max = rchild;
	   if (max != i)  //若最大值为孩子节点,则交换孩子节点和最大值
	   {
		   int temp = a[i];
		   a[i] = a[max];
		   a[max] = temp;
		   i = max;  //然后将刚刚交换的孩子节点设为根节点,继续调整下一层子树的堆,(,因为交换根节点和孩子节点后,可能导致子树的堆结构遭到破坏。需要从上往下不断调整)
	   }
	   else break;  //若最大值还是原来的根节点,则不需要调整,直接退出即可
	}
	
}

void heakSort(int *a,int n)  //堆排序的实现
{
	for (int i = n / 2 - 1; i >= 0;i-- )  //从最后一个非叶子节点开始,构建一个大顶堆
	{
		makeHeap(a, i, n);
	}

	for (int i = n - 1; i >= 0; i--)  //将堆顶的最大值,放在数组末尾,然后重新调正大顶堆,此时只需要从根节点往下调整一次即可
	{
		int temp = a[i];
		a[i] = a[0];
		a[0] = temp;
		makeHeap(a, 0, i);
	}
}



8. 计数排序
以空间换时间

void countSort(int *a, int n)
{
	int max = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] > max)
			max = a[i];  //找到原数组中的最大值
	}
	int *temp = new int[max+1];  //建立临时数组,数组下标表示原数组的元素,如:temp[20]=2,表示a中20 出现两次
	for (int i = 0; i < max + 1; i++)
		temp[i] = 0;
	for (int i = 0; i < n; i++)
		temp[a[i]]++;
	int index = 0;
	for (int i = 0; i < max + 1; i++)
	{
		for (int j = 0; j < temp[i]; j++)
			a[index++] = i;
	}
	delete[] temp;  //释放内存
}

9.桶排序
同样是以空间换取时间

void bucketSort(int* a,int n)
{
	int min = a[0];
	int max = a[0];
	for (int i = 0; i < n; i++)  //找到原数组中的最大、最小值
		if (min > a[i])
			min = a[i];
		else
			if (max < a[i])
				max = a[i];

	int b = (max - min) / 5 + 1; //每个桶的容量
	int** temp;  //二维数组
	temp = new int*[5]; 
	for (int i = 0; i < 5; i++)
	{
		temp[i] = new int[n+1];  //建立5个桶,容量为n+1,
	}
	for (int i = 0; i < 5; i++)
		temp[i][n] = 0;  //每个桶的最后一位表示桶中的元素个数

	for (int i = 0; i < n; i++)
	{
      int index = (a[i] - min) /b;  //将原数组中的元素映射到相应的桶中
	  temp[index][temp[index][n]++] = a[i];  //元素加入桶中的同时,相应的桶的最后一位加一,表示桶中元素个数加一
	}
	int i = 0;
	for (int j = 0; j < 5; j++)
	{
		int num = temp[j][n];  //每个桶的数量
		if (num!= 0)
		{
			int *sort = new int[num];
			for (int f = 0; f <num; f++)
				sort[f] = temp[j][f];
			InsertionSort(sort, num);  //对每个桶内部进行排序

			for (int s = 0; s <num; s++)
				a[i++] = sort[s];  //以此将排序后桶中的元素放回原数组
			delete[] sort; //内存释放
		}
	}
	for (int i = 0; i < 5; i++)  //释放二维数组的内存
	{
		delete[] temp[i];
	}
	delete[] temp;
}

10. 基数排序
思路:将数组中的元素先按个为进行排序,然后再按十位进行排序,再按百位进行排序,,,,,以此类推

void radixSort(int* a ,int n)
{
	int max = a[0];
	for (int i = 0; i < n; i++)  //找到原数组中的最大值
	{
		if (a[i] > max)
			max = a[i];
	}

		int maxnum = 0;
		int max1 = max;
		while (max1!=0)  //确定原数组中最大值的位数,桶排序需要进行maxnun次排序
		{
			max1 = max1 / 10;
			maxnum++;
		}

		int** temp = new int*[10];   //建立10个桶
		for (int i = 0; i < 10; i++)
		{
			temp[i] = new int[n+1];  //每个桶容量为n+1,最后一个位表示桶中元素个数
			temp[i][n] = 0;
		}
		int d = 1;
		while (maxnum>0)
		{
			for (int i = 0; i < n; i++)
			{
				int index = (a[i]/d) % 10;  //按位进行储存
				temp[index][temp[index][n]++] = a[i];  //将元素放入相应的桶中,如个位是3的元素,放入下标为3的桶中
			}
			int j = 0;
			int q = 0;
			while (q<10)
			{
				if (temp[q][n] != 0)
				{
					for (int i = 0; i < temp[q][n]; i++)
					{
						a[j++] = temp[q][i];  //按位的大小进行排序
						temp[q][i] = 0;  //清除桶中的数据,以便桶可以进行下次储存数据
					}
						temp[q][n] = 0;//将桶中用于表示桶内数据个数的值置为0,以便下次使用桶
				}
				 q++;
			}
			maxnum--;
			d = d * 10;
	
		}

		for (int i = 0; i < 10; i++)
		{
			delete[] temp[i];
		}
		delete[] temp;
}
  • 注:
    对于十大排序算法,总是写了忘,忘了写,今天终于又重新在博客里面写了写,方便以后复习。排序算法关键还是要先理解各个排序思想,只有理解排序思想后,然后读读别人的代码,自己在动手谢谢,才能够有更深的理解。
    加上前一篇关于二分法的文章,这也算是我第一次写博客,之前学习一直是在笔记本上做笔记,但是感觉手写代码好麻烦,写博客能够方便复习,也希望自己能够尽量多谢谢博客,总结学习的所获,也好再以后进行查修补改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值