C++实现七种经典排序算法

利用C++实现七种常见的排序算法:

具体的排序方法如下所示:

(1)冒泡排序

基本思想:比较相邻的两个数,如果前者比后者大,则进行交换。每一轮排序结束,选出一个未排序中最大的数放到数组后面。常见冒泡排序算法如下所示:

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

升级版冒泡排序法:通过从低到高选出最大的数放到后面,再从高到低选出最小的数放到前面,如此反复,直到左边界和右边界重合。当数组中有已排序好的数时,这种排序比传统冒泡排序性能稍好。

void superbubblesort(int *arr,int n)
{
	int left = 0, right = n-1;
	while(left <right)
	{
		for(int i = left; i<right;i++)
		{
			if(arr[i]>arr[i+1])
			{
				int tempi = arr[i];
				arr[i] = arr[i+1];
				arr[i+1] = tempi;
			}
		}
		right--;
		for (int j = right; j >left; j--)
		{
			if(arr[j]>arr[j+1])
			{
				int tempj = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tempj;
			}
		}
		left++;
	}
}

(2)快速排序

基本思想:选取一个基准元素,通常为数组最后一个元素(或者第一个元素)。从前向后遍历数组,当遇到小于基准元素的元素时,把它和左边第一个大于基准元素的元素进行交换,即从前往后找小的,从后往前找大的。利用分治策略从已经分好的两组中分别进行以上步骤,直到排序完成。

//把值进行交换
void swap(int *x,int *y)
{
	int temp = *x;
	*x = *y;
	*y = temp;
} 

//把数组分成两部分
int partition(int *a,int left ,int right)
{
	int j = left;  //用来遍历数组 
	int i = j-1;  //用来指向小于基准元素的位置
	int key = a[right]; //基准元素
	//快速排序的思想,从前往后找大于基准元素的放到右边
	for (; j < right; ++j)
	{
		if(a[j] <= key)
			swap(&a[j], &a[++i]);
	}
	//把基准元素放到中间
	swap(&a[right], &a[++i]);
	//返回数组中间的位置
	return i;
}

//快速排序的函数
void quicksort(int *a,int left ,int right)
{
	if(left >= right)
		return;
	int mid = partition(a,left,right);
	quicksort(a,left,mid-1);
	quicksort(a,mid+1,right);
}

(3)直接插入排序

基本思想:和交换排序不同的是它不用进行交换操作,而是用一个临时变量存储当前值。当前面的元素比后面大时,先把后面的元素存入临时变量,前面元素的值放到后面元素位置,再到最后把其值插入到合适的数组位置。所以相应的辅助空间为O(1)。

void insertsort(int *a ,int n)  //直接插入排序
{
	int temp =0;
	for (int i = 1; i < n; i++)
	{
		int j =i - 1;
		if(a[i]<a[j])
		{
		  temp = a[i];
		  a[i] = a[j];
		  while(temp <a[j-1])
		   {
			a[j] = a[j-1];
			j--;
		    }
		  a[j] = temp;
		}
	}
}

(4)希尔排序

基本思想: 在直接插入排序的思想下设置一个最小增量dk,刚开始dk设置为n/2。进行插入排序,随后再让dk=dk/2,再进行插入排序,直到dk为1时完成最后一次插入排序,此时数组完成排序。

void shellsort(int *a ,int n) //希尔排序主函数
{
	int dk =n/2;
	while (dk>1)
	{
		shellinsertsort(a , n , dk);
		dk /= 2;
	}
}

void shellinsertsort(int *a ,int n,int dk)
{
	for (int i = dk; i < n; i++)
	{
		int j = i-dk;
		if(a[i]<a[j])
		{
			int tmp = a[i];
			a[i] = a[j];
			while(a[j]>tmp)
			{
				a[j+dk] =a[j];
				j-=dk;
			}
			a[j+dk] = tmp;
		}
	}
}

(5)直接选择排序

基本思想:依次选出数组最小的数放到数组的前面。首先从数组的第二个元素开始往后遍历,找出最小的数放到第一个位置。再从剩下数组中找出最小的数放到第二个位置。以此类推,直到数组有序。

void selectsort(int *a ,int n)
{
	for (int i = 0; i < n; i++)
	{
		int key = i;  //临时变量用来存储最小的变量
		for (int j = i+1; j < n; j++)
		{
			if(a[j]<a[key])
				key =j; //交换,找到最小的数值
		}
	    if(key !=i)
	    {
			int temp = a[key];
			a[key] = a[i];
			a[i] =temp;
	    }
	}
}

(6)堆排序

基本思想:先把数组构造成一个大顶堆(父亲节点大于其子节点),然后把堆顶(数组最大值,数组第一个元素)和数组最后一个元素交换,这样就把最大值放到了数组最后边。把数组长度n-1,再进行构造堆,把剩余的第二大值放到堆顶,输出堆顶(放到剩余未排序数组最后面)。依次类推,直至数组排序完成。

