希尔算法:
希尔算法是在插入排序上的改进,因为插入排序在基本有序的队列中,会排序很快,所以希尔算法相比插入排序,是通过循环将数组变成基本有序。
先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前三种方法有较大提高。
分组规则:分组数=数据总数/3+1
void ShellSort(int arr[], int length)
{
int increasement = length;
int i, j, k;
do
{
//确定分组的增量
increasement = increasement / 3 + 1;
for (i = 0; i < increasement;i++)
{
for (j = i + increasement; j < length;j+=increasement)
{
//从小到大
if (arr[j]<arr[j-increasement])
{
int temp = arr[j];
for (k = j - increasement; k >= 0 && temp < arr[k];k-=increasement)
{
arr[k + increasement] = arr[k];
}
arr[k + increasement] = temp;
}
}
}
} while (increasement>1);
}
快速排序
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法
分治法基本思想
先从数列中取出毅哥数作为基准数(枢轴)。
分区过程将比这个数大的数全放到他的右边,小于或者等于的数全放在左边(升序)。
在对左右区间重复第二步,指导各区间只有一个数字。
排序思想:
//快速排序 从小到大
void QuickSort(int arr[], int start, int end)
{
int i = start;
int j = end;
///基准数
int temp = arr[start];
if (i<j)
{
while (i < j)
{
//从右向左找比基准数小的
while (i<j&&temp<=arr[j])
{
j--;
}
//填坑
if (i < j)
{
arr[i] = arr[j];
i++;
}
//从左向右 找比基准数大
while (i<j&&temp>arr[i])
{
i++;
}
//填坑
if (i < j)
{
arr[j] = arr[i];
j--;
}
}
//把基准数放到i或者j位置
arr[i] = temp;
//递归
//对左半部分,快速排序
QuickSort(arr, start, i - 1);
//对右半部分,快速排序
QuickSort(arr, i+1, end);
}
}
当第一次循环结束后,标志位左边应该都小于上述代码的temp,右边都大于。在分别左右两边进行排序,所以要用到递归。
归并算法:
基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
1.将数组分为两组,然后分别对两组再次进行分组,当每组数字为一个时,这时每组可以看作有序数组。
2.将每组合并,在合并过程中进行排序,将排序后的数组放入临时数组中。
下图为数组分组,用到了递归
//合并算法 从小到大
void Merge(int arr[], int start, int end, int mid, int *temp)
{
int i_start = start;
int i_end = mid;
int j_start = mid + 1;
int j_end = end;
int length = 0;//辅助空间长度
//合并两个有序序列
while (i_start<=i_end&&j_start<=j_end)
{
if (arr[i_start]<arr[j_start])
{
temp[length] = arr[i_start];
i_start++;
length++;
}
else
{
temp[length] = arr[j_start];
j_start++;
length++;
}
}
//i这个序列 上个步骤遍历结束之后 i,j中不知道哪一个序列中会有一个数字没有输出
while (i_start<=i_end)
{
temp[length] = arr[i_start];
i_start++;
length++;
}
//j这个序列
while (j_start <= j_end)
{
temp[length] = arr[j_start];
j_start++;
length++;
}
//把辅助空间 覆盖原空间
for (int i= 0; i< length;i++)
{
arr[start + i] = temp[i];
}
}
堆算法:
完全二叉树
堆排序用到的就是完全二叉树的模型
堆排序的核心思想就是要首先初始化大顶堆(每个节点都大于他的子节点,所以上图中A的值最大,B,C为第二大第三大)。
最后一个有子节点的数 = 总节点数/2
E的位置= 10/2 = 5
1.初始化大顶堆