https://blog.csdn.net/neverwa/article/details/79629314
https://blog.csdn.net/weiwenhp/article/details/8621049
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);