您的位置:首页 > 其它

排序算法的判别: Insert or Merge,Insertion or Heap Sort

2017-05-15 21:16 363 查看

1. 09-排序2 Insert or Merge

题目

09-排序2 Insert or Merge (25分)

分析

题目输入原始数组和经过若干步插入排序或者归并排序的结果,要我们判断用的是哪个排序,并输出下一步排序的结果。

插入排序比较简单,这儿需要注意的是归并排序最好用非递归的归并排序。

并且在每一步排序之后都要检查是否和给出的数组相同,如果相同下一次排序之后要输出。

具体插入排序和归并排序可以参考我前面的两篇博客。

http://blog.csdn.net/bobo1356/article/details/71749720

http://blog.csdn.net/bobo1356/article/details/71909977

代码

#include<stdio.h>
#define ElementType int
#define MAXN 101

int arrayEqual(int A[], int B[], int N)
{
int i,ans = 1;
for(i=0; i<N; i++)
{
if(A[i] != B[i])
{
ans = 0;
break;
}
}
return ans;
}
void printArray(int A[], int N)
{
int i;
printf("%d",A[0]);
for(i=1; i<N; i++)
{
printf(" %d",A[i]);
}
printf("\n");
}
void Insert_sort(ElementType A[], ElementType B[], int N){
int i,j;
int equ = 0;
ElementType tmp;
for(i=1; i<N; i++){
tmp = A[i];         //摸下一张牌
for(j=i-1; j>=0 && tmp<A[j]; j--){
A[j+1] = A[j];      //移出空位
}
A[j+1] = tmp;           //新牌落位

if(equ == 1)
{
printf("Insertion Sort\n");
printArray(A,N);
break;

}
if(arrayEqual(A,B,N))
{
equ = 1;
}
}
}

void Merge(ElementType A[],ElementType tmpA[], int L, int R, int rightEnd)
{
int tmp = L,leftEnd = R-1,size = rightEnd-L+1;
while(L<=leftEnd && R<=rightEnd)
{
if(A[L] <= A[R])    tmpA[tmp++] = A[L++];
else                tmpA[tmp++] = A[R++];
}
while(L<=leftEnd)       tmpA[tmp++] = A[L++];
while(R<=rightEnd)      tmpA[tmp++] = A[R++];

int i;
for(i=0; i<size; i++)   A[rightEnd-i] = tmpA[rightEnd-i];

}
//将A[]中的N个元素归并到tmpA[]中,其中length表示当前有序子列的长度
void Merge_pass(ElementType A[], ElementType tmpA[], int N, int length)
{
int i;
for(i=0; i<=N-2*length; i+=2*length)
{
Merge(A, tmpA, i, i+length, i+2*length-1);
}
//归并最后两个列
if(i+length < N)    Merge(A, tmpA, i, i+length, N-1);
else{//如果最后只剩一个子列
for(; i<N; i++) tmpA[i] = A[i];
}
}

void Merge_sort(ElementType A[],ElementType B[], int N)
{
int length = 1, equ = 0;
ElementType *tmpA;
tmpA = malloc(sizeof(ElementType) * N);
if(tmpA != NULL)
{
while(length < N)
{
//将A归并到tmpA
Merge_pass(A, tmpA, N, length);
length *= 2;
if(equ == 1)
{
printf("Merge Sort\n");
printArray(tmpA, N);
break;
}
if(arrayEqual(tmpA, B, N))  equ = 1;

//将tmpA归并到A中
Merge_pass(tmpA, A, N,length);
length *= 2;
if(equ == 1)
{
printf("Merge Sort\n");
printArray(A, N);
break;
}
if(arrayEqual(A, B, N)) equ = 1;
}
free(tmpA);
}else
{
printf("空间不足\n");
}

}

int main()
{
int ini[MAXN],res[MAXN];
int tmp[MAXN];
int N,i;
//freopen("insertOrMerge.txt","r",stdin);

scanf("%d",&N);
for(i=0; i<N; i++)  scanf("%d",&ini[i]);
for(i=0; i<N; i++)  scanf("%d",&res[i]);

for(i=0; i<N; i++)  tmp[i] = ini[i];
Insert_sort(tmp,res,N);

for(i=0; i<N; i++)  tmp[i] = ini[i];
Merge_sort(tmp,res,N);

return 0;
}


小结

这儿有一个优化,可以让插入排序有一个返回值,如果确实是插入排序,就不再执行归并排序了。

但我这儿看到N比较小,也就没有这样做了。

