數據結構課程設計【C++實現】

(一)線性結構(鏈表)題目

報數問題
問題描述:有n個小朋友圍成一圈玩遊戲,小朋友從1至n編號,2號小朋友坐在1號小朋友的順時針方向,3號小朋友坐在2號小朋友的順時針方向,……,1號小朋友坐在n號小朋友的順時針方向。
  遊戲開始,從1號小朋友開始順時針報數,接下來每個小朋友的報數是上一個小朋友報的數加1。若一個小朋友報的數爲k的倍數或其末位數(即數的個位)爲k,則該小朋友被淘汰出局,不再參加以後的報數。當遊戲中只剩下一個小朋友時,該小朋友獲勝。
  例如,當n=5, k=2時:
  1號小朋友報數1;
  2號小朋友報數2淘汰;
  3號小朋友報數3;
  4號小朋友報數4淘汰;
  5號小朋友報數5;
  1號小朋友報數6淘汰;
  3號小朋友報數7;
  5號小朋友報數8淘汰;
  3號小朋友獲勝。
  給定n和k,請問最後獲勝的小朋友編號爲多少?
輸入格式
  輸入一行,包括兩個整數n和k,意義如題目所述。
輸出格式
  輸出一行,包含一個整數,表示獲勝的小朋友編號。
樣例輸入
5 2
樣例輸出
3
樣例輸入
7 3
樣例輸出
4
數據規模和約定
對於所有評測用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 9。
要求:利用單向循環鏈表存儲結構模擬此過程。

代碼

