算法导论笔记——归并排序C语言实现

第二章

算法基础

2.3.1 分治法
许多有用的算法在结构上是递归的,为了解决某个问题,算法依次或多次递归的
调用其自身已解决其紧密相关的若干子问题。这些算法典型遵循分治法的思想。

分治模式每层递归都有三个步骤:
分解 将原问题分解为若干子问题,这些子问题都是原问题较小的 实例实例:对
于给定输入序列成为问题的实例。
解决 递归的求解各子问题,如果子问题够小则可以直接求解。
合并 将子问题的解合并成原文题的解。

归并排序完全遵循分治模式。
分解 待排序的n个元素的序列成各具n/2个元素的两个子序列。
解决 递归的求解各个子问题,若子问题足够小,则直接求解
合并 合并两个已排序的子序列产生答案

原书伪代码(含哨兵 用于判断子序列元素是否用完)
排序部分
MERGE(A,p,q,r) //A待排数组,p起始项,q中间项,r末尾项
n1 = q - p + 1
n2 = r - q
//创建两个子序列L[1..n1+1],M[1..n2+1]
for i = 1 to n1
 L[i] = A[q+j]
for j = 1 to n2
 R[j] = A[q + j]
L[n1 + 1] = ∞      //哨兵
R[n2 + 1] = ∞
i = 1
j = 1
for k = p to r     //两个已排列好子序列逐个个比较
 if L[i] <= R[j]
    A[k] = L[i]
    i = i + 1
 else A[k] = R[j]
    j = j + 1

递归部分
MERGE-SORT(A,p,r)
 if p < r
    q = (p + r)/2
    MERGE-SORT(A,p,q)//向下递推
    MERGE-SORT(A,q+1,r)
    MERGE(A,p,q,r)    //调用排序 

C语言实现(含哨兵)
#include<stdio.h> 
void paixu(int a[],int p,int q,int r) //排序部分 
{
int l[q-p+1+1],m[r-q+1]; //创建两个已排好的子序列
int k,i,j;
for(i = 0,k = p;i < q-p+1;i++,k++) //为子序列赋值
{
 l[i]=a[k];
}
for(i = 0,k = q+1;i<r-q;i++,k++)
{
 m[i]=a[k];
}
l[q-p+1]=999;   //为哨兵赋值 
m[r-q]=999;
k = 0;
i = 0;
j = 0;
for(k = p;k<r+1;k++)   //子序列依次比较进行排序
{ 
 if(l[i]<m[j])
{
  a[k] = l[i];
  i++;
}
 else
{
  a[k] = m[j];
  j++;
}
}
}
void merge(int a[],int p,int r) //递归部分
{
int q;
q = (p+r)/2;  //确定中间项
if(r>p)
{
 merge(a,p,q);    //分别递推
 merge(a,q+1,r);
 paixu(a,p,q,r);  //排序当前两个经历过递推已排好序的子序列
}
} 
int main()
{
int a[8], i = 0;
for(;i<8;i++) 
 scanf("%d",&a[i]);
merge(a,0,7);  //调用递归进行排序
for(i = 0;i<8;i++) 
 printf("%d ",a[i]);
return 0;
}

C语言实现(不含哨兵)
#include<stdio.h> 
void paixu(int a[],int p,int q,int r) 
{
int l[q-p+1],m[r-q]; 
int k,i,j;
for(i = 0,k = p;i < q-p+1;i++,k++)
 l[i]=a[k];
for(i = 0,k = q+1;i<r-q;i++,k++)
 m[i]=a[k];
k = 0;
i = 0;
j = 0;
for(k = p;k<r+1;k++)
{ 
 if(i != q-p+1&&j !=r-q)
{ 
 if(l[i]<m[j])
{
  a[k] = l[i];
  i++;
}
 else
{
  a[k] = m[j];
  j++;
}
}
 else if(j == r-q)
{
  a[k] = l[i];
  i++;
}
 else if(i == q-p+1)
{
  a[k] = m[j];
  j++;
}
}
}
void merge(int a[],int p,int r) 
{
int q;
q = (p+r)/2;
if(r>p)
{
 merge(a,p,q);
 merge(a,q+1,r);
 paixu(a,p,q,r);
}
} 
int main()
{
int a[8],i = 0;
for(;i<8;i++) //read
 scanf("%d",&a[i]);
merge(a,0,7);
for(i = 0;i<8;i++) //write
 printf("%d ",a[i]);
return 0;
}

猜你喜欢

转载自blog.csdn.net/jazrynwong/article/details/79635535