外部排序:指数据不能一次性加载到内存里去
内部排序:指数据能一次性加载到内存里去
非比较排序:不用比较就能进行的排序
比较排序:进行比较才能进行的排序
稳定性:如两个学生按照学号排:a在b的前面,按照成绩排a还是在b的前面,则这种排序算法是稳定的;若是如两个学生按照学号排:a在b的前面,按照成绩排b在a的前面,则是不稳定的(成绩是有序的)
排序算法分类:
1、插入排序:
内部排序:指数据能一次性加载到内存里去
非比较排序:不用比较就能进行的排序
比较排序:进行比较才能进行的排序
稳定性:如两个学生按照学号排:a在b的前面,按照成绩排a还是在b的前面,则这种排序算法是稳定的;若是如两个学生按照学号排:a在b的前面,按照成绩排b在a的前面,则是不稳定的(成绩是有序的)
排序算法分类:
1、插入排序:
插入排序
.h
# pragma once
# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# include<assert.h>
//插入排序
void PrintArray(int *array, int size);
void InsertSort(int *array, int size);
.c
# include"paixu1.h"
void PrintArray(int *array, int size)
{
int i = 0;
for (; i < size; ++i)
{
printf("%d", array[i]);
}
printf("\n");
}
void InsertSort(int *array, int size)
{
int i = 1;
for (; i < size; ++i)
{
int key = array[i];
int end = i - 1;
//查找待插入元素的位置
while (end >= 0 && key < array[end])
{
array[end + 1] = array[end];
--end;
}
//key大于end+1处的元素
array[end + 1] = key;
}
}
void TestChaRuSort()
{
int array[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
PrintArray(array, sizeof(array) / sizeof(array[0]));
InsertSort(array, sizeof(array) / sizeof(array[0]));
PrintArray(array, sizeof(array) / sizeof(array[0]));
}
test.c
# include"paixu1.h"
void PrintArray(int *array, int size)
{
int i = 0;
for (; i < size; ++i)
{
printf("%d", array[i]);
}
printf("\n");
}
void InsertSort(int *array, int size)
{
int i = 1;
for (; i < size; ++i)
{
int key = array[i];
int end = i - 1;
//查找待插入元素的位置
while (end >= 0 && key < array[end])
{
array[end + 1] = array[end];
--end;
}
//key大于end+1处的元素
array[end + 1] = key;
}
}
void TestChaRuSort()
{
int array[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
PrintArray(array, sizeof(array) / sizeof(array[0]));
InsertSort(array, sizeof(array) / sizeof(array[0]));
PrintArray(array, sizeof(array) / sizeof(array[0]));
}
结果:
(1)插入排序用二分法优化
begin标记起始地址,end标记最后一个元素的位置;key与中间元素进行比较
搬移元素的次数没改变,但是比较的次数相对于未优化的场景减少了;插入排序适用于(1、数据接近于有序的情况时间复杂度为O(n),不用搬移数据;2、适用于数据量较小的、元素个数较少的)
头文件及测试代码同上
.c
# include"paixu1.h"
void PrintArray(int *array, int size)
{
int i = 0;
for (; i < size; ++i)
{
printf("%d", array[i]);
}
printf("\n");
}
void InsertSort(int *array, int size)
{
int i = 1;
for (; i < size; ++i)
{
int key = array[i];
int begin = 0;
int end = i - 1;
int mid =-1;
//通过二分查找查找待插入元素的位置
while (begin<=end)
{
mid = begin + ((end - begin) >> 1);
if (key>=array[mid])
begin = mid + 1;
else
end = mid - 1;
}
//搬移元素
end = i - 1;
while (end >= begin)
{
array[end + 1] = array[end];
--end;
}
array[begin] = key;
}
}
void TestChaRuSort()
{
int array[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
PrintArray(array, sizeof(array) / sizeof(array[0]));
InsertSort(array, sizeof(array) / sizeof(array[0]));
PrintArray(array, sizeof(array) / sizeof(array[0]));
}
2、希尔排序
void ShellSort(int *arr,int sz)
{
int i=1;
int gap=3;
while(gap>0)
{
for(i=gap;i<sz;i++){
int key=arr[i];
int end=i-gap;
while(end>=0&&key<arr[end]){
arr[end+gap]=arr[end];
end-=gap;
}
arr[end+gap]=key;
}
gap--;
}
}
关于gap取值的多种方式:
1、首先将gap直接给为size,每次给gap直接除二
2、每次都给gap取一些素数,直至取到1为止
3、每次让gap取gap除三加1的方式,gap从size的位置开始,效率很高。代码如下:
void shellSort(int *array, int size)
{
int i = 1;
int gap = size;
while (gap>1)//因为按照这种方式,gap最后一次的取值一定是1而不是0
{
gap = gap / 3 + 1;
for (i = gap; i < size; ++i)//第一个分组的排序
{
int key = array[i];
int end = i - gap;
//查找待插入元素的位置
while (end >= 0 && key < array[end])
{
array[end + gap] = array[end];
end -= gap;
}
//插入元素
array[end + gap] = key;
}
}
}