排序&&圖 學習筆記(數據結構)

直接插入排序

# 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, -(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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章