排序算法(二)

### 排序算法(二)
```c
/////////////////////////////////////////////////////////////
//归并排序(递归)
//时间复杂度:O(N * logN)
//空间复杂度:O(N)
//稳定性:稳定排序
////////////////////////////////////////////////////////////

void _MergeArray(int array[], int64_t beg, int64_t mid,  int64_t end, int* tmp){
    int64_t cur1 = beg;
    int64_t cur2 = mid;
    int64_t tmp_index = beg;
    while(cur1 < mid && cur2 < end){
        if(array[cur1] < array[cur2]){
            tmp[tmp_index++] = array[cur1++];
        }else{
            tmp[tmp_index++] = array[cur2++];
        }
    }
    while(cur1 < mid){
        tmp[tmp_index++] = array[cur1++];
    }
    while(cur2 < end){
        tmp[tmp_index++] = array[cur2++];
    }
    //进行归并的时候处理的区间是 array[beg, end),
    //对应的会把这部分区间元素填充到 tmp[beg, end)
    memcpy(array + beg, tmp + beg, sizeof(int) * (end - beg));
    return;
}

void _MergeSort(int array[], int64_t beg, int64_t end, int* tmp){
    if(end - beg <= 1){
        //要么一个元素,要么没有元素,要么非法区间
        return;
    }
    int64_t mid = beg +(end - beg) / 2;
    //此时有了两个区间[beg, mid), [mid, end)
    _MergeSort(array, beg, mid, tmp);
    _MergeSort(array, mid, end, tmp);
    _MergeArray(array, beg, mid,  end, tmp);
    return;
}

void MergeSort(int array[], size_t size){
    int* tmp = (int*)malloc(sizeof(int) * size); 
    _MergeSort(array, 0, size, tmp);
    free(tmp);
}


/////////////////////////////////////////////////////////////
//归并排序
//时间复杂度:O(N * logN)
//空间复杂度:O(N)
//稳定性:稳定排序
////////////////////////////////////////////////////////////

void MergeSortByLoop(int array[], size_t size){
    if(size <= 1){
        return;
    }
    int* tmp = (int*)malloc(sizeof(int) * size);
    size_t gap = 1;
    for(; gap < size; gap *= 2){
        //在当前gap下,使用i帮助我们完成所有长度为gap的区间合并
        size_t i = 0;
        for(;i < size; i += 2 * gap){
            size_t beg = i;
            size_t mid = i + gap;
            //为了防止 mid超出数组最大size
            if(mid > size){
                mid = size;
            }
            size_t end = i + 2 * gap;
            if(end > size){
                end = size;
            }
            _MergeArray(array, beg, mid, end, tmp);
        }
    }
    free(tmp);
}


/////////////////////////////////////////////////////////////
//快速排序
//时间复杂度:O(N * logN) 最坏情况O(N ^ 2)
//空间复杂度:最坏O(N)
//稳定性:不稳定排序
////////////////////////////////////////////////////////////

//取一个基准值,倒腾,使前半部分小于基准值,后半部分大于基准值
//如果逆序,快排就不合适,递归可能很深,针对小数组不合适
// C++ STL std::sort
// 1.选取基准值的的方法:三个元素选中间值
// 2.当递归深度达到一定值的时候,就不在继续递归,而是把排序算法转化成堆排序
// 3.当递归达到一定程度之后,子区间的元素个数已经比较小,把排序算法编程插入排序

//交换法
int64_t Partion(int array[], int64_t beg, int64_t end){
    if(end - beg <= 1){
        return beg;
    }
    int64_t left = beg;
    int64_t right = end - 1;
    //数组的最后一个元素作基准元素
    int key = array[right];
    //从左往右找一个大于key的值
    while(left < right){
        while(left < right && array[left] <= key){
            ++left;
        }
        //从右往左找一个小于key的值
        while(left < right && array[right] >= key){
            --right;
        }
        if(left < right){
            Swap(&array[left], &array[right]);
        }
    }
    //最后把left指向的位置和基准值交换
    Swap(&array[left], &array[end - 1]);
    return left;
}

void  _QuickSort(int array[], int64_t beg, int64_t end){
    if(end - beg <= 1){
        return;
    }
    //[beg, mid),左半区间
    //[mid + 1, end],右半区间
    //
    int64_t mid = Partion(array, beg, end);
    _QuickSort(array, beg, mid);
    _QuickSort(array, mid + 1, end);
}

void QuickSort(int array[], size_t size){
    _QuickSort(array, 0, size);
    return;
}

//挖坑法
int64_t Partion2(int array[], int64_t beg, int64_t end){
    if(end - beg <= 1){
        return beg;
    }
    int64_t left = beg;
    int64_t right = end - 1;
    //数组的最后一个元素作基准元素
    int key = array[right];
    while(left < right){
        while(left < right && array[left] <= key){
            ++left;
        }
        if(left < right){
            array[right--] = array[left];
        }
        while(left < right && array[right] >= key){
            --right;
        }
        //循环可以退出,意味着 right 指向了一个小于基准值的元素,
        //就可以把这个值填到刚才left 指向的坑里
        //一旦复制操作完成,right自身又成了一个坑
        if(left < right){
            array[left++] = array[right];
        }
    }
    //一旦left 和right重合,说明整个区间整理完毕
    //但是还有一个坑
    array[left] = key;
    return left;
}

//3.双指针前移法
//略

//非递归版本快速排序
void QuickSortByLoop(int array[], size_t size){
    if(size <= 1){
        return;
    }
    LinkStack stack;
    LinkStackInit(&stack);
    int64_t beg = 0;
    int64_t end = size;
    LinkStackPush(&stack, beg);
    LinkStackPush(&stack, end);
    while(1){
        int ret = LinkStackTop(&stack, &end);
        if(ret == 0){
            //栈为空,说明排序结束
            break;
        }
        LinkStackPop(&stack);
        LinkStackTop(&stack, &beg);
        if(end - beg <= 1){
            continue;
        }
        int64_t mid = Partion(array,beg, end);
        LinkStackPush(&stack, beg);
        LinkStackPush(&stack, mid);
        LinkStackPush(&stack, mid + 1);
        LinkStackPush(&stack, end);
    }
}

/////////////////////////////////////////////////////////////
//计数排序
/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
//奇数排序
/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
//睡眠排序:创建线程,根据退出时间
/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
//猴子排序:无线猴子定理
/////////////////////////////////////////////////////////////

“`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值