7-18 排序(25 分)
给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:
数据1:只有1个元素;
数据2:11个不相同的整数,测试基本正确性;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
数据6:105个顺序整数;
数据7:105个逆序整数;
数据8:105个基本有序的整数;
数据9:105个随机正整数,每个数字不超过1000。
输入格式:
输入第一行给出正整数N(≤105),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。
输出格式:
在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。
输入样例:
11
4 981 10 -17 0 -20 29 50 8 43 -5
输出样例:
-20 -17 -5 0 4 8 10 29 43 50 981
非递归进行实现 思路很类似链表吧。方法也是俩个俩个的合并。
代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 1000000
/** merge 排序 非递归实现**/
void swap(int x,int y) /**交换函数**/
{
int z;
z=y;
y=x;
x=z;
}
long long compare(long long x,long long y) /**比较函数**/
{
if(x>=y)return 1;
else return 0;
}
void conbine(long long *arr,int* idex,int x,int y) /**两个数组的合并(归并排序内用来合并的函数)**/
{
int p1=x,p2=y,head,next; /** x,y 分别是数组的第一个下标 实现 类似于链表 , head 是 头 next 是 正在插入时指针
idex 是 记录 每个数的 指向下一个比他大的数的下标 **/
if(compare(arr[x],arr[y])) /**先找到 俩数组合并后的 第一个下标**/
{
head=next=y;
p2=idex[p2];
}
else
{
head=next=x;
p1=idex[p1];
}
while(p1>=0&&p2>=0) /** 俩数组比较 小的出去**/
{
if(compare(arr[p1],arr[p2]))
{
idex[next]=p2;
p2=idex[p2];
}
else
{
idex[next] =p1;
p1=idex[p1];
}
next=idex[next];
}
while(p1>=0) /**再把剩的全踢出去**/
{
idex[next]=p1;
p1=idex[p1];
next=idex[next];
}
while(p2>=0)
{
idex[next]=p2;
p2=idex[p2];
next=idex[next];
}
idex[next]=-head; /**合并后数组最后一个等于头下标的负值**/
}
void merge(long long *arr,int *idex,int n) /**归并排序**/
{
int i=1,j,x,y,f;
f=1;
while(1)
{
while(i<=n&&idex[i]>0) i++; /**循环 每次找俩个 数组来合并**/
if(i<=n) x=i++;
else x=0;
while(i<=n&&idex[i]>0) i++;
if(i<=n) y=i++;
else y=0;
//printf("%d %d\n",x,y);
if(x&&y) /**找到俩个 合并**/
{
conbine(arr,idex,-idex[x],-idex[y]);
f=0;
}
/*for(j=1;j<=n;j++)
printf("%d ",idex[j]);
printf("\n");*/
if(f) break; /**f 意义是如果 最后 只找到一个 负数(头下标的负值) 就排好序了**/
if(i>n) /** 小排序 一次后 进行第二次小排序**/
{
i=1;
f=1;
}
}
}
void display(long long *arr,int *idex,int x) /**用来输出 不多说了**/
{
//printf("->");
int f=1;
while(x>=0)
{
if(f) f=0;
else printf(" ");
printf("%lld",arr[x]);
x=idex[x];
}
}
int main(){
int n,i,j;
scanf("%d",&n);
long long *arr;
arr = (long long *)malloc((n+2)*sizeof(long long)); /** 数组最好从 下标 1 开始 ,为了最后解决头下标负数 0 = -0的矛盾**/
for(i=1;i<=n;i++)
{
scanf("%lld",&arr[i]);
}
int *idex;
idex=(int*)malloc((n+2)*sizeof(int));
for(i=1;i<=n;i++)
idex[i]=-i;
merge(arr,idex,n);
//conbine(arr,idex,1,2);
for(i=1;i<=n;i++)
{
if(idex[i]<0)
{
display(arr,idex,-idex[i]);
break;
}
}
return 0;
}