2. Insertion or Heap Sort

题目

09-排序3 Insertion or Heap Sort (25分)

分析

这道题和上面那一道是同种类型的题目。不过是把判断归并排序改成了判断堆排序。

堆排序要注意的是数组从0还是1的位置开始放入有效元素。如果是从0开始,那么 leftChild = parent*2;从1开始,那么 leftChild = parent*2+1。我就是这儿没注意导致结果一直有问题。

同时我上面说的那个小优化在这次代码中实现了。

我的代码

#include<stdio.h>
#define ElementType int
#define MAXN 101

int arrayEqual(int A[], int B[], int N)
{
int i,ans = 1;
for(i=0; i<N; i++)
{
if(A[i] != B[i])
{
ans = 0;
break;
}
}
return ans;
}

void printArray(int A[], int N)
{
int i;
printf("%d",A[0]);
for(i=1; i<N; i++)
{
printf(" %d",A[i]);
}
printf("\n");
}

int Insert_sort(ElementType A[], ElementType B[], int N){
int i,j;
int equ = 0, right = 0;
ElementType tmp;
for(i=1; i<N; i++){
tmp = A[i];         //摸下一张牌
for(j=i-1; j>=0 && tmp<A[j]; j--){
A[j+1] = A[j];      //移出空位
}
A[j+1] = tmp;           //新牌落位

if(equ == 1)
{
right = 1;
printf("Insertion Sort\n");
printArray(A,N);
break;

}
if(arrayEqual(A,B,N))
{
equ = 1;
}
}

return right;
}

void Filter(ElementType A[], int pos, int N)
{
int child,parent;
ElementType tmp = A[pos];
for(parent=pos; parent*2+1<N; parent=child)
{
child = parent*2+1;
if(child+1<N && A[child]<A[child+1])    child++;

if(A[child] > tmp){
A[parent] = A[child];
}else{
break;
}
}
A[parent] = tmp;
}
void BuildMaxHeap(ElementType A[], int N)
{
int i;
for(i=N/2-1; i>=0; i--) Filter(A, i, N);
}

Swap(ElementType A[], int i, int j)
{
ElementType tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}

int Heap_sort(ElementType A[], ElementType B[], int N)
{
int i;
int equ = 0, right = 0;
BuildMaxHeap(A, N);

//printArray(A,N);
for(i=N-1; i>=0; i--)
{
Swap(A, 0, i);
Filter(A, 0, i);

//  printArray(A,N);

if(equ == 1)
{
right = 1;
printf("Heap Sort\n");
printArray(A,N);
break;

}
if(arrayEqual(A,B,N))
{
equ = 1;
}
}
return right;
}

int main()
{
int ini[MAXN],res[MAXN];
int tmp[MAXN];
int N,i;

#ifndef ONLINE_JUDGE
freopen("insertOrMerge.txt","r",stdin);
#endif

scanf("%d",&N);
for(i=0; i<N; i++)  scanf("%d",&ini[i]);
for(i=0; i<N; i++)  scanf("%d",&res[i]);

for(i=0; i<N; i++)  tmp[i] = ini[i];
int right = Insert_sort(tmp,res,N);

if(right == 0)
{
for(i=0; i<N; i++)  tmp[i] = ini[i];
Heap_sort(tmp,res,N);
}

return 0;
}


小结

在这次我学到了一个小技巧:

如果经常在本地代码进行重定向,从文件输入,然后提交到OJ上经常忘记注释的话,可以这样:

#ifndef ONLINE_JUDGE
freopen("insertOrMerge.txt","r",stdin);
#endif


因为一般的OJ都会给我们提交的程序加上
#define ONLINE_JUDGE


这是一种条件编译

上述代码意思就是如果没有 define ONLINE_JUDGE的话,就会编译下面的语句;如果已经定义了的话,比如在程序前面加上
#define ONLINE_JUDGE
,那么就不会编译下面的语句,标准输入设备还是键盘。

还有一种比较常用的条件编译如下:

#define DEBUG 1
#if DEBUG
printf("%d %d\n",x,y);
#endif


在我们调试程序的时候使 DEBUG 值为1,就可以输出一些中间结果,方便程序的调试;当我们调试结束,要提交代码的时候,可是又不想删除掉这些输出语句时(为了方便以后程序的修改调试),那么我们只需要修改 DEBUG 的值为0,编译器进行预处理的时候就不会编译下面的这句语句了。

所以条件编译有时候是很有用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息