資料結構實驗之佇列一:排隊買飯遇到的函式傳值問題

勤學鳥發表於2018-04-17

資料結構實驗之佇列一:排隊買飯
Problem Description
中午買飯的人特多,食堂真是太擁擠了,買個飯費勁,理工大的小孩還是很聰明的,直接奔政通超市,哈哈,確實,政通超市裡面也賣飯,有好幾種菜,做的比食堂好吃多了,價格也不比食堂貴,並且買菜就送豆漿,吸引了不少童鞋。所以有時吧,人還是很多的,排隊是免不了的,悲劇的是超市只有兩個收銀視窗。

問題是這樣的:開始有兩隊人在排隊,現在我們們只研究第一隊,現在我們給每個人一個編號,保證編號各不相同,排在前面的人買完飯就走了,有些人挑完飯就排在後面等待付款,還有一些人比較聰明,看到另一個隊人比較少,直接離開這個隊到另一個隊去了。我要問的是隊的總人數和某個位置上人的編號。

Input
首先輸入一個整數m(m<10000),代表當前有m個人,第二行輸入m個數,代表每個人的編號,第三行輸入一個整數n(n<10000),代表佇列變動和詢問一共n次,以後n行,JOIN X表示編號為X(保證與以前的編號不同)的人加入;LEAVE Y表示第Y(Y小於當前佇列長度)個位置 上的人離隊 ;ASK Z(Z小於當前佇列長度)表示詢問第Z個位置上的人的編號;FINISH D表示有D個人買完飯離開了;LENGTH表示詢問佇列的長度 。保證所有資料在int 範圍內.

Output
對每個詢問輸出相應的答案,每個答案佔一行。

Sample Input
3
1 2 3
6
JOIN 4
ASK 2
LEAVE 2
LENGTH
FINISH 2
LENGTH
Sample Output
2
3
1
Hint

#include <iostream>
using namespace std;
struct Team
{
    int num;
    Team* next;
};
Team* Create(Team *head, int n)
{
    Team *p = head;
    for (int i = 0; i < n; i++)
    {
        Team *q = new Team();
        cin >> q->num;
        p->next = q;
        q->next = NULL;
        p = q;
    }
    return p;
}
void Join(Team *p, int n)
{
    Team *q = new Team();
    q->num = n;
    p->next = q;
    q->next = NULL;
    p = q;
}
void Leave(Team* head, int n, Team* t)
{
    Team* p = head;
    n = n - 1;
    //之所以要先讓n-1,是想保證p在要刪除結點的前驅,便於刪除
    while (n--)
    {
        p = p->next;
    }

    if (p->next == t)
    {
        t = p;
    }
    Team *q = p->next;
    p->next = p->next->next;
    delete q;

}
void Finish(Team* head, int n, Team* t)
{
    while (n--)
    {
        Team *p = head->next;
        if (!p)
            break;
        if (t == head->next)
            t = head;
        head->next = head->next->next;
        delete p;
    }
}
int Ask(Team *head, int n)
{
    Team *p = head;
    while (n--)
    {
        p = p->next;
    }
    return p->num;
}
int Length(Team* head)
{
    int num = 0;
    Team *p = head;
    while (p->next)
    {
        num++;
        p = p->next;
    }
    return num;
}
int main()
{
    int m;
    cin >> m;
    Team* head = new Team();
    Team* p = Create(head, m);
    int n;
    cin >> n;
    while (n--)
    {
        string s;
        cin >> s;
        if (s == "JOIN")
        {
            int num;
            cin >> num;
            Join(p, num);
        }
        else if (s == "LEAVE")
        {
            int num;
            cin >> num;
            Leave(head, num, p);
        }
        else if (s == "ASK")
        {
            int num;
            cin >> num;
            cout << Ask(head, num) << endl;
        }
        else if (s == "FINISH")
        {
            int num;
            cin >> num;
            Finish(head, num, p);
        }
        else if (s == "LENGTH")
        {
            cout << Length(head) << endl;
        }
    }
    return 0;
}

這裡寫圖片描述
執行結果和給的例項一樣,但是提交後是WrongAnswer,經過除錯後發現問題出現在Join函式上
這裡寫圖片描述
在1,2,3的佇列中新增4,再新增5,詢問第4個位置的人的時候,竟然報號5,說明Join 5的時候加到了4的前面,3的後面了。
分析下出現這種情況的原因:其實是函式傳值中的問題沒有搞清楚

函式傳值問題

傳遞變數

void f1(int a, int b)
{
    cout << "這是f1(int a, int b)" << endl;
    cout << "a的地址:" << &a << endl;
    cout << "b的地址:" << &b << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "交換a,b的值之後:" << endl;
    int t = a;
    a = b;
    b = t;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
}

int main()
{
    int a,b;
    a = 5;
    b = 7;
    cout << "這是在主函式中:" << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "a的地址:" << &a << endl;
    cout << "b的地址:" << &b << endl;
    cout << "---------------------------" << endl;
    f1(a, b);
    cout << "---------------------------" << endl;
    cout << "這是在主函式中:" << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "---------------------------" << endl;
    return 0;
}

這裡寫圖片描述
可見,直接傳變數,傳遞的是變數的值,而不是變數本身,即在函式中是另外分配了空間來儲存傳進來的值的,不是對變數本身的操作,從它們地址的不同就可以體現。而且在函式中對a,b變數值的修改是不影響主函式中a,b的值。

傳遞指標

void f2(int* pa, int* pb)
{
    cout << "這是f2(int* pa, int* pb)" << endl;
    cout << "pa存放的地址:" << pa << endl;
    cout << "pb存放的地址:" << pb << endl;
    cout << "pa的地址:" << &pa << endl;
    cout << "pb的地址:" << &pb << endl;
    cout << "交換*pa,*pb的值:" << endl;
    int n = *pa;
    *pa = *pb;
    *pb = n;
    cout << "*pa:" << *pa << endl;
    cout << "*pb:" << *pb << endl;
    cout << "交換pa,pb存放的地址:" << endl;
    int* m;
    m  = pa;
    pa = pb;
    pb = m;
    cout << "pa存放的地址:" << pa << endl;
    cout << "pb存放的地址:" << pb << endl;
}

int main()
{
    int a,b;
    a = 5;
    b = 7;
    int* pa = &a;
    int* pb = &b;
    cout << "這是在主函式中:" << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "a的地址:" << &a << endl;
    cout << "b的地址:" << &b << endl;
    cout << "pa存放的地址:" << pa << endl;
    cout << "pb存放的地址:" << pb << endl;
    cout << "pa的地址:" << &pa << endl;
    cout << "pb的地址:" << &pb << endl;
    cout << "---------------------------" << endl;
    f2(pa, pb);
    cout << "---------------------------" << endl;
    cout << "這是在主函式中:" << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "pa存放的地址:" << pa << endl;
    cout << "pb存放的地址:" << pb << endl;
    cout << "---------------------------" << endl;
    return 0;
}

這裡寫圖片描述
可見,傳遞指標,傳遞的是指標的值,而不是指標本身,即在函式中是另外分配了空間來儲存傳進來的值的,不是對指標本身的操作,從它們地址的不同就可以體現。而且在函式中對pa,pb變數值的修改是不影響主函式中pa,pb的值。這很容易理解,因為指標就是一種“型別”啊,對指標的操作和上面對變數操作沒區別。
但是對*pa,*pb的操作會影響到a,b的值,因為這是對a,b的地址的操作。

傳遞引用

void f3(int &a, int &b)
{
    cout << "這是f3(int &a, int &b)" << endl;
    cout << "a的地址:" << &a << endl;
    cout << "b的地址:" << &b << endl;
    int t = a;
    a = b;
    b = t;
}

int main()
{
    int a,b;
    a = 5;
    b = 7;
    cout << "這是在主函式中:" << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "a的地址:" << &a << endl;
    cout << "b的地址:" << &b << endl;
    cout << "---------------------------" << endl;
    f3(a, b);
    cout << "---------------------------" << endl;
    cout << "這是在主函式中:" << endl;
    cout << "a的值:" << a << endl;
    cout << "b的值:" << b << endl;
    cout << "a的地址:" << &a << endl;
    cout << "b的地址:" << &b << endl;
    cout << "---------------------------" << endl;
    return 0;
}

這裡寫圖片描述
可見,傳遞引用傳遞的就是變數本身。

小結:以前一直以為傳遞指標和傳遞引用是一樣的,在函式中修改值都會傳回到主函式,現在才弄明白指標和引用還是有區別的。

好的,弄明白函式傳值的效果,就可以著手修改上面的程式了。

#include <iostream>
using namespace std;
struct Team
{
    int num;
    Team* next;
};
Team* Create(Team *head, int n)
{
    Team *p = head;
    for (int i = 0; i < n; i++)
    {
        Team *q = new Team();
        cin >> q->num;
        p->next = q;
        q->next = NULL;
        p = q;
    }
    return p;
}
Team* Join(Team *p, int n) //這裡將修改後的p直接作為返回值返回
{
    Team *q = new Team();
    q->num = n;
    p->next = q;
    q->next = NULL;
    p = q;
    return p;
}
void Leave(Team* head, int n, Team* &t)//因為傳遞指標實質上是傳遞值,所以這裡使用引用來傳值
{
    Team* p = head;
    n = n - 1;
    while (n--)
    {
        p = p->next;
    }
    if (p->next == t)
    {
        t = p;
    }
    Team *q = p->next;
    p->next = p->next->next;
    delete q;

}
void Finish(Team* head, int n, Team* &t)//同上
{
    while (n--)
    {
        Team *p = head->next;
        if (!p)
            break;
        if (t == head->next)
            t = head;
        head->next = head->next->next;
        delete p;
    }
}
int Ask(Team *head, int n)
{
    Team *p = head;
    while (n--)
    {
        p = p->next;
    }
    return p->num;
}
int Length(Team* head)
{
    int num = 0;
    Team *p = head;
    while (p->next)
    {
        num++;
        p = p->next;
    }
    return num;
}
int main()
{
    int m;
    cin >> m;
    Team* head = new Team();
    Team* p = Create(head, m);
    int n;
    cin >> n;
    while (n--)
    {
        string s;
        cin >> s;
        if (s == "JOIN")
        {
            int num;
            cin >> num;
            p = Join(p, num);
        }
        else if (s == "LEAVE")
        {
            int num;
            cin >> num;
            Leave(head, num, p);
        }
        else if (s == "ASK")
        {
            int num;
            cin >> num;
            cout << Ask(head, num) << endl;
        }
        else if (s == "FINISH")
        {
            int num;
            cin >> num;
            Finish(head, num, p);
        }
        else if (s == "LENGTH")
        {
            cout << Length(head) << endl;
        }
    }
    return 0;
}

AC了!!!!

相關文章