目录
插入排序
1.基本思想
2.单个元素插入有序数组图解
int arr[5]={1,2,4,5};
2.然后在比较4与3的大小,发现4比3大,那么4往后移动,覆盖后一个位置的值:
3.在继续比较2与3的大小,发现2比3小,那么此时2后边的位置就是待插入的位置,把3插入后:
完成了将3插入依然保证数组升序。注意:此时的插入只能从后往前比较,因为数组后有空位置。
完成了在单个升序数组中将元素插入,这一操作给了我们启发,假如现在有一乱序的数组,我们怎么进行插入排序呢?
3.插入排序图解
给定一组数据:
int arr[5]={6,2,1,3,4};
1.首先可以将数组的第一个元素6看作是一个升序数组,那么问题就变成了将数字2进行插入,使前两个元素称为一个升序的数组,插入2后:
2.此时将上图中2和6看作是一个升序的数组,数字1为待插入的数值,将1插入后:
3.再将1、2、6这三个数值看作一个升序数组,数字3为待插入数值,插入后:
4.最后一次将前四个数值看作是一个升序的数组,将数值4进行插入,插入后:
完成以上步骤就完成了整个的插入排序。
4.代码
void InsertSort(int* arr, int size){
for (int i = 0; i < size - 1;i++){
int end = i;//记录每次待插入数值前一个位置的数组下标
int data = arr[end + 1];//待插入的数值
while (end >= 0 && arr[end]>data){
arr[end + 1] = arr[end];
end--;
}
arr[end + 1] = data;
}
}
在以上代码中,外层循环表示要插入的轮数,比如有5个元素,那么就要进行4轮插入。内层循环的作用是寻找每次插入的位置。注意:end从0开始,此时满足一开始将第一个元素视作单独数组,而且end<size-1;那么arr[end+1]也刚好不会越界,满足要求。
5.复杂度与稳定性
时间复杂度:O(N^2);
空间复杂度:O(1);
稳定性:稳定(注意while循环中arr[end]<data,不能带等号)
希尔排序
1.基本思想
2.图解
假如有以下一组数据:
int arr[]={2,6,3,8,4,1,7,9,5};
1.开始给定整数为gap=3,分组后对每一组分别排序:
2.gap自减1,接下来距离为2是一组,分组后对每一组分别排序:
3.gap在自减1,最后一次每1个一组,分组后对每一组分别排序:
以上步骤就是用希尔排序的思想完成的。
3.代码
void ShellSort(int* arr,int size){
int gap = 3;
while (gap){
for (int i = 0; i<size-gap; i++){
int end = i;
int data = arr[end + gap];
while (end>=0&&arr[end]>data){
arr[end + gap] = arr[end];
end -= gap;
}
arr[end + gap] = data;
}
gap--;
}
}
根据上述代码,可以发现希尔排序内部利用插入排序进行的,只是将数据划分成了组,进行了多次排序,所以说:希尔排序是对直接插入排序的优化。
此时注意end的取值范围,必须保证end+gap不能越界。
4.复杂度与稳定性
时间复杂度:
空间复杂度:O(1)
稳定性:不稳定