//插排
//稳定
//时间复杂度【最差情况】:O(n^2)
//空间复杂度:O(1)
void InsertSort(int array[], int size)
{
int key;
int i, j;
for (i = 1; i < size; i++){
key = array[i];
for (j = i - 1; j >= 0; j--){
if (key >= array[j]){
break;
}
else{
array[j + 1] = array[j];
}
}
array[j + 1] = key;
}
}
void _InsertSort(int array[], int size, int gap)
{
for (int g = 0; g < gap; g++){
int key;
int i, j;
for (i = gap + g; i < size; i += gap){
key = array[i];
for (j = i - gap; j >= 0; j -= gap){
if (key >= array[j]){
break;
}
else{
array[j + gap] = array[j];
}
}
array[j + gap] = key;
}
}
}
//希排
//1 不稳定
//2 时间复杂度【最差情况】: O(n^2)
void ShellSort(int array[], int size)
{
int gap = size;
while (1){
gap = gap / 3 + 1;
_InsertSort(array, size, gap);
if (gap == 1){
break;
}
}
}
void Swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//不稳定
//时间复杂度 O(n^2)
//选择排序1(每次选择最大的放到最后)
void SelectSort(int array[], int size)
{
//i代表每次还剩多少个数,当剩下一个数的时候,就不要移动了
for (int i = size; i > 1; i--){
int max = 0;//最大值下标
for (int j = 1; j < i; j++){
if (array[j] > array[max]){
max = j;
}
}
Swap(array + max, array + i - 1);
}
}
//选择排序2(每次选择最大的放到最后,同时选择最小的放到最前边)
void SelectSrotOP(int array[], int size)
{
int left = 0, right = size - 1;
while (left < right)
{
int min = left, max = left;
for (int j = left + 1; j <= right; j++){
if (array[j] > array[max]){
max = j;
}
if (array[j] < array[min]){
min = j;
}
}
Swap(array + left, array + min);
//注意!!!
if (max == left){//此时说明最大值下标就是left下标元素
max = min;//此时最大值已经被交换到下标为min了,所以max应该移到min处
}
Swap(array + right, array + max);
left++; right--;
}
}
void AdjustDown(int array[], int size, int root)
{
int left = 2 * root + 1;//左孩子下标
int right = 2 * root + 2;//右孩子下标
if (left >= size){
return;//没有左孩子(右孩子也肯定没有)
}
int max = left;
if (right < size && array[right] > array[left]){
max = right;
}//有孩子,判断大孩子下标
if (array[root] >= array[max]){
return;//如果双亲节点大于大孩子,不用调整
}
Swap(array + root, array + max);//交换大孩子和双亲节点
AdjustDown(array, size, max);
}
void CreateHeap(int array[], int size)
{
//从最后一个非叶子节点
//不断向下调整
for (int i = (size - 1) / 2; i >= 0; i--){
AdjustDown(array, size, i);
}
}
//堆排
//不稳定
//时间复杂度 O(N*logN)
void HeapSort(int array[], int size)
{
//1 建大堆(升序)(找最大值)
CreateHeap(array, size);
for (int i = 0; i < size - 1; i++){
Swap(&array[0], &array[size - 1 - i]);
AdjustDown(array, size - i - 1, 0);
}
}
//冒泡排序
//稳定
//时间复杂度 O(N^2)
void BubbleSort(int array[], int size)
{
for (int i = 0; i < size - 1; i++){
int isSorted = 1;
for (int j = 0; j < size - 1 - i; j++){
if (array[j] > array[j + 1]){
Swap(array + j, array + j + 1);
isSorted = 0;
}
}
if (1 == isSorted){
break;
}
}
}
//快排小的放左、大的放右【左右指针法】
//时间复杂度 O(N)
int Partition_01(int array[], int left, int right)//基准值的下标
{
int begin = left;//不是0
int end = right; //不是right-1
while (begin < end){
//如果基准值在最右边,先动begin
while (begin < end && array[begin] <= array[right]){
begin++;//第二次比较左右下标,防止所有元素都小于基准值,
}
while (begin < end && array[end] >= array[right]){
end--;//第二次比较左右下标,防止所有元素都大于基准值,
}
Swap(array + begin, array + end);
}
Swap(array + begin, array + right);
return begin;//基准值
}
//快排
//时间复杂度 O(N*logN) 最坏情况就是单枝树O(N^2)
//空间复杂度 O(logN) O(N)
//array [left, right]
//左闭右闭
void _QuickSort(int array[], int left, int right)
{
if (left >= right){
return;
}
int div = Partition_02(array, left, right);//基准值的下标
_QuickSort(array, left, div - 1); //[left, div-1]
_QuickSort(array, div + 1, right); //[div+1, right]
}
void QuickSort(int array[], int size)
{
_QuickSort(array, 0, size - 1);
}
//快排小的放左、大的放右【左右挖坑法】
//时间复杂度 O(N)
int Partition_02(int array[], int left, int right)
{
int begin = left;
int end = right;
int pivot = array[right];//pivot 存的就是基准值
while (begin < end){
while (begin < end && array[begin] <= pivot){
begin++;
}
array[end] = array[begin];//补右坑==挖左坑
while (begin < end && array[end] >= pivot){
end--;
}
array[begin] = array[end];//补左坑==挖右坑
}
array[begin] = pivot;
return begin;
}
//快排
//时间复杂度 O(N*logN) 最坏情况就是单枝树O(N^2)
//空间复杂度 O(logN) O(N)
//array [left, right]
//左闭右闭
void _QuickSort(int array[], int left, int right)
{
if (left >= right){
return;
}
int div = Partition_02(array, left, right);//基准值的下标
_QuickSort(array, left, div - 1); //[left, div-1]
_QuickSort(array, div + 1, right); //[div+1, right]
}
void QuickSort(int array[], int size)
{
_QuickSort(array, 0, size - 1);
}
//快排小的放左、大的放右【前后指针】
//时间复杂度 O(N)
int Partition_03(int array[], int left, int right)
{
int div = left;
int cur = left;
while (cur < right){
if (array[cur] < array[right]){
Swap(array + cur, array + div);
div++;
}
cur++;
}
Swap(array + div, array + right);
return div;
}
//快排
//时间复杂度 O(N*logN) 最坏情况就是单枝树O(N^2)
//空间复杂度 O(logN) O(N)
//array [left, right]
//左闭右闭
void _QuickSort(int array[], int left, int right)
{
if (left >= right){
return;
}
int div = Partition_03(array, left, right);//基准值的下标
_QuickSort(array, left, div - 1); //[left, div-1]
_QuickSort(array, div + 1, right); //[div+1, right]
}
void QuickSort(int array[], int size)
{
_QuickSort(array, 0, size - 1);
}
附加讲解:(快排不稳定)
选择基准值的方法:1)最边上(最左、最右)
2)随机
3)三数取中
void Merge(int array[], int left, int mid, int right, int *extra)
{
int left_i = left;
int right_i = mid;
int extra_i = left;
while (left_i < mid && right_i < right){
if (array[left_i] <= array[right_i]){
extra[extra_i++] = array[left_i++];
}
else{
extra[extra_i++] = array[right_i++];
}
}
while (left_i < mid){
extra[extra_i++] = array[left_i++];
}
while (right_i < right){
extra[extra_i++] = array[right_i++];
}
for (int i = left; i < right; i++){
array[i] = extra[i];
}
}
//归并排序
//时间复杂度 O(N*logN)
//空间复杂度 O(N)
//array [left, right)
//左闭右开
void _MergeSort(int array[], int left, int right, int *extra)
{
if (left == right - 1){
return;//[0,1)
}
if (left >= right){
return;//区间没有数了
}
int mid = left + (right - left) / 2;
_MergeSort(array, left, mid, extra);//[left, mid)//左边排有序
_MergeSort(array, mid, right, extra);//[mid, right)//右边排有序
Merge(array, left, mid, right, extra);//整体合并成有序
}
void MergeSort(int array[], int size)
{
int *extra = (int *)malloc(size * sizeof(int));
_MergeSort(array, 0, size, extra);//左闭右开
free(extra);
}
归排稳定
总结: