几种常用的排序算法
冒泡排序
最好时间复杂度O(n)
,最坏时间复杂度O(n^2)
,平均时间复杂度O(n^2)
基本理论:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个
- 每趟从第一对相邻元素开始,对每一对相邻元素作同样的工作,直到最后一对
- 针对所有的元素重复以上的步骤,除了已排序过的元素(每趟排序后的最后一个元素),直到没有任何一对数字需要比较
void bubble(int *array, int n)
{
for (size_t i = 0; i < n-1; i++) {
if (*(array+i) > *(array+i+1))
swapInt(array+i, array+i+1);
}
}
void bubbleSort(int *array, int n)
{
for (size_t i = n; i > 0; i--) {
bubble(array, i);
}
}
冒泡排序算法的优化,判断本次循环是否有交换,要是没有交换,则说明以及是数组是顺序的,不需要继续判断。
void bubbleSortOptimization(int *array, int n)
{
int isSwap = 0;
for (size_t j = n-1; j > 0; j--) {
isSwap = 0;
for (size_t i = 0; i < j; i++) {
if (*(array+i) > *(array+i+1)) {
swapInt(array+i, array+i+1);
array+i+1
isSwap = 1;
}
}
if (!isSwap)
break;
}
}
继续对冒泡排序继续优化,保存每次小循环最后一次最后一个位置,该位置之后都是有序的,不需要排序后面的数字
void bubbleSortOptimization1(int *array, int n)
{
int pos = n-1;
int isSwap = 0;
for (size_t j = n-1; j > 0; j--) {
isSwap = 0;
int newPos = 0;
for (size_t i = 0; i < pos; i++) {
if (*(array+i) > *(array+i+1)) {
swapInt(array+i, array+i+1);
isSwap = 1;
newPos = i;
}
}
if (!isSwap)
break;
pos = newPos;
}
}
选择排序
最好时间复杂度O(n^2)
,最坏时间复杂度O(n^2)
,平均时间复杂度O(n^2)
基本理论:
- 首先在未排序序列中找到最大元素,存放到排序序列的最后位置
- 再从剩余未排序元素中继续寻找最大元素,然后放到未排序序列的最后位置
- 重复第二步,直到所有元素均排序完毕
int findMaxPos(int *array, int n)
{
int pos = 0;
int max = array[0];
for (size_t i = 1; i < n; i++) {
if (array[i] > max) {
max = array[i];
pos = i;
}
}
return pos;
}
void selectSort(int *array, int n)
{
while (n > 1) {
int pos = findMaxPos(array, n);
swapInt(array+n-1, array+pos);
n--;
}
}
选择排序的排序,在一次遍历中同时找出最大值和最小值,放到数组两端,这样就能将遍历的趟数减少一半
void selectionSortOptimize(int * num, int size)
{
int left = 0, right = size - 1;
while (left < right){
int min = left, max = right;
for (size_t i = left; i <= right; i++){ //内循环同时找出最大值和最小值
if(num[i] < num[min])
min = i;
if(num[i] > num[max])
max = i;
}
swapInt(&num[max], &num[right]);
swapInt(&num[min], &num[left]);
left++;
right--;
}
return ;
}
插入排序
最好时间复杂度O(n)
,最坏时间复杂度O(n^2)
,平均时间复杂度O(n^2)
基本思想:将无序数组中的数据插入到有序数组中合适的位置。
void insert(int *array, int n)
{
int i = n;
int key = array[n]; //设置一个key保留
while (array[i-1] > key){
array[i] = array[i-1]; //数字是向后移动的
i--;
if (0 == i)
break;
}
array[i] = key;
}
void insertSort(int *array, int n)
{
for (size_t i = 1; i < n; i++) {
insert(array, i); ‣n: i
}
}
快速排序
最好时间复杂度O(nlog2n)
,最坏时间复杂度O(n^2)
,平均时间复杂度O(nlog2n)
- 先从数列中取出一个数作为基准数
- 将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
- 再对左右区间重复第二步,直到各区间只有一个数
void qSort(int *array, int begin, int end)
{
if (begin>end)
return;
int key = array[begin];
int i = begin, j = end;
while (i < j) {
/*从右往左找到第一个比key小的数值*/
while (i<j && *(array+j) >= key)
j--;
/*从左往右找到第一个比key大的数值*/
while (i<j && *(array+i) <= key)
i++;
swapInt(array+i, array+j); //交换两者的大小
}//循环跳出来时i和j指向同一个位置,此时key左面的都比key小,key右面的都比key大
swapInt(array+begin, array+j); //此时i或者j的位置就是基准值应该放的位置,交换
qSort(array, begin, i-1); ‣end: i-1
qSort(array, i+1, end); ‣begin: i+1
return;
}
二分查找算法
查找的前提是数组以及拍好序了
int binarySearch(int *array, int key, int low, int high)
{
while (low<=high) {
int mid = (low+high)/2;
if (key == *(array+mid)) {
return mid;
}else if (key > *(array+mid)) {
low = mid+1;
}else {
high = mid-1;
}
}
return -1;
}
int binarySearch_recursive(int *array, int key, int low, int high)
{
if (low > high)
return -1;
int mid = low+(high-low)/2;
if (*(array+mid) == key) {
return mid;
}else if (*(array+mid) > key) {
return binarySearch_recursive(array, key, low, mid-1);
}else {
return binarySearch_recursive(array, key, mid+1, high);
}
}