【啊哈!算法】棧、隊列、鏈表

棧、隊列、鏈表


  • 隊列
  • 紙牌遊戲 小貓釣魚
  • 鏈表
  • 模擬鏈表

隊列


特點:管子,兩邊開口,先進先出 (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.

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