MergingSort
- 递归排序的两种实现
<script type="text/javascript">
//归并排序(递归实现)
//思想:堆排序利用了完全二叉树的性质,但是比较麻烦
//而归并排序则是直接利用构造一颗完全二叉树
//实现策略:先对数据分组,分到只有一个元素是:拷贝数组的元素到本次函数的
//SR数组中,归并SR到arr2中,arr2指向上层函数的SR数组
//时间复杂度:归并的次数是完全二叉树的高度,同时每次都需要对两个序列
//进行排序O(n),所以总的时间复杂度为O(nlogn)
//空间复杂度O(n+logn) n是数组 logn是递归需要的空间
//稳定性:稳定
function MergingSort(obj)
{
MSort(obj.data,obj.data,1,obj.length);
}
//拆分序列
//下层的数据SR归并到arr2中,arr2中本层函数的SR
function MSort(arr1,arr2,s,t)
{
var m;
var SR=[];
//SR用来存放下层函数归并的数据
if(s==t)
arr2[s]=arr1[s];
else
{
m=Math.floor((s+t)/2);
MSort(arr1,SR,s,m);
MSort(arr1,SR,m+1,t);
//console.log(SR);
//打印归并的过程
Merge(arr2,SR,s,m,t);
//console.log(arr2);
//打印归并的过程
}
}
//归并排序的非递归实现
//时间复杂度:O(nlogn)
//空间复杂度:O(n)
//稳定性:稳定
function MergingSort1(obj)
{
var k=1;
//k代表每次归并的序列长度
var arr1=[];
while(k<obj.length)
{
//执行两次是为了把数据放放到元素中
//归并arr中的数据到arr1
MergePass(obj.data,arr1,k,obj.length);
k=2*k;
//归并arr1到arr
MergePass(arr1,obj.data,k,obj.length);
k=2*k;
}
}
//如何进行分组
//k代表归并的序列长度 n代表的是总序列的长度
function MergePass(arr,arr1,s,n)
{
var i=1;
//最少还有两个可以归并
while(i<=n-2*s+1)
{
Merge(arr1,arr,i,i+s-1,i+2*s-1);
i+=(2*s);
}
//当还有两个分组时
if(i<n-s+1)
Merge(arr1,arr,i,i+s-1,n);
else
{//最多只有一个分组时
for(i;i<=n;i++)
{
arr1[i]=arr[i];
}
}
}
function Merge(arr1,arr2,s,m,t)
{
var i,j;
//把s到t的元素按从小的到大的顺序存放到数组中
for(i=s,j=m+1;s<=m && j<=t;i++)
{
if(arr2[s]<arr2[j])
arr1[i]=arr2[s++];
else
arr1[i]=arr2[j++];
}
if(s<=m)
{
for(;s<=m;s++)
{
arr1[i++]=arr2[s];
}
}
if(j<=t)
{
for(;j<=t;j++)
{
arr1[i++]=arr2[j];
}
}
}
var obj={
data:[0,3,11,5,2,4,3,11,5],
length:8
}
MergingSort(obj);
console.log(obj.data);
MergingSort1(obj)
console.log(obj.data);
</script>