排序算法的判别: 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,编译器进行预处理的时候就不会编译下面的这句语句了。
所以条件编译有时候是很有用的。
相关文章推荐
- 1098. Insertion or Heap Sort (25)
- 排序算法(insert ,shell ,quick ,select , merge ,heap)
- 【PAT】【Advanced Level】1098. Insertion or Heap Sort (25)
- PAT 甲级 1098. Insertion or Heap Sort (25)
- 1098. Insertion or Heap Sort (25) 21'
- 1098. Insertion or Heap Sort (25)
- PAT - 甲级 - 1098. Insertion or Heap Sort (25)(排序)
- Insertion or Heap Sort PAT甲级真题(堆排序)
- 1098. Insertion or Heap Sort (25)
- 1098. Insertion or Heap Sort 解析
- PAT 1098. Insertion or Heap Sort (25)
- PAT (Advanced Level) 1098. Insertion or Heap Sort (25)
- 中国大学MOOC-陈越、何钦铭-数据结构 Insertion or Heap Sort
- 1098. Insertion or Heap Sort (25)-PAT甲级真题(堆排序)
- 1098. Insertion or Heap Sort
- PAT甲级 1098. Insertion or Heap Sort (25)
- 1098. Insertion or Heap Sort (25)
- 1098.Insertion or Heap Sort
- 1098. Insertion or Heap Sort (25)
- 1098. Insertion or Heap Sort (25)C语言