#include <bits/stdc++.h>
using namespace std;
typedef struct node
{
    int data;
    struct node *next,*prior;
}node,*linklist;
int n,k;
linklist L;//頭指針
bool judge(int x)
{
    if(x%k==0||x%10==k)return 1;//被淘汰
    return 0;
}
void build(linklist &L)//建立雙向循環鏈表(無尾指針)
{
    L=new node;
    L->data=1;//頭指針儲存元素
    linklist r=L;
    linklist s;
    for(int i=2;i<=n;i++)
    {
        s=new node;
        s->data=i;
        s->prior=r;
        r->next=s;
        r=s;
    }
    r->next=L;
    L->prior=r;
}
void output()
{
    linklist p=L;
    for(int i=1;i<=n;i++)
    {
        printf("%d\n",p->data);
        p=p->next;
    }
}
int solve(linklist L)
{
    int cnt=0,num=0;
    linklist p=L;
    while(1)
    {
        if(cnt==n-1)//淘汰個數cnt
            return p->data;
        num++;//報數爲num
        if(judge(num))
        {
            p->prior->next=p->next;
            p->next->prior=p->prior;
            linklist tmp=p;
            p=p->next;
            cnt++;
            delete tmp;
        }
        else p=p->next;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>k;
    build(L);
    //output();
    int ans=solve(L);
    printf("%d\n",ans);
    return 0;
}

(二)棧和隊列題目

迷宮問題求解
任務:可以輸入一個任意大小的迷宮數據,用非遞歸的方法求出一條走出迷宮的路徑,並將路徑輸出;
要求:在上交資料中請寫明:存儲結構、基本算法(可以使用程序流程圖)、源程序、測試數據和結果、算法的時間複雜度、另外可以提出算法的改進方法;

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
char a[N][N];
bool vis[N][N];
int n,m,bx,by,ex,ey;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
    int x,y,cnt;
}pre[N][N],path[N*N];
queue<node>q;
int bfs()
{
    q.push({bx,by,0});
    while(!q.empty())
    {
        node tmp=q.front();q.pop();
        int x=tmp.x,y=tmp.y,cnt=tmp.cnt;
        if(x==ex&&y==ey)return cnt;
        vis[x][y]=1;
        for(int i=0;i<4;i++)
        {
            int nx=x+dir[i][0];
            int ny=y+dir[i][1];
            if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!vis[nx][ny]&&a[x][y]=='0')
            {
                q.push({nx,ny,cnt+1});
                pre[nx][ny].x=x;
                pre[nx][ny].y=y;
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;//輸入迷宮大小
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>a[i][j];//輸入迷宮
    cin>>bx>>by>>ex>>ey;//輸入起點和終點座標
    int ans=bfs();
    printf("%d\n",ans);//輸出最短步數
    int nx=ex,ny=ey;
    int cnt=0;
    while(1)
    {
        path[++cnt]={nx,ny};
        if(nx==bx&&ny==by)break;
        int t1=nx,t2=ny;
        nx=pre[t1][t2].x;
        ny=pre[t1][t2].y;

    }
    for(int i=cnt;i>=1;i--)//輸出最短路徑
        printf("(%d, %d)\n",path[i].x,path[i].y);
    return 0;
}

測試數據

輸入格式
  輸入兩個整數n和m,表示n*m大小的迷宮。
  輸入n行,表示迷宮,0表示可走的路,1表示牆。
  輸入起點座標bx、by。
  輸入終點座標ex、ey。
輸出格式
  輸出一行,包含一個整數cnt,表示最短步數。
  輸出cnt行,表示起點到終點的最短路徑,格式如樣例所示。

test_01
輸入:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
1 1
5 5
輸出:
8
(1, 1)
(2, 1)
(3, 1)
(3, 2)
(3, 3)
(3, 4)
(3, 5)
(4, 5)
(5, 5)

test_02
輸入:
17 54
011111111111111111111111111111111111111111111111111111
011111100000001111111111111111111111111111111101111111
011111101111011111111111111111111111111111110000000011
000000001111011111100000000001111111111111111101111111
111111101111011111101111111111111111111111111101111111
111111101111011111101111111111111111111111111101111111
111111101111011111101111111111111111111111111101111111
111111101111011111100000000000000000011111111101111111
111111101111011111101111111111111111011111111101111111
111111100000000000001111111111111111011111111101111111
111111111111111111111111111111111111011111111101111111
111111111111111111000000000000000000011000000001111111
111111111111111111011111111111111111111011111101111111
111111111111111111011111111111111111111011111101111111
111111111111111111011111111111111111111011111100000011
111111111111111111000000000000000000000011111111111001
111111111111111111111111111111111111111111111111111100
1 1
17 54
輸出:
117
(1, 1)
(2, 1)
(3, 1)
(4, 1)
(4, 2)
(4, 3)
(4, 4)
(4, 5)
(4, 6)
(4, 7)
(4, 8)
(5, 8)
(6, 8)
(7, 8)
(8, 8)
(9, 8)
(10, 8)
(10, 9)
(10, 10)
(10, 11)
(10, 12)
(10, 13)
(10, 14)
(10, 15)
(10, 16)
(10, 17)
(10, 18)
(10, 19)
(10, 20)
(9, 20)
(8, 20)
(8, 21)
(8, 22)
(8, 23)
(8, 24)
(8, 25)
(8, 26)
(8, 27)
(8, 28)
(8, 29)
(8, 30)
(8, 31)
(8, 32)
(8, 33)
(8, 34)
(8, 35)
(8, 36)
(8, 37)
(9, 37)
(10, 37)
(11, 37)
(12, 37)
(12, 36)
(12, 35)
(12, 34)
(12, 33)
(12, 32)
(12, 31)
(12, 30)
(12, 29)
(12, 28)
(12, 27)
(12, 26)
(12, 25)
(12, 24)
(12, 23)
(12, 22)
(12, 21)
(12, 20)
(12, 19)
(13, 19)
(14, 19)
(15, 19)
(16, 19)
(16, 20)
(16, 21)
(16, 22)
(16, 23)
(16, 24)
(16, 25)
(16, 26)
(16, 27)
(16, 28)
(16, 29)
(16, 30)
(16, 31)
(16, 32)
(16, 33)
(16, 34)
(16, 35)
(16, 36)
(16, 37)
(16, 38)
(16, 39)
(16, 40)
(15, 40)
(14, 40)
(13, 40)
(12, 40)
(12, 41)
(12, 42)
(12, 43)
(12, 44)
(12, 45)
(12, 46)
(12, 47)
(13, 47)
(14, 47)
(15, 47)
(15, 48)
(15, 49)
(15, 50)
(15, 51)
(15, 52)
(16, 52)
(16, 53)
(17, 53)
(17, 54)

附:POJ 迷宮問題簡化版

POJ 3984 迷宮問題

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N=1e3+10;
char a[N][N];
bool vis[N][N];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
    int x,y,cnt;
}pre[N][N],path[N*N];
queue<node>q;
void bfs()
{
    q.push({0,0,0});
    while(!q.empty())
    {
        node tmp=q.front();q.pop();
        int x=tmp.x,y=tmp.y,cnt=tmp.cnt;
        if(x==4&&y==4)return;
        vis[x][y]=1;
        for(int i=0;i<4;i++)
        {
            int nx=x+dir[i][0];
            int ny=y+dir[i][1];
            if(nx>=0&&nx<5&&ny>=0&&ny<5&&!vis[nx][ny]&&a[x][y]=='0')
            {
                q.push({nx,ny,cnt+1});
                pre[nx][ny].x=x;
                pre[nx][ny].y=y;
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            cin>>a[i][j];
    bfs();
    int nx=4,ny=4;
    int cnt=0;
    while(1)
    {
        path[++cnt]={nx,ny};
        if(nx==0&&ny==0)break;
        int t1=nx,t2=ny;
        nx=pre[t1][t2].x;
        ny=pre[t1][t2].y;
    }
    for(int i=cnt;i>=1;i--)
        printf("(%d, %d)\n",path[i].x,path[i].y);
    return 0;
}

(三)樹型結構題目

二叉樹的構造
任務:已知二叉樹的層序和中序遍歷序列,或已知二叉樹的先序序列、中序序列,試編寫算法建立該二叉樹( 用遞歸或非遞歸的方法都可以)。
要求:能夠輸入樹的各個結點,並能夠輸出用不同方法遍歷的遍歷序列;分別建立建立二叉樹存儲結構的的輸入函數、輸出層序遍歷序列的函數、輸出先序遍歷序列的函數;

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
typedef struct node
{
    char data;
    struct node *lchild,*rchild;
}node,*Tree;
char pre[N],mid[N];
int get_pos(char s,int l,int r)
{
    for(int i=l;i<=r;i++)
        if(mid[i]==s)return i;
    return -1;
}
void build(Tree &T,int i,int l,int r)//i是遍歷到的先序的位置,[l,r]是中序子表的左右端點
{
    int pos=get_pos(pre[i],l,r);//pos是由先序的i位置得到在中序的位置
    if(pos==-1){T=NULL;return;}
    T=new node;
    T->data=pre[i];
    build(T->lchild,i+1,l,pos-1);
    build(T->rchild,i+pos-l+1,pos+1,r);
}
void pre_travel(Tree T)//先序遍歷
{
    if(T==NULL)return;
    printf("%c",T->data);
    pre_travel(T->lchild);
    pre_travel(T->rchild);
}
void mid_travel(Tree T)//中序遍歷
{
    if(T==NULL)return;
    mid_travel(T->lchild);
    printf("%c",T->data);
    mid_travel(T->rchild);
}
void post_travel(Tree T)//後序遍歷
{
    if(T==NULL)return;
    post_travel(T->lchild);
    post_travel(T->rchild);
    printf("%c",T->data);
}
void level_travel(Tree T)//層次遍歷
{
    queue<Tree>q;
    q.push(T);
    while(!q.empty())
    {
        Tree x=q.front();q.pop();
        printf("%c",x->data);
        if(x->lchild)q.push(x->lchild);
        if(x->rchild)q.push(x->rchild);
    }
}
void output(Tree T)
{
    printf("\n先序遍歷:");
    pre_travel(T);
    printf("\n");
    printf("中序遍歷:");
    mid_travel(T);
    printf("\n");
    printf("後序遍歷:");
    post_travel(T);
    printf("\n");
    printf("層次遍歷:");
    level_travel(T);
    printf("\n");
}
int main()
{
    Tree T;
    printf("請輸入前序序列:");
    cin>>pre+1;
    printf("請輸入中序序列:");
    cin>>mid+1;
    int n=strlen(pre+1);
    build(T,1,1,n);
    output(T);
    return 0;
}

測試數據

輸入:
ABDEFCHKGJ
DBFEAHKCJG
輸出:
先序遍歷:ABDEFCHKGJ
中序遍歷:DBFEAHKCJG
後序遍歷:DFEBKHJGCA
層次遍歷:ABCDEHGFKJ

(四)圖型結構題目

拓撲排序
任務:編寫函數實現圖的拓撲排序。

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m,x,y,cnt,d[N],ans[N];
typedef struct arcnode
{
    int to;
    struct arcnode *next;
}edge;
struct node
{
    int data;
    edge *head;
}v[N];
void add(int x,int y)
{
    edge *s=new edge;
    s->to=y;
    s->next=v[x].head;
    v[x].head=s;
}
void topo_sort()//拓撲排序
{
    int s[N],top=-1;//手寫棧,用數組模擬棧s,指針爲top
    for(int i=1;i<=n;i++)
        if(!d[i])s[++top]=i;//將入度爲0的點入棧
    while(top>-1)
    {
        int x=s[top];top--;
        ans[++cnt]=x;
        for(edge *p=v[x].head;p!=NULL;p=p->next)
        {
            int y=p->to;
            d[y]--;//y的入度減1
            if(!d[y])s[++top]=y;//將入度爲0的點入棧
        }
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>v[i].data;
        v[i].head=NULL;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y;
        d[y]++;//統計每個點的入度
        add(x,y);
    }
    topo_sort();
    for(int i=1;i<=cnt;i++)
        i==cnt?printf("v%d\n",ans[i]):printf("v%d ",ans[i]);
    return 0;
}

測試數據

輸入:
12 16
1 2 3 4 5 6 7 8 9 10 11 12
1 4
1 2
1 3
1 12
4 5
2 3
3 5
3 7
5 7
3 8
9 12
9 10
10 12
9 11
11 6
6 8
輸出:
v9 v10 v11 v6 v1 v4 v2 v3 v5 v7 v8 v12

(五)查找、排序、文件

散列表的插入、刪除和查找
功能要求:
(1)初始化散列表;
(2)向散列表中插入一個元素;
(3)從散列表中刪除一個元素;
(4)從散列表中查找一個元素。
散列表通常採用鏈接法處理衝突,散列文件中每個節點的類型定義爲:
Struct FLNode
{ //散列主文件中的節點類型
ElemType data ; //值域
Int *next; //指向下一個節點的指針域
};
其中data域用來存儲待散列的元素,next域用來存儲下一個同義詞元素在散列表中的存儲位置,即所在節點的位置號。

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=20,mod=13;//哈希函數H(x)=x%mod
typedef struct node
{
    int data;
    struct node *next;
}node,*linklist;
int n,x;
linklist L[N];
void init()//初始化散列表
{
    for(int i=0;i<mod;i++)
    {
        L[i]=new node;
        L[i]->next=NULL;
    }
}
void insert_L(int x)//插入x
{
    int y=x%mod;//哈希函數H(x)=x%mod
    linklist head=L[y];
    linklist s=new node;
    s->data=x;
    s->next=head->next;
    head->next=s;
}
void output()//輸出散列表
{
    for(int i=0;i<mod;i++)
    {
        printf("%d:",i);
        linklist p=L[i]->next;
        while(p)
        {
            if(p->next)printf("%d ",p->data);
            else printf("%d",p->data);
            p=p->next;
        }
        printf("\n");
    }
}
void seek(int x)//查找x
{
    int y=x%mod;
    linklist p=L[y]->next;
    int cnt=0;
    while(p)
    {
        cnt++;
        if(p->data==x)
        {
            printf("查找成功!\n");
            printf("查找的元素 %d 在第 %d 個鏈表的第 %d 個節點\n",x,y,cnt);
            return;
        }
        p=p->next;
    }
    printf("查找失敗!\n");
}
void del(int x)//刪除x
{
    int y=x%mod;
    linklist p=L[y];
    while(p->next)
    {
        if(p->next->data==x)
        {
            linklist tmp=p->next;
            p->next=tmp->next;
            delete tmp;
            printf("刪除成功!\n當前散列表:\n");
            output();
            return;
        }
        p=p->next;
    }
    printf("要刪除的節點不存在!\n");
}
int main()
{
    ios::sync_with_stdio(false);
    init();
    printf("請輸入若干個數插入到散列表中(輸入0時結束輸入):\n");
    while(cin>>x&&x)
    {n++;insert_L(x);}
    printf("\n當前散列表:\n");
    output();
    printf("\n請輸入要查找的元素:\n");
    cin>>x;
    seek(x);
    printf("\n請輸入要刪除的元素:\n");
    cin>>x;
    del(x);
    return 0;
}

測試數據

test_01
輸入:
19 14 23 1 68 20 84 27 55 11 10 79 0
55
55
輸出:
在這裏插入圖片描述

test_02
輸入:
19 14 23 1 68 20 84 27 55 11 10 79 0
100
100
輸出:
在這裏插入圖片描述

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