力求在正确的前提下尽量短小。
首先是atoi,设置一个全局变量valid,输入无效置为false,有效置为true,这个代码要注意6点
1,输入指针为nullptr
2,去除首部空格
3,判断正负号
4,判断没有digit的情况
5,过滤非法字符
6,判断溢出
bool valid;
#define MAX 0x7fffffff
int atoi2(const char* in){
valid=true;
if(in==nullptr)return valid=false;
while(*in==' ')in++;
bool minus=false;
if(*in=='-'){
minus=true;
in++;
}else if(*in=='+')
in++;
long long result=0;
if(*in>'9'||*in<'0')return valid=false;
while(*in<='9'&&*in>='0'){
result=result*10+*in++-'0';
if(result-minus>MAX)
return valid=false;
}
if(minus)
result=-result;
return result;
}
快排,函数体只有8行,非常简单:
void qsort(int*left,int*right){
if(right-left<2)return;
int*p1=left,*p2=left;
for(;p2<right;++p2)
if(*p2<=*(right-1))swap(*p1++,*p2);
qsort(left,p1-1);
qsort(p1,right);
}
归并排序,因为需要额外申请空间,有额外赋值操作,所以看上去有些不和谐:
void msort(int*left,int*right){
if(right-left<2)return;
int*mid=left+(right-left)/2;
msort(left,mid);
msort(mid,right);
vector<int>tmp;
int*p1=left,*p2=mid;
while(p1!=mid||p2!=right)
if(p1==mid)tmp.push_back(*p2++);
else if(p2==right)tmp.push_back(*p1++);
else if(*p1<*p2)tmp.push_back(*p1++);
else tmp.push_back(*p2++);
for(int t:tmp)
*left++=t;
}
堆排,a--是为了让下标从1开始,个人习惯:
void sink(int*a,int n,int i){
if((2*i==n&&a[2*i]>a[i])||(2*i+1<=n&&a[2*i]>a[i]&&a[2*i]>=a[2*i+1])){
swap(a[i],a[2*i]);
sink(a,n,2*i);
}
else if(2*i+1<=n&&a[2*i+1]>a[i]&&a[2*i+1]>=a[2*i]){
swap(a[i],a[2*i+1]);
sink(a,n,2*i+1);
}
}
void hsort(int*a,int n){
if(a==NULL||n<2)return;
a--;
for(int i=n/2;i>0;--i)sink(a,n,i);
while(n>1){
swap(a[1],a[n--]);
sink(a,n,1);
}
}
下面3个排序,其实都差不多。
选择排序:
void select(int * a, int n){
while(n--){
int m=0;
for(int i=1;i<=n;++i)
if(a[i]>a[m])m=i;
swap(a[m],a[n]);
}
}
冒泡排序:
void bubble(int*a,int n){
while(n--)
for(int i=0;i<n;++i)
if(a[i]>a[i+1])swap(a[i],a[i+1]);
}
插入排序:
void insert(int*a,int n){
for(int i=0;i<n;++i)
for(int j=i-1;j>=0&&a[j]>a[j+1];--j)
swap(a[j],a[j+1]);
}
寻找第k小的元素,其实就是快排的划分,平均时间复杂度是o(n),有空再写个五分中位法:
int getK(int*left,int*right,int k){
if(right-left==1)return*left;
int*p1=left,*p2=left;
for(;p2<right;++p2)
if(*p2<=*(right-1))swap(*p1++,*p2);
int*mid=p1-1;
int n=mid-left+1;
if(n==k)return *mid;
else if(k<n)return getK(left,mid,k);
else return getK(p1,right,k-n);
}