棧、隊列、鏈表
- 隊列
- 棧
- 紙牌遊戲 小貓釣魚
- 鏈表
- 模擬鏈表
隊列
特點:管子,兩邊開口,先進先出 (First In First Out)
隊列的三個基本元素:一個數組,兩個變量
#include<iostream>
using namespace std;
struct queue {
int data[100]; //隊列主體,用來存儲內容
int head; //隊首
int tail; //隊尾
};
typedef struct queue Queue; //將 struct queue 重命名爲 Queue
int main() {
Queue q;
//初始化隊列
q.head = 1;
q.tail = 1;
for(int i = 0; i < 5; i++) {
cin >> q.data[q.tail];
q.tail++; //進隊列
}
while (q.head < q.tail) {
cout << q.data[q.head];
q.head++; //出隊列
}
return 0;
}
棧
特點:管子,一邊開口,後進先出 (Last In First Out)
棧的基本元素:一個數組,一個變量
#include<iostream>
using namespace std;
struct stack {
int data[100]; //棧主體,用來存儲內容
int top; //棧頂 棧頂指針 top 指向的是棧頂上的一個空間
};
typedef struct stack Stack; //將 struct stack 重命名爲 Stack
int main() {
Stack s;
//初始化棧
s.top = 0;
for(int i = 0; i < 5; i++) {
cin >> s.data[s.top];
s.top++; //入棧 壓棧
}
while (s.top > 0) {
s.top--; //出棧
cout << s.data[s.top];
}
return 0;
}
紙牌遊戲 小貓釣魚
Question:俗稱 “接竹竿”,就是接牌,有相同的將二者之間的牌收入手裏,一方無牌則敗
分析:兩人手中的牌是隊列,桌面上的牌是棧
約定:牌面 1~9
#include<iostream>
using namespace std;
struct stack {
int data[100]; //棧主體
int top; //棧頂
};
struct queue {
int data[1000];
int head;
int tail;
};
typedef struct stack Stack;
typedef struct queue Queue;
int main() {
Stack s;
Queue q, p;
int book[10];
s.top = 0;
q.head = 0; q.tail = 0;
p.head = 0; p.tail = 0;
//初始化標記數組
for (int i = 1; i <= 9; i++) {
book[i] = 0;
}
//讀入牌 每人六張
cout << "input q: ";
for (int i = 0; i < 6; i++) {
cin >> q.data[q.tail];
q.tail++;
}
cout << "input p: ";
for (int i = 0; i < 6; i++) {
cin >> p.data[p.tail];
p.tail++;
}
while(q.head < q.tail && p.head < p.tail) {
//q出牌
int t = q.data[q.head];
q.head++; //出隊
// int flag = 0;
// for (int i = 0; i < s.top; i++) { //遍歷棧 這裏是遍歷表示棧的數組
// if(t == s.data[i]) {
// flag = 1;
// break;
// }
// } //用標記數組來判斷比遍歷棧要方便
// if (flag == 0) {
if (book[t] == 0) {
s.data[s.top] = t;
s.top++; //入棧
book[t] = 1;
}
else {
q.data[q.tail] = t;
q.tail++; //入隊
do {
q.data[q.tail] = s.data[s.top - 1];
q.tail++;
book[s.data[s.top - 1]] = 0;
s.top--;
} while (s.data[s.top] != t); //這裏是取了數組的巧
}
if (q.head == q.tail) break;
//p出牌
t = p.data[p.head];
p.head++;
if(book[t] == 0) {
s.data[s.top] = t;
s.top++;
book[t] = 1;
}
else {
p.data[p.tail] = t;
p.tail++;
do {
p.data[p.tail] = s.data[s.top - 1];
p.tail++;
book[s.data[s.top - 1]] = 0;
s.top--;
} while (s.data[s.top] != t);
}
if (p.head == p.tail) break;
cout << "q current: ";
for (int i = q.head; i < q.tail; i++) {
cout << q.data[i] << " ";
}
cout << endl;
cout << "p current: ";
for (int i = p.head; i < p.tail; i++) {
cout << p.data[i] << " ";
}
cout << endl;
}
if (p.head = p.tail) {
cout << "q victory current: " << endl;
for (int i = q.head; i < q.tail; i++) {
cout << q.data[i] << " ";
}
}
else {
cout << "p victory current: " << endl;
for (int i = p.head; i < p.tail; i++) {
cout << p.data[i] << " ";
}
}
cout << endl;
if (s.top > 0) {
cout << "stack still have: " << endl;
for (int i = 0; i < s.top; i++) {
cout << s.data[i] << " ";
}
}
else {
cout << "stack is empty." << endl;
}
return 0;
}
鏈表
概念:指針變量 p
,作用是存儲一個內存空間的首地址 p = &a
- 間接訪問運算符
*
,作用是取得指針p
所指向的內存中的值,還有可以用作聲明指針變量 - 動態存儲:
malloc(4)
;作用是從內存中申請分配指定字節大小的內存空間,此處申請四個字節,它的返回是一個指向該空間的 void * 通用指針,需要強轉
若不知int
佔用幾個字節,可以用sizeof(int)
獲取,寫出就是malloc(sizeof(int))
- 對動態申請的空間進行操作:
int *p;
p = (int *)malloc(sizeof(int)); //malloc 返回的是 void *,需要強制轉換成 int *
- 訪問結構體內部成員:有兩種方式
.
和->
,指針變量不能用.
訪問,只能用後者p->data
如果你必須要用.
的話也行,不過在這之前需要將指針指向的內存中的東西取出 像這樣(*p).data
,因爲*
的優先級低於.
free(p)
的作用:將指針還原爲未初始化狀態並使內存塊在堆上重新變成可用狀態
鏈表的實現:
#include<iostream>
#include<cstdlib>
using namespace std;
struct node {
int data;
struct node *next; //結構體指針變量 next
};
int main() {
struct node *head, *q, *p;
int n;
head = NULL;
cout << "input n: ";
cin >> n;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
//動態申請一個空間,放一個結點,並用臨時指針 p 指向它
p = (struct node *)malloc(sizeof(struct node));
p->data = a;
p->next = NULL;
if(head == NULL) {
head = p;
}
else {
q->next = p;
}
q = p;
} //一個長度爲 n 的鏈表建成
//輸出一下
struct node *t;
t = head;
while (t != NULL) {
cout << t->data << " ";
t = t->next;
}
//結束時建議用 free 命令釋放動態申請的空間
free(head);
free(q);
free(p);
free(t);
return 0;
}
插入結點:
int a;
cin >> a;
t = head; //遍歷
while (t != NULL) {
if (t->next == NULL || t->next->data > a) { //當 t 爲最後一個結點 或 t 的下一個結點的數據域的值大於 a 時插入 p 結點
p = (struct node *)malloc(sizeof(struct node));
p->data = a;
p->next = NULL;
p->next = t->next;
t->next = p;
break;
}
}
模擬鏈表
就是用兩個數組,其中一個數組做數據域的集合,另一個數組做指針域的集合
End.