zzulioj1174长整数排序(指针专题)
题目描述
长整数排序。输入n 然后输入n个位数不超过100位的大整数,输入的整数可能含有前导0。将这n个长整数排序后输出,输出不含前导0。
int greater(char *s1, char *s2)
{
若s1指向的整数大于s2指向的整数,返回一个正整数;
若s1指向的整数小于s2指向的整数,返回负整数;
若s1指向的整数等于s2指向的整数,返回0;
}
输入
输入第一行是一个正整数n(n<=10),接下来n行是n个大整数,均非负。
输出
输出n行,为n个升序排序后的大整数。
样例输入
3
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
54213456565
113456789456231545674632132156465132123156456423132156465461321654878976464654132132156455
样例输出
54213456565
12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
113456789456231545674632132156465132123156456423132156465461321654878976464654132132156455
代码展示一
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int greater(char *s1,char *s2);
int main()
{
int i,j,n;
scanf("%d",&n);
char *s[n],temp[100];
//输入n个大整数
for(i=0;i<n;i++)
{
s[i]=(char *)malloc(100*sizeof(char));
scanf("%s",s[i]);
}
//利用定义的函数进行冒泡排序 ,使之从小到大排序
for(i=0;i<n;i++)
for(j=i;j<n;j++)
{
if(greater(s[i],s[j])>0)
{
strcpy(temp,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],temp);
}
}
//输出排好序的大整数
for(i=0;i<n;i++)
printf("%s\n",s[i]);
return 0;
}
int greater(char *s1,char *s2)
{
int len1,len2,i,t1=0,t2=0;
//计算两个大整数长度
len1=strlen(s1);
len2=strlen(s2);
//判断字符串是否有前导零并将前导0去掉
for(i=0;s1[i]!='\0';i++)
{
if(s1[i]=='0')
t1++;
else
break;
}
if(t1==len1)
{
s1[0]='0';
s1[1]='\0';
t1=0;
len1=1;
}
if(t1>0)
{
for(i=0;i<len1-t1;i++)
{
s1[i]=s1[i+t1];
}
s1[i]='\0';
}
for(i=0;s2[i]!='\0';i++)
{
if(s2[i]=='0')
t2++;
else
break;
}
if(t2==len2)
{
s2[0]='0';
s2[1]='\0';
t2=0;
len2=1;
}
if(t2>0)
{
for(i=0;i<len2-t2;i++)
{
s2[i]=s2[i+t2];
}
s2[i]='\0';
}
//比较大小操作
len1=len1-t1;
len2=len2-t2;
if(len1>len2) return 1;
else if(len1<len2) return -1;
else
{
for(i=0;i<len1;i++)
{
if(s1[i]>s2[i]) return 1;
else if(s1[i]<s2[i]) return -1;
}
return 0;
}
}
说明
这个代码最开始写的时候大部分输入时结果是正确的,但不太完善,因为当输入有一个全为0的大整数时,输出时不会输出它,只是一个空白,按理说应该保留一个0才对,所以又加了一个if语句判断当输入大整数全为0的情况。
代码展示二
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
int greater(char *s1,char *s2); //排序函数
int InputRight(char *s);
int main()
{
int i,j,n,flag=0;
scanf("%d",&n);
char *s[n],temp[100];
//输入n个大整数
for(i=0;i<n;i++)
{
s[i]=(char *)malloc(100*sizeof(char));
scanf("%s",s[i]);
flag=InputRight(s[i]);
if(flag==1)
break;
}
if(flag==1)
{
printf("输入不合法!\n");
}
else
{
//利用定义的函数进行冒泡排序 ,使之从小到大排序
for(i=0;i<n;i++)
for(j=i;j<n;j++)
{
if(greater(s[i],s[j])>0)
{
strcpy(temp,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],temp);
}
}
//输出排好序的大整数
for(i=0;i<n;i++)
printf("%s\n",s[i]);
}
return 0;
}
int InputRight(char *s)
{
int i,f=0;
for(i=0;s[i]!='\0';i++)
{
if(isdigit(s[i])==0) //如果有一个字符不是数字
{
f=1;
break;
}
}
return f;
}
int greater(char *s1,char *s2)
{
int len1,len2,i,t1=0,t2=0;
char ch[200];
len1=strlen(s1);
len2=strlen(s2);
//判断字符串是否有前导零并将前导0去掉
for(i=0;s1[i]!='\0';i++)
{
if(s1[i]=='0')
t1++;
else
break;
}
if(t1==len1)
{
s1[0]='0';
s1[1]='\0';
t1=0;
len1=1;
}
if(t1>0)
{
for(i=0;i<len1-t1;i++)
{
s1[i]=s1[i+t1];
}
s1[i]='\0';
}
for(i=0;s2[i]!='\0';i++)
{
if(s2[i]=='0')
t2++;
else
break;
}
if(t2==len2)
{
s2[0]='0';
s2[1]='\0';
t2=0;
len2=1;
}
if(t2>0)
{
for(i=0;i<len2-t2;i++)
{
s2[i]=s2[i+t2];
}
s2[i]='\0';
}
//比较大小操作
len1=len1-t1;
len2=len2-t2;
if(len1>len2) return 1;
else if(len1<len2) return -1;
else
{
for(i=0;i<len1;i++)
{
if(s1[i]>s2[i]) return 1;
else if(s1[i]<s2[i]) return -1;
}
return 0;
}
}
说明
这个代码加入了一个判断语句当输入不合法即输入的大整数中包含非数字的字符时结束输入,输出“输入不合法!”,然后结束此程序,不再进行其他的排序操作。
代码展示三
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int greater(char *s1,char *s2); //比较两个大整数的大小
char *def(char *a); //返回一个指向大整数中第一个不为0的位置
int main()
{
int i,j,n;
char *s[20],*sp=NULL,temp[101],str[101];
scanf("%d",&n);
//输入大整数
for(i=0;i<n;i++)
{
scanf("%s",temp); //先用temp暂存输入的大整数
sp=def(temp);
s[i]=(char *)malloc(100*sizeof(char));
strcpy(s[i],sp);
/* 也可以使用下列代码输入
s[i]=(char *)malloc(100*sizeof(char));
scanf("%s",s[i]); //输入大整数
s[i]=def(s[i]); //去除可能存在的前导0
*/
}
//进行升序排序
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
{
if(greater(s[i],s[j])==1) //如果s[i] 大于s[j],将二者互换
{
strcpy(str,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],str);
}
}
//输出
for(i=0;i<n;i++)
printf("%s\n",s[i]);
return 0;
}
char *def(char *a)
{
int i;
char *ch=a;
for(i=0;a[i]!='\0';i++)
{
if(a[i]!='0') break;
if(a[i+1]=='\0') break; //此为输入全为0的情况
}
ch=&a[i];
return ch;
}
int greater(char *s1,char *s2)
{
int i,len1,len2;
//计算两个大整数的长度
len1=strlen(s1);
len2=strlen(s2);
//进行比较大小操作
if(len1>len2) return 1;
else if(len1<len2) return -1;
else
{
for(i=0;i<len1;i++)
{
if(s1[i]>s2[i]) return 1;
if(s1[i]<s2[i]) return -1;
}
return 0;
}
}
代码展示四
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int greater(char *s1,char *s2); //比较两个大整数的大小
char *def(char *a); //返回一个指向大整数中第一个不为0的位置
int main()
{
int i,j,n;
char *s[20],*str1=NULL,str[101],*temp=NULL;
scanf("%d",&n);
//输入大整数
for(i=0;i<n;i++)
{
scanf("%s",str); //先用temp暂存输入的大整数
str1=def(str); // 指针sp接收函数返回值指向大整数第一个不为零的位置
s[i]=(char*)malloc(sizeof(char)*(strlen(str1)+1));
strcpy(s[i],str1);
}
//进行升序排序
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
{
if(greater(s[i],s[j])==1) //如果s[i] 大于s[j],将二者互换
{
temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}
//输出
for(i=0;i<n;i++)
printf("%s\n",s[i]);
return 0;
}
char *def(char *a)
{
char *sp=NULL;
int i;
for(i=0;a[i]!='\0';i++)
{
if(a[i]!='0'||(a[i]=='0'&&a[i+1]=='\0')) //当前位置不为 '0' ,指针指向当前位置并返回
//也可以写成: if(a[i]!='0'||a[i+1]=='\0')
{
sp=&a[i];
return sp;
}
}
}
int greater(char *s1,char *s2)
{
int i,len1,len2;
//计算两个大整数的长度
len1=strlen(s1);
len2=strlen(s2);
//进行比较大小操作
if(len1>len2) return 1;
else if(len1<len2) return -1;
else
{
for(i=0;i<len1;i++)
{
if(s1[i]>s2[i]) return 1;
if(s1[i]<s2[i]) return -1;
}
return 0;
}
}
这个代码与上一个很相似,主要的区别主要是下面几句,一个定义的是
char *s[20],*sp=NULL,temp[101],str[101];
scanf("%s",temp); //先用temp暂存输入的大整数
sp=def(temp);
s[i]=(char *)malloc(100 * sizeof(char));
strcpy(str,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],str);
另一个为
char *s[20],*str1=NULL,str[101],*temp=NULL;
scanf("%s",str); //先用temp暂存输入的大整数
str1=def(str); // 指针sp接收函数返回值指向大整数第一个不为零的位置
s[i]=(char*)malloc(sizeof(char)* (strlen(str1)+1));
temp=s[i];
s[i]=s[j];
s[j]=temp;
由上可知动态分配时若采用malloc(sizeof(char)* (strlen(str1)+1))这种形式,那么在进行排序的时候当s[i]大于s[j]需要进行交换的时候,那个交换的变量temp必须定义的也为指针类型,若交换的中间变量定义的时候为一字符串数组,那么动态分配的时候就不能采用这种形式,不然的话提交显示答案错误,但是在devc++上运行是对的,能够将测试用例顺利排序,而如果采用malloc(100 * sizeof(char))这种形式,进行交换时中间变量定义时是*temp还是temp[101],提交时结果都是对的,原因的话暂时还没想明白,等明白了再来补充一下
Tips:
输入时也可以不用scanf函数如下列所示:
int i,j,n;
char *s[20],*str1=NULL,str[101],*temp=NULL;
scanf("%d",&n);
getchar(); //吸收'\n'
//输入大整数
for(i=0;i<n;i++)
{
gets(str); //先用temp暂存输入的大整数
str1=def(str); // 指针sp接收函数返回值指向大整数第一个不为零的位置
s[i]=(char*)malloc(sizeof(char)*(strlen(str1)+1));
//s[i]=(char*)malloc(sizeof(char)*100);
strcpy(s[i],str1);
}