用数组实现 冒泡、选择、插入、堆等排序

冒泡排序:

时间复杂度为:o(N^2)

空间复杂度为:o(1)

稳定性:稳定性排序

编写代码时应注意  加上一个  if  判断条件,如果数组长度size <=1;数组中只有一个元素,不用比较,程序直接退出

使用[0,bound)作为有序区间

[bound,size)作为待排序区间,使用for循环,每次从待排序区间找到一个最小值放入有序区间,循环结束后就实现了冒泡排序

void BubbleSort(int array[], int size){
	if (size <= 1){
		return;
	}
//[0,bound)为有序区间,
//[bound,size)为待排序区间
//每循环一次找到一个最小的元素
	int bound = 0;
	for (; bound < size; bound++){
		int cur = size - 1;
		for (; cur>bound; cur--){
			if (array[cur] < array[cur - 1]){
				swap(&array[cur], &array[cur - 1]);
			}
		}
	}
	return;

}

这里第一层for循环 int bound=0;一直到size,第二层for循环,从数组最后一个元素从后往前遍历,随着 bound 值的增加,每次冒泡都可找出一个最小值放入有序区间。

选择排序:

时间复杂度:o(N^2)

空间复杂度:o(1)

稳定性:不稳定排序

编写代码时应注意  加上一个  if  判断条件,如果数组长度size <=1;数组中只有一个元素,不用比较,程序直接退出

void SelectSort(int array[], int size){
//[0,bound)为有序区间
//[bound,size)为待排序区间
//每次从待排序区间找出一个值array[cur],与array[bound]比较,若小于bound,则交换cur和bound的值。
//每次循环,bound下标++
	//排序前必须先判断size长度,若size小于等于1,就退出排序,只有一个不用再排序
	if (size <= 1){
		return;
	}
	int bound = 0;
	for (; bound < size; bound++){
		int cur = bound;
		for (; cur < size; cur++){
			if (array[bound]>array[cur]){
				swap(&array[bound], &array[cur]);
			}
		}
	}
	return;
}

使用[0,bound)作为有序区间

[bound,size)作为待排序区间,选择 int bound =0; 这个位置的元素作为比较对象,

第一层for 循环bound从零到size,第二层  cur 从bound到size,将每一个元素与bound进行比较,如果小于array[bound]则交换元素,就将最小的值放在了前面。

插入排序:

时间复杂度:o(N^2)

空间复杂度:o(1)

稳定性:稳定排序

编写代码时应注意  加上一个  if  判断条件,如果数组长度size <=1;数组中只有一个元素,不用比较,程序直接退出

void InsertSort(int array[], int size){
	if (size <= 1){
		return;
	}
	//[0,bound)为有序区间
	//[bound,size)为待排序区间
	int bound = 1;
	for (; bound < size; bound++){
		int bound_value = array[bound];
		int i = bound;
		for (; i>0; i--){
			if (array[i - 1] > array[i]){
				//进行数据搬运
				array[i] = array[i - 1];
			}
			else{
				//已经找到了一个合理位置
				//当前数组中的这个元素已经小于bound_value,就需要把bound_value放到这个元素后面
				//即放到下标为i的位置上
				//array[i]=bound_value
				break;
			}
		}
		//下面这行代码表示两重含义:
		//1.当前数组中的这个元素已经小于bound_value,就需要把bound_value放到这个元素后面
				//即放到下标为i的位置上
				//array[i]=bound_value
		//2.处理循环结束的情况,循环结束时,i=0;此时i,和i+1的位置上是数据搬运后的相同元素,
		//没有给i赋值循环就退出了,在循环结束后应该对array[i]赋值,bound_value中存的就是数据未搬移前i中的值。
		array[i] = bound_value;
	}
}

例如   9 5 2 7这四个数,刚开始 限定有序区间就是 [9] ,待排序区间为[5,2,7],然后将待排序区间内的2插入有序区间,因为 9>2 ,将 9 搬移到 2 的位置,再将原来9的位置设成2,将待排序区间内的元素,全部插入有序区间,就完成了排序。

堆排序:

时间复杂度:o(N * log(N))

空间复杂度:o(1)

稳定性:不稳定排序

编写代码时应注意  加上一个  if  判断条件,如果数组长度size <=1;数组中只有一个元素,不用比较,程序直接退出

//index 表示从当前下标开始进行调整
//创建大堆,要求父节点大于左 右子树
void AdjustDown(int array[], int size, int index){
	int parent = index;
	int child = 2 * parent + 1;
	while (child < size){
		//先拿左右子树比较看谁大,再拿大的和父节点比较
		if (child + 1 < size&&array[child + 1] > array[child]){
			//右子树比左子树大,就让child指向右子树
			child = child+1;
		}
		if (array[child] > array[parent]){
			swap(&array[child], &array[parent]);
		}
		else{
			//此时就调整完了
			break;
		}
		parent = child;
		child = 2 * parent + 1;
	}
	return;
}
void HeapCreate(int array[], int size){
	if (size <= 1){
		return;
	}
	//下沉式调整,从后往前遍历,从最后一个非叶子节点开始遍历
	//size-1表示最后一个元素的下标
	//拿着这个下标 -1/2 即得到了当前元素的父节点 
	int i = (size - 1 - 1) / 2;
	for (; i >= 0; i--){
		AdjustDown(array, size, i);
	}

}
void HeapPop(int array[], int size){
	if (size <= 1){
		return;
	}
	swap(&array[0], &array[size - 1]);
	AdjustDown(array, size-1, 0);
}
//堆排序
//时间复杂度:o(N * log(N))
//空间复杂度:o(1)
//稳定性:不稳定排序
void HeapSort(int array[], int size){
	if (size <=1){
		return;
	}
	//1.建立大堆
	HeapCreate(array, size);
	//2.循环删除堆顶元素
	//每次删除一个元素,就把当前最大的值放到数组末尾了
	int i = 0;
	for (; i < size; i++){
		//size数值不变,靠size-1来限定数组长度
		HeapPop(array,size-i);
	}
}

写堆排序之前首先需要建堆

由于这里是要进行升序排序,所以建大堆最好,因为大堆堆顶元素数值最大,只需要循环删除堆顶最大元素,己将堆顶元素与末尾元素交换,这样最大数值的元素就到了数组的末尾,就可以得到一个升序的有序数组。

堆排序需要的代码较多,在此使用单独的函数将其代码封装起来。

单独封装一个向下调整的函数,adjustdown,使用HeapCreate函数创建一个大堆。

再封装一个Heatpop函数把数组中的数由大到小排列。

pop时需要注意,由于是循环删除堆顶元素,每次的size需要-1,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值