排序算法中的小技巧

https://blog.csdn.net/neverwa/article/details/79629314
https://blog.csdn.net/weiwenhp/article/details/8621049 
快速排序 非递归
https://blog.csdn.net/Arctton/article/details/4089393  使用堆栈和不使用堆栈

void MergeSortIteration(int A[], int len)    // 非递归(迭代)实现的归并排序(自底向上)
{
    int left, mid, right;// 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right]
    for (int i = 1; i < len; i *= 2)        // 子数组的大小i初始为1,每轮翻倍
    {
        left = 0;
        while (left + i < len)              // 后一个子数组存在(需要归并)
        {
            mid = left + i - 1;
            right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够
            Merge(A, left, mid, right);
            left = right + 1;               // 前一个子数组索引向后移动
        }
    }
}

当我们利用left  mid right 进行步长i递增的时候,如果设right=mid+i如果要保证left到mid   mid+1到right  两个队列数目相等。那么这个mid就必须为mid=left+i-1.。直观的来讲如果mid=left+i  。那么左队列就有1(left本身) 加i个,右队列只有i个,不对等。所以在约束定义为“:左队列为left到mid  右队列 mid+1到right 时,应该用mid=left+i-1,right=mid+i,来保证左右队列皆为i个元素。或者用mid=left+i   right=mid+i+1来保证左右队列各i+1各元素。很显然在归并排序中,应该使用最小粒度的分组,即为前者。


int Partition(int A[], int left, int right)  // 划分函数
{
    int pivot = A[right];               // 这里每次都选择最后一个元素作为基准
    int tail = left - 1;                // tail为小于基准的子数组最后一个元素的索引
    for (int i = left; i < right; i++)  // 遍历基准以外的其他元素
    {
        if (A[i] <= pivot)              // 把小于等于基准的元素放到前一个子数组末尾
        {
            Swap(A, ++tail, i);
        }
    }
    Swap(A, tail + 1, right);           // 最后把基准放到前一个子数组的后边,剩下的子数组即是大于基准的子数组
                                        // 该操作很有可能把后面元素的稳定性打乱,所以快速排序是不稳定的排序算法
    return tail + 1;                    // 返回基准的索引
}

在以上编码中

int tail = left - 1;  与  
 Swap(A, ++tail, i);

猜你喜欢

转载自blog.csdn.net/qq_41641296/article/details/81017818