外部排序:指数据不能一次性加载到内存里去
内部排序:指数据能一次性加载到内存里去
非比较排序:不用比较就能进行的排序
比较排序:进行比较才能进行的排序
稳定性:如两个学生按照学号排: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、希尔排序
.c
源文件及测试代码同未优化的插入排序
void shellSort(int *array, int size) { int i = 1; int gap = 3;//将分组的间隔给为3 while (gap>0) { 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; } 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;//将分组的间隔给为3 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; } } }