//进行堆排序,依次选出最大值放在最后面
void heapsort(int *a ,int n)
{
	creatheap(a,n/2-1,n);
	for (int j = n-1; j >=0; j--)
	{
		int temp = a[0];
		a[0] = a[j];
		a[j] =temp;

		int i = j/2-1;
		creatheap(a, i, j);
	}
}

//  创建大堆顶,i为当前节点,n为堆的大小
//    从第一个非叶子结点i从下至上,从右至左调整结构
//    从两个儿子节点中选出较大的来与父亲节点进行比较
//    如果儿子节点比父亲节点大,则进行交换
void creatheap(int *a,int i,int n)
{
	for(;i>=0;--i)
	{
		int left = i*2 + 1;  //左子树结点  
		int right = i*2 + 2; //右子树结点
		int j =0;
		if(right < n)
		{
			a[left]>a[right] ? j=left : j = right;
		}
		else
			j=left;
		if(a[j] >a[i])
		{
			int temp = a[i];
			a[i] = a[j];
			a[j] =temp;
		}
	}
}

(7)归并排序

基本思想:归并算法应用到分治策略,简单说就是把一个大的问题分解成易于解决的小问题后一个个解决,最后在把小问题的一步步合并成总问题的解。这里的排序应用递归来把数组分解成一个个小数组,直到小数组的数有序,再把有序的小数组两两合并而成有序的大数组。

void mergesort(int *a ,int left ,int right)
{
	if(left >right)
		return ;
	int mid = (left+right)/2;
	mergesort(a, left , mid-1);
	mergesort(a, mid+1, right);
	merge(a, left ,right ,mid);
}

//合并两个已经排好序的数组
void merge (int *a ,int left, int mid ,int right)
{
	int len = right -left + 1;  //数组的长度
	int *temp = new int[len];  //分配len个长度的临时数组
	int k = 0;
	int i = left ;
	int j = mid +1;
	while (i<=mid && j<=right)
	{
		//选择较小的存入临时数组
		temp[k++] = a[i] <= a[j] ? a[i++] : a[j++];
	}
	while(i<= mid)
	{
		temp[k++] = a[i++];
	}
	while(j<=right)
	{
		temp[k++] = a[j++];
	}
	for (int k = 0; k < len; k++)
	{
		a[left++] = temp[k];
	}
}

运行,对相应的函数建立头文件,在主函数进行调用,主函数代码如下:

#include <iostream>
#include "BubbleSort.h"
#include "QuickSort.h"
#include "InsertSort.h"
#include "SelectSort.h"
#include "MergeSort.h"

using namespace std;

void main()
{

	int arr[] = {10,6,5,2,3,8,7,4,9,1};
	int n = sizeof(arr) / sizeof(arr[0]);
	for(int i = 0; i < n ; i++)
		cout<<arr[i]<<" ";
	cout<<endl;
	
	bubblesort(arr, n);
	/*
	最差时间复杂度为O(n^2);
	平均时间复杂度为O(n^2);
	稳定性:稳定;
	辅助空间O(1)
	*/
	superbubblesort(arr,n);
	/*
	这种排序比传统冒泡排序性能稍好
	*/
	quicksort(arr,0,n-1);
	/*
	最差时间复杂度:O(n^2);
	最优时间复杂度:O(nlogn);
	平均时间复杂度:O(nlogn);
	稳定性:不稳定的;
	辅助空间:O(nlogn)
	*/
	insertsort(arr,n);
	/*
	最差时间复杂度:O(n^2);
	最优时间复杂度:O(n);
	平均时间复杂度:O(n^2);
	稳定性:稳定;
	辅助空间:O(1)
	*/
	shellsort(arr,n);
	/*
	最差时间复杂度:O(n^2);
	最优时间复杂度:O(n);
	平均时间复杂度:O(n^1.3);
	稳定性:不稳定的;
	辅助空间:O(1)
	*/
	selectsort(arr,n);
	/*
	最差时间复杂度:O(n^2);
	最优时间复杂度:O(n^2);
	平均时间复杂度:O(n^2);
	稳定性:不稳定的;
	辅助空间:O(1)
	*/
	heapsort(arr,n);
	/*
	最差时间复杂度:O(nlogn);
	最优时间复杂度:O(nlogn);
	平均时间复杂度:O(nlogn);
	稳定性:不稳定的;
	辅助空间:O(1)
	*/
	mergesort(arr,0,n-1);
	/*
	最差时间复杂度:O(nlogn);
	最优时间复杂度:O(nlogn);
	平均时间复杂度:O(nlogn);
	稳定性:不稳定的;
	辅助空间:O(n)
	*/

	for(int i = 0; i < n ; i++)
		cout<<arr[i]<<" ";
	cout<<endl;
}

 

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值