直接插入排序
# include <stdio.h>
# include <string.h>
# define N 10000
int a[N];
void insertion_sort(int *a, int len)
{
int temp;
int i, j, k;
for(i=1; i<len; ++i)
{
temp = a[i];
for(j=i; j>=1 && a[j-1]>temp; j--)
{
a[j] = a[j-1];
}
a[j] = temp;
for(k=0; k<len; ++k)
{
printf("%d ", a[k]);
}
printf("\n");
}
}
int main(void)
{
memset(a, 0, sizeof(a));
int n, i;
int len = 0;
scanf("%d", &n);
for(i=0; i<n; ++i)
{
scanf("%d", &a[i]);
len++;
}
insertion_sort(a, len);
return 0;
}
折半插入排序
# include <stdio.h>
# include <string.h>
# define N 10000
int a[N];
void insertion_sort(int *a, int len)
{
int temp;
int i, j, k;
for(i=1; i<len; ++i)
{
temp = a[i];
for(j=i; j>=1 && a[j-1]>temp; j--)
{
a[j] = a[j-1];
}
a[j] = temp;
for(k=0; k<len; ++k)
{
printf("%d ", a[k]);
}
printf("\n");
}
}
int main(void)
{
memset(a, 0, sizeof(a));
int n, i;
int len = 0;
scanf("%d", &n);
for(i=0; i<n; ++i)
{
scanf("%d", &a[i]);
len++;
}
insertion_sort(a, len);
return 0;
}
希爾排序(shell)
# include <stdio.h>
typedef int ElemenType ;
void traverse(ElemenType A[], int N)
{
int i;
for(i=0; i<N; ++i)
{
printf("%d", A[i]);
if(i!=N-1)
printf(" ");
else
printf("\n");
}
}
void shell_sort(ElemenType A[], int N)
{
int D, P;
int i;
int Tmp;
for(D=N/2; D>0; D/=2)//incremental is d/2
{
for(P=D; P<N; ++P)
{
Tmp = A[P];
for(i=P; i>=D&&A[i-D]>Tmp; i-=D)
{
A[i]=A[i-D];
}
A[i]=Tmp;
}
traverse( A, N);
}
return ;
}
int main(void)
{
int n;
scanf("%d", &n);
int i;
int a[100000];
for(i=0; i<n; ++i)
{
scanf("%d", &a[i]);
}
shell_sort(a, n);
return 0;
}
冒泡排序
# include <stdio.h>
void traverse(int a[], int n)
{
int i;
for(i=0; i<n; ++i)
{
printf("%d", a[i]);
if(i!=n-1)
printf(" ");
else
printf("\n");
}
}
void bubble_sort(int a[], int n)
{
int t;
int i, j;
int flag = 0;
for(i=0; i<n-1; ++i)
{
flag=0;
for(j=0; j<n-1-i; ++j)
{
if(a[j]>a[j+1])
{
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
flag=1;
}
}
traverse(a, n);
if(flag==0)
break;
}
}
int main(void)
{
int i;
int n;
int a[10000];
scanf("%d", &n);
for(i=0; i<n; ++i)
{
scanf("%d", &a[i]);
}
bubble_sort(a, n);
return 0;
}
簡單選擇排序
#include <stdio.h>
void traverse(int a[], int n)
{
int i;
for(i=0; i<n; ++i)
{
printf("%d", a[i]);
if(i!=n-1)
printf(" ");
else
printf("\n");
}
}
int sort(int a[], int n)
{
int i,j,k,tmp;
for(i=0;i<n-1; i++)
{
k=i;
for(j=i+1; j<n; ++j)
if(a[k]>a[j]) k=j;
tmp=a[k];a[k]=a[i];a[i]=tmp;
traverse(a,n);
}
return 0;
}
int main()
{
int a[100000];
int i;
int n;
scanf("%d", &n);
for(i=0; i<n; i++) scanf("%d", &a[i]);
sort(a,n);
// for(i=0; i<10; i++) printf("%d\n", a[i]);
return 0;
}
歸併排序(求逆序數)
#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int a[maxn],cnt,b[maxn],n;
ll ans=0;
void merge(int l, int mid, int r)
{
int p1=l, p2=mid+1;
For(i,l,r)
{
if((p1<=mid)&&((p2>r)||(a[p1]<=a[p2])))
{
b[i]=a[p1];
p1++;
}
else
{
b[i]=a[p2];
ans+=mid-p1+1;
p2++;
}
}
// cout<<ans<<' '<<l<<' '<<r<<endl;
For(i,l,r)a[i]=b[i];
}
void divid(int l, int r)
{
int mid=(l+r)>>1;
if(l<r)
{
divid(l,mid);
divid(mid+1,r);
}
merge(l,mid,r);
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
For(i,1,n)cin>>a[i];
divid(1,n);
cout<<ans<<endl;
return 0;
}
歸併排序(非遞歸寫法,枚舉尺度)
#include <iostream>
#include <cstdio>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int a[100],n;
void merge(int x, int mid, int y)
{
int l=x;
int r=mid+1;
int b[y-x+1],j=0;
while(l<=mid&&r<=y)
{
if(a[l]<=a[r])b[j++]=a[l++];
else b[j++]=a[r++];
}
while(l<=mid)b[j++]=a[l++];//這裏和歸併排序一樣。
while(r<=mid)b[j++]=a[r++];
For(i,0,j-1)a[x++]=b[i];
}
void divide(int cnt)
{
int cur=1;
while(cur+2*cnt-1<=n)
{
merge(cur,cur+cnt-1,cur+2*cnt-1);
cur+=2*cnt;
}
if(cur+cnt-1<n)merge(cur,cur+cnt-1,n);//右邊不夠枚舉的尺度,要特殊合併。
}
void print()
{
For(i,1,n)cout<<a[i]<<' ';
cout<<endl;
}
void msort()
{
int cnt=1;
while(cnt<n)
{
divide(cnt);
print();
cnt*=2;
}
}
int main()
{
cin>>n;
For(i,1,n)cin>>a[i];
msort();
return 0
}
//smaple1:
/*
10
5 4 8 0 9 3 2 6 7 1
*/
//sample output
/*
4 5 0 8 3 9 2 6 1 7
0 4 5 8 2 3 6 9 1 7
0 2 3 4 5 6 8 9 1 7
0 1 2 3 4 5 6 7 8 9
*/
快速排序(求第k大數)
#include <iostream>
#include <cstdio>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=5e6+10;
int a[maxn],n,k,ans=0;
inline int read()
{
int ans=0;
char ch=getchar();bool neg=false;
while(ch<'0'||ch>'9')
{
if(ch=='-')neg=true;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans=ans*10+ch-'0';
ch=getchar();
}
return (neg)?-ans:ans;
}
void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(x>9)write(x/10);
putchar(x%10+'0');
}
void find(int l, int r)
{
//cout<<l<<' '<<r<<' '<<k<<endl;
int i=l, j=r;
int mid=(l+r)/2;
int x=a[mid];
while(i<=j)
{
while(a[i]<x)i++;
while(a[j]>x)j--;
if(i<=j)
{
swap(a[i],a[j]);
i++;j--;
}
}
// int ans=0;
if(i-1==k)ans=a[i-1];
else if(i-1<k&&i<=r)find(i,r);//板子是隻有一個元素就不看了,這裏要看,萬一是呢。
else if(i-1>k&&l<=j)find(l,j);//這裏還要限制是k在哪裏,k即是【l,r】上的一點,所以不用傳參數
return ;
}
int main()
{
int t;
t=read();
while(t--)
{
n=read();k=read();
For(i,1,n)a[i]=read();find(1,n);
write(ans);
putchar('\n');
}
return 0;
}
堆排序
#include <iostream>
#include <cstdio>
using namespace std;
int n,a[100];
void adjust(int cur, int l, int r)
{
int i,j,h;
j=cur;
while((2*j<=r&&a[j]<a[2*j])||(2*j+1<=r&&a[j]<a[2*j+1]))
{
if(2*j+1>r||a[2*j]>=a[2*j+1])h=2*j;//走兒子大
else h=2*j+1;//右兒子大
if(a[j]<a[h])swap(a[j],a[h]),j=h;//兒子大於爸爸
}
}
void print()
{
for(int i=1;i<=n; i++)cout<<a[i]<<' ';
cout<<endl;
}
void mheap()
{
int i,j,h;
for(i=n/2; i>=1; i--)adjust(i,1,n);//從底層開始,對每個樹根開始調整。
print();
for(i=n;i>1; i--)
{
swap(a[1],a[i]);adjust(1,1,i-1);//這裏調整範圍要注意,感覺l可以不要
//由於是每次把最後一個與祖先交換,所以每次調整都要在原先的堆裏的祖先開始調整。
print();
}
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++)cin>>a[i];
mheap();
return 0;
}
基數排序
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
vector<int>d[10];
int a[1000];int n,cnt=0;
void print()
{
For(i,1,n)printf("%03d ",a[i]);
cout<<endl;
}
int main()
{
cin>>n;
For(i,1,n)cin>>a[i];
For(k,1,3)
{
cnt=0;
For(i,1,n)d[a[i]/(int)pow(10,k-1)%10].push_back(a[i]);
For(i,0,9)
{
for(int j=0; j<d[i].size(); j++)a[++cnt]=d[i][j];
d[i].clear();
}
print();
}
return 0;
}
實現圖的存儲結構
#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int g[1500][1500];
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n,m,a,b;
cin>>n>>m;
For(i,1,m)
{
cin>>a>>b;
g[a][b]=1;
}
For(i,1,n)
{
For(j,1,n)
{
if(g[i][j])cout<<1;
else cout<<0;
cout<<' ';
}
cout<<endl;
}
return 0;
}
AC(vector)
#include <iostream>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
vector<int>v[1000];
int main()
{
int n,m,x,y;
cin>>n>>m;
For(i,1,n)
{
v[i].resize(n+1);
}
For(i,1,m)
{
cin>>x>>y;
v[x][y]=1;
}
For(i,1,n)
{
For(j,1,n)
{
if(v[i][j])cout<<1<<' ';
else cout<<0<<' ';
}
cout<<endl;
}
return 0;
}
圖的深度遍歷
這題輸入有點噁心(好在之前有看到過類似的)
這裏用到了鏈式前向星存圖(鄰接表的一種,不會的可以csdn裏搜,這裏不贅述),其實也可以vector去存圖。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define fzhead EDGE(int _to, int _val, int _next)
#define fzbody to(_to),val(_val),next(_next)
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxm=1e4+10;
const int maxn=1e4+10;
map<string,int>ma;//爲每一個字符串賦一個值
vector<string>v;//把映射前的字符串先保存起來
int n,m,cnt,tp,head[maxn],vis[maxn];
struct EDGE
{
int to,val,next;
EDGE(){}
fzhead:fzbody{}
}e[maxm];//鏈式前向星存圖,
void add(int bg, int to, int val)
{
e[++cnt]=EDGE(to,val,head[bg]);
head[bg]=cnt;
}
void dfs(int u)
{
vis[u]=1;
cout<<v[u]<<' ';
for(int i=head[u]; i!=-1; i=e[i].next)
{
int V=e[i].to;
if(!vis[V])dfs(V);
}
}
int main()
{
mst(head,-1);
cin>>tp>>n>>m;
string s,a,b;
int tot=0,w;
For(i,1,n)
{
cin>>s;
ma[s]=tot++;//
v.push_back(s);//
}
For(i,1,m)
{
if(tp==1||tp==3)cin>>w;
cin>>a>>b;
int x=ma[a],y=ma[b];
if(tp==0)add(x,y,0);
else if(tp==1)add(x,y,w);
else if(tp==2)add(x,y,0),add(y,x,0);
else add(x,y,w),add(y,x,w);
}
dfs(0);
return 0;
}
圖的廣度搜索
注意區別和優先隊列的bfs
#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mst(x,a) memset(x,a,sizeof(x))
#define fzhead EDGE(int _to, int _val, int _next)
#define fzbody to(_to), val(_val), next(_next)
using namespace std;
const int maxn=1e4+10;
vector<string>v;
map<string,int>ma;
int cnt,n,m,tp,vis[maxn],head[maxn];
struct EDGE
{
int to, val, next;
EDGE(){}
fzhead:fzbody{}
}e[maxn];
void add(int bg, int to, int val)
{
e[++cnt]=EDGE(to, val, head[bg]);
head[bg]=cnt;
}
void bfs()
{
queue<int>q;
q.push(0);
vis[0]=1;
while(!q.empty())
{
int u=q.front();q.pop();
cout<<v[u]<<' ';//dij的vis放在for外的
for(int i=head[u]; i!=-1; i=e[i].next)
{
int to=e[i].to;
if(!vis[to])//這裏表示已經入隊,就不要重複入隊了。
{
vis[to]=1;
q.push(to);
}
}
}
}
int main()
{
mst(head,-1);
int tot=0,w;
string s,a,b;
cin>>tp>>n>>m;
For(i,1,n)
{
cin>>s;
ma[s]=tot++;
v.push_back(s);
}
For(i,1,m)
{
if(tp==1||tp==3)cin>>w;
cin>>a>>b;
int x=ma[a],y=ma[b];
if(tp==0)add(x,y,0);
else if(tp==1)add(x,y,w);
else if(tp==2)add(x,y,0),add(y,x,0);
else add(x,y,0),add(y,x,0);
}
bfs();
return 0;
}
順序查找
#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int a[10000];
int main()
{
int n,key,ans=0;
cin>>n;
For(i,1,n)cin>>a[i];
cin>>key;
For(i,1,n)if(a[i]==key){ans=i;break;}
if(ans)cout<<"The element position is "<<ans<<"."<<endl;
else cout<<"The element is not exist."<<endl;
return 0;
}
二分查找
#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int a[10000];
int main()
{
int n,key;
cin>>n;
For(i,1,n)cin>>a[i];
cin>>key;
int l=1,r=n,mid,flag=0,ans=-1;
while(l<=r)
{
mid=l+(r-l)/2;
if(a[mid]<=key)
{
l=mid+1;
ans=mid;
}
else r=mid-1;
}
if(a[ans]==key)cout<<"The element position is "<<ans-1<<"."<<endl;
else cout<<"The element is not exist."<<endl;
return 0;
}
哈希查找(終於學會了,真就b站畢業哈哈。)
H(k)=3*k MOD length(構造hash函數)
常見的處理衝突的方法(開放定址法)
- 一般設置1爲增量
- 也可以1^2, -(1) ^ 2, 2 ^2,-2 ^2,…
#include <iostream>
#include <cstdio>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int hh[100000];
int n,x,cnt=0,temp,tot=0;
int gethash(int &cnt, int x)
{
int fou=x*3%n;
while(hh[fou]!=0)
{
fou=(fou+1)%n;
temp++;
}
hh[fou]=x;
}
int main()
{
cin>>n;
while((cin>>x)&&x!=-1)
{
tot++;
temp=1;
gethash(temp,x);
cnt+=temp;
}
For(i,0,n-1)
if(hh[i])cout<<hh[i]<<' ';
else cout<<"X ";
cout<<"\n";
printf("Average search length=%.6f\n",(double)cnt/(double)tot);
return 0;
}