前面我们用递归的方法实现了归并排序,递归比较占用内存空间,能不能用非递归的方法来实现归并排序呢。答案当然是可以的。
使用非递归排序的思路如下(以序列{0,4,8,9,7,1,3,9,2}为例):
1.首先s=1,把数组中数两两归并,并放入一个新数组中(一般就拿它本身的那个数组来放),如果最后多一个数(例如最后一个数字2单独为一组),那么直接把这个数加入到新数组中去。这步完成后,每相邻的两个数内部是排好了序的,在这一步里面,会对9个序列(每个数是一个序列)进行归并,最终得到5个序列。
2.第二步s=2,把第1到第4个数,第5到第8个数进行归并,最后一个数字2又是单独的一个序列,不参与归并。第二步完成后,从第一个数开始,每相邻的4个数是排好序了的,在这一步里面会对5个序列(每2个数一个序列,最后一个数单独一个序列)进行归并,最终得到3个序列。
3.第三步s=4,把第1到8个数进行归并,最后一个数字2又是单独的一个序列,归并完成后,前面8个数内部是有序的,这一步里面会对3个序列(每4个数一个序列,最后一个数单独一个序列)进行归并,最终得到2个序列。
4第四步s=8,把第1到16个数进行归并,这时候最后一个数字2就参与到归并中去了,归并完成后,整个序列就都是有序的了,这一步里面会对两个序列(每8个数一个序列,最后一个数单独一个序列)进行归并,最终得到一个序列。
下面看具体的代码实现:
首先是通用的合并两个有序list的方法:
/// <summary>
/// 把两个有序的序列A和B合并到一个有序列temp里面
/// </summary>
/// <param name="sortListA">有序序列A</param>
/// <param name="sortListB">有序序列B</param>
/// <param name="tempList">有序序列Temp</param>
public void Merge(List<int> sortListA, List<int> sortListB, List<int> tempList)
{
int countB = 0;
int countA = 0;
//1.以某个序列为原始序列,把它的每一个数,与另外的一个序列做比较
for (int i = 0; i < sortListA.Count; i++)
{
//1.1循环遍历序列B的每一个序列(因为B序列是有序列的,所以第一个元素是最小的)
for (int j = countB; j < sortListB.Count; j++)
{
//1.2如果A序列中的某个元素比B中的小,就把A中的这个元素加到temp中去
if (sortListA[i] < sortListB[j])
{
tempList.Add(sortListA[i]);
countA++;//记录加到temp中去的A序列中元素的数量
break;
}
//1.2否则把B中的元素加到temp中去
else
{
tempList.Add(sortListB[j]);
countB++;//记录加到temp中去的B序列中元素的数量
}
}
}//注意,此for循环结束后,一定有一个序列中的元素全部加到了temp中去了。
//如果此处不相等,代表B中的元素还没有加完,那么把B中剩下的元素加入到Temp中去
if (countB != sortListB.Count)
{
for (int k = countB; k < sortListB.Count; k++)
{
tempList.Add(sortListB[k]);
}
}
//否则的话,代表A中的元素还没有加完,那么把A中剩下的元素加入到Temp中去
else
{
for (int k = countA; k < sortListA.Count; k++)
{
tempList.Add(sortListA[k]);
}
}
}