資料結構實驗之佇列一:排隊買飯遇到的函式傳值問題
資料結構實驗之佇列一:排隊買飯
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了!!!!
相關文章
- 資料結構之「佇列」資料結構佇列
- 資料結構之php實現佇列資料結構PHP佇列
- 【php實現資料結構】鏈式佇列PHP資料結構佇列
- java 資料結構 之 佇列的實現 (二)Java資料結構佇列
- 資料結構實驗5、鏈佇列的基本操作資料結構佇列
- JavaScript資料結構之-佇列JavaScript資料結構佇列
- 資料結構之佇列(Queue)資料結構佇列
- JavaScript資料結構之佇列JavaScript資料結構佇列
- python資料結構之棧、佇列的實現Python資料結構佇列
- 重學資料結構之佇列資料結構佇列
- 資料結構之「雙端佇列」資料結構佇列
- 資料結構學習之佇列資料結構佇列
- 資料結構之棧和佇列資料結構佇列
- 實戰PHP資料結構基礎之佇列PHP資料結構佇列
- php實現基本資料結構之棧、佇列PHP資料結構佇列
- C語言資料結構:鏈式佇列的建立及其出入隊操作C語言資料結構佇列
- JavaScript資料結構之陣列棧佇列JavaScript資料結構陣列佇列
- 資料結構-佇列資料結構佇列
- 【資料結構-----佇列】資料結構佇列
- 資料結構 - 佇列資料結構佇列
- js實現資料結構--佇列JS資料結構佇列
- 資料結構二之棧和佇列資料結構佇列
- 【資料結構】佇列(順序佇列、鏈佇列)的JAVA程式碼實現資料結構佇列Java
- 資料結構棧和佇列排隊演算法應用的例子【停車場停車位排隊管理系統】資料結構佇列演算法
- Java版-資料結構-佇列(陣列佇列)Java資料結構佇列陣列
- 資料結構-佇列-樹資料結構佇列
- 資料結構—棧/佇列資料結構佇列
- 資料結構-佇列、棧資料結構佇列
- 資料結構之PHP(最大堆)實現優先佇列資料結構PHP佇列
- 畫江湖之資料結構【第二話:佇列和棧】佇列資料結構佇列
- 畫江湖之資料結構 [第二話:佇列和棧] 佇列資料結構佇列
- 資料結構——迴圈佇列PTA習題資料結構佇列
- Java版-資料結構-佇列(迴圈佇列)Java資料結構佇列
- 資料結構:特殊的線性表之 棧 & 佇列資料結構佇列
- 資料結構-js實現棧和佇列資料結構JS佇列
- 資料結構 使用2個棧實現一個佇列資料結構佇列
- 棧與佇列鏈式儲存結構一貨物上架問題佇列
- JavaScript資料結構03 – 佇列JavaScript資料結構佇列