数据结构 - 排序(C++)

基本概念

  • 稳定性
    如果i==j,且i在j前面,排序完成后i仍旧在j前面则这个排序算法是稳定的,否则不稳定。

插入类排序

  • 直接插入排序
/**
	直接插入排序
时间复杂度:O(n^2)
空间复杂度:O(1) 
*/
void InsertSort(int R[], int n){
	int i, j;
	int temp;
	for(i=1; i<n; ++i){	//第一个元素不用比较 从第二个开始插入 
		temp = R[i];	//将待插入元素暂存 
		j = i-1;		//找到待插入元素前一个元素 
		while(j>=0 && temp<R[j]){	//循环寻找插入位置	若未找到进入循环体 
			R[j+1] = R[j];	//将被比较元素后移 
			--j;	
		}
		R[j+1] = temp;	//找到插入位置 插入元素 
	}
} 
  • 直接选择排序
    在所有元素中选择出最小的,将元素位置与第一个交换,再将剩余元素重复上述过程,直至有序。

  • 折半插入排序

/**
	折半插入排序
时间复杂度:O(n^2)
空间复杂度:O(1) 
*/
void BinaryInsertSort(int R[], int n){
	int low, high, m;	
	int i, j, temp;
	for(i=1; i<n; ++i){	//从第二个元素开始插入 
		low = 0;
		high = i-1;		
		temp = R[i];	//保存插入元素 
		while(low <= high){	 
			m = (low + high)/2;
			if(R[m] > temp)
				high = m-1;
			else
				low = m+1;
		}
		for(j=i-1; j>high; --j)	//将high后面的元素全部后移一位 
			R[j+1] = R[j];
		R[high+1] = temp;  		//插入元素 
	} 
}
  • 希尔排序
/**
	希尔排序 
时间复杂度:O(n^2)
空间复杂度:O(1) 
*/
void ShellSort(int R[], int n){
	int i, j, temp, k; 
	int gap;	//gap为步长	 
	for(gap=n/2; gap>0; gap/= 2){	//将步长每次缩短一半 
		//对gap个子序列全部进行排序 
		for(i=0; i<gap; i++){
			//直接插入排序 
			for( j = i+gap; j<n; j=j+gap){
				if(R[j]<R[j-gap]){
					temp = R[j];
					k = j-gap;
					while(k>=0 && R[k]>temp){
						R[k+gap] = R[k];
						k -= gap;
					}
					R[k+gap] = temp;
				}
			}
		}
	}
}

交换类排序

  • 冒泡排序
/**
	冒泡排序
时间复杂度:O(n^2)
空间复杂度:O(1) 
*/
void BubbleSort(int R[], int n){
	int i, j, flag, temp;
	for(i=n-1; i>=1; --i){	//使下标为 i 的元素始终为最大值 
		flag = 0;			//标记变量 该趟是否发生了改变 
		for(j=1; j<=i; ++j){ 
			if(R[j-1] > R[j]){	//交换元素 
				temp = R[j];
				R[j] = R[j-1];
				R[j-1] = temp;
				flag = 1;		//flag==1 证明该趟发生了交换  
			}
		}
		if(flag == 0)	//如果未发生交换代表序列有序 
			return;
	}
} 
  • 快速排序
/**
	快速排序
时间复杂度:O(n*log2^n)
空间复杂度:O(log2^n) 
*/
void QuickSort(int R[], int low, int high){
	int temp;
	int i=low, j=high;
	if(low < high){	
		temp = R[low];	//保存枢纽元素 
		//循环将元素分为 {小于枢纽 枢纽 大于枢纽} 
		while(i<j){	
			while(j>i && R[j]>=temp) --j;	//从左往右扫描找到小于temp的元素 
			if(i<j){	//放在枢纽元素左边 
				R[i] = R[j];
				++i;
			}
			while(i<j && R[i]<temp)	++i;	//从右往左扫描找到大于temp的元素放在右边 
			if(i<j){
				R[j] = R[i];
				--j;
			}
		}
		R[i] = temp;	//将temp放在最终位置 
		QuickSort(R, low, i-1);	//递归对小于枢纽的元素进行排序 
		QuickSort(R, i+1, high);//递归对大于枢纽的元素进行排序 
	}	
}
  • 堆排序
    先建堆,取堆顶,再重复。堆为一个完全二叉树。

算法比较

排序算法时间复杂度空间复杂度算法稳定性
直接插入排序O(n^2) 最坏、平均
O(n) 最好
O(1)稳定
折半插入排序O(n^2) 最坏、平均
O(n*log2^n) 最好
O(1)稳定
希尔排序O(n^2)O(1)不稳定
冒泡排序O(n^2) 最坏、平均
O(n) 最好
O(1)稳定
快速排序O(n^2) 最坏
O(n*log2^n)最好、平均
O(log2^n)不稳定
简单选择排序O(n^2)O(1)不稳定
堆排序O(n*log2^n)O(1)不稳定
二路归并排序O(n*log2^n)O(n)稳定
基数排序O(d(n+r_d)) 最坏、平均
n:序列关键字数
d:关键字的关键位数
r_d:关键字基的个数
O(r_d)稳定

稳定性:快速排序、希尔排序、简单选择排序、堆排序 是不稳定的,其余都是稳定的。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值