冒泡排序:
时间复杂度为: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,