0% found this document useful (0 votes)
5 views32 pages

Lab 2

The document contains C++ code for implementing linked lists and polynomials using classes. It includes definitions for classes such as 'element', 'linkedlist', 'Term', and 'Polynomial', along with their respective methods for operations like insertion, deletion, and evaluation. Additionally, it features a library management system with a 'Book' structure and a 'Library' class for managing book records.

Uploaded by

leminhquan150505
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views32 pages

Lab 2

The document contains C++ code for implementing linked lists and polynomials using classes. It includes definitions for classes such as 'element', 'linkedlist', 'Term', and 'Polynomial', along with their respective methods for operations like insertion, deletion, and evaluation. Additionally, it features a library management system with a 'Book' structure and a 'Library' class for managing book records.

Uploaded by

leminhquan150505
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 32

Phần I: Danh sách liên kết

//element.h
#pragma once
#ifndef ELEMENT_H
#define ELEMENT_H

class element
{
private:
int data;
element* pointer;

public:
element();
element(int);
virtual ~element();

int Getdata() { return data; }


void Setdata(int val) { data = val; }
element* Getpointer() { return pointer; }
void Setpointer(element* val) { pointer = val; }

protected:

};

#endif // ELEMENT_H

//element.cpp
#include "element.h"

element::element() {
//ctor
this->data = 0;
this->pointer = nullptr;
}
element::element(int data) {
//ctor
this->data = data;
this->pointer = nullptr;
}
element::~element() {
//dtor
}

//linkedlist.h
#pragma once
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "element.h"

class linkedlist {
private:
element* head;
element* tail;
int nNum;
public:
linkedlist();
virtual ~linkedlist();
element* Gethead() { return head; }
void Sethead(element* val) { head = val; }
element* Gettail() { return tail; }
void Settail(element* val) { tail = val; }
void InsertFirst(element*);
void InsertTail(element*);
bool InsertAt(element*, int);
bool DeleteFirst();
bool DeleteTail();
bool DeleteAt(element*);
void Travel();
int SumList();
int MaxList();
int CountPrime();
int CountOccurrences(int);
void SplitList(int, linkedlist&, linkedlist&);
protected:
};
#endif // LINKEDLIST_H

//linkedlist.cpp
#include "linkedlist.h"
#include <iostream>
using namespace std;

linkedlist::linkedlist() {
//ctor
this->head = nullptr;
this->tail = nullptr;
this->nNum = 0;
}
linkedlist::~linkedlist() {
//dtor
}

void linkedlist::InsertFirst(element* e) {
if (this->head == nullptr)
this->head = this->tail = e;
else {
e->Setpointer(this->head); //step 1
this->head = e; // step 2
}

this->nNum++;
}

void linkedlist::InsertTail(element* e) {
if (this->head == nullptr)
this->head = this->tail = e;
else {
this->tail->Setpointer(e);// step 1
this->tail = e; // step 2
}

this->nNum++;
}
bool linkedlist::InsertAt(element* p, int value) {
if (p == nullptr) {
return false;
}

element* temp = this->head;


while (temp != nullptr) {
if (temp->Getdata() == value) {
return false; // Nếu giá trị đã tồn tại, không thêm vào danh
sách
}
temp = temp->Getpointer();
}

element* newElement = new element(value);

if (p == this->head) {
this->InsertFirst(newElement);
}
else {
newElement->Setpointer(p->Getpointer());
p->Setpointer(newElement);

if (p == this->tail) {
this->tail = newElement;
}
}

return true;
}

void linkedlist::Travel() {
element* p = this->head;
while (p != nullptr) {
cout << p->Getdata() << " ";
p = p->Getpointer();
}
cout << "\n";
}
bool linkedlist::DeleteFirst() {
if (this->head == nullptr) return false;
else {
element* p = this->head;
this->head = this->head->Getpointer();
delete p;
return true;
}
}

bool linkedlist::DeleteTail() {
if (this->head == nullptr) {
return false;
}

if (this->head == this->tail) {
delete this->head;
this->head = this->tail = nullptr;
}
else {
element* p = this->head;
while (p->Getpointer() != this->tail) {
p = p->Getpointer();
}
delete this->tail;

this->tail = p;
this->tail->Setpointer(nullptr);
}
this->nNum--;
return true;
}

bool linkedlist::DeleteAt(element* p) {
if (this->head == nullptr || p == nullptr) {
return false;
}

if (p == this->head) {
return this->DeleteFirst();
}

if (p == this->tail) {
return this->DeleteTail();
}

// Tìm phần tử ngay trước `p`


element* prev = this->head;
while (prev->Getpointer() != p && prev->Getpointer() != nullptr) {
prev = prev->Getpointer();
}

if (prev->Getpointer() == nullptr) {
return false;
}

// Xóa phần tử `p` ra khỏi danh sách


prev->Setpointer(p->Getpointer());
delete p;

this->nNum--;
return true;
}

int linkedlist::SumList() {
int sum = 0;
element* p = this->head;
while (p != nullptr) {
sum += p->Getdata();
p = p->Getpointer();
}
return sum;
}

int linkedlist::MaxList() {
if (this->head == nullptr) {
throw runtime_error("List is empty, no maximum value."); // Xử lý
danh sách rỗng
}

element* p = this->head;
int maxVal = p->Getdata();

while (p != nullptr) {
if (p->Getdata() > maxVal) {
maxVal = p->Getdata();
}
p = p->Getpointer();
}
return maxVal;
}

bool isPrime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}

int linkedlist::CountPrime() {
int count = 0;
element* p = this->head;

while (p != nullptr) {
if (isPrime(p->Getdata())) count++;
p = p->Getpointer();
}
cout << endl;
return count;
}

int linkedlist::CountOccurrences(int x) {
int count = 0;
element* p = this->head;

while (p != nullptr) {
if (p->Getdata() == x) {
count++;
}
p = p->Getpointer();
}
return count;
}

void linkedlist::SplitList(int x, linkedlist& smaller, linkedlist& larger) {


element* p = this->head;

// Duyệt qua danh sách liên kết gốc


while (p != nullptr) {
// Nếu giá trị của p nhỏ hơn x, thêm vào danh sách "smaller"
if (p->Getdata() < x) {
smaller.InsertTail(new element(p->Getdata()));
}
// Nếu giá trị của p lớn hơn x, thêm vào danh sách "larger"
else if (p->Getdata() > x) {
larger.InsertTail(new element(p->Getdata()));
}
p = p->Getpointer(); // Chuyển sang phần tử tiếp theo
}
}

//main.cpp
#include <iostream>
#include "linkedlist.h"
using namespace std;

int main() {
linkedlist* list_ = new linkedlist();
linkedlist smallerList;
linkedlist largerList;
element* e;
int x, y;
cout << "Nhap x (tim phan tu trung voi x): ";
cin >> x;
cout << "Nhap y (gia tri tach danh sach): ";
cin >> y;
cout << "\n";

// cau 4
e = new element(9);
list_->InsertTail(e);

e = new element(10);
list_->InsertTail(e);

e = new element(8);
list_->InsertTail(e);

element* e1 = new element(7);


element* e2 = new element(17);

// cau 5
list_->InsertFirst(e1);
list_->InsertFirst(e2);
// bo sung cau 10
list_->InsertAt(e1, 13);
list_->Travel();

// cau 1
cout << "Sum List: " << list_->SumList() << endl;

// cau 2
cout << "Max List: " << list_->MaxList() << endl;

// cau 3
cout << "Prime : " << list_->CountPrime() << endl;

// cau 9
cout << "So luong phan tu trung voi x: " << list_->CountOccurrences(x)
<< endl;

// cau 11
list_->SplitList(y, smallerList, largerList);

cout << "Smaller than " << y << ": ";


smallerList.Travel();
cout << "Larger than " << y << ": ";
largerList.Travel();

// cau 6
list_->DeleteFirst();
cout << "\n";
list_->Travel();

// cau 7
list_->DeleteTail();
cout << "\n";
list_->Travel();

// cau 8
list_->DeleteAt(e1);
cout << "\n";
list_->Travel();

return 0;
}

Bài tập ứng dụng:


1.
//Term.h
#pragma once
class Term
{
private:
int heso;
int bac;
Term* next;
public:
Term();
Term(int, int);
virtual ~Term();
int getHeso() const { return heso; }
void setHeso(int val) { heso = val; }
int getBac() const { return bac; }
void setBac(int val) { bac = val; }
Term* getNext() { return next; }
void setNext(Term* val) { next = val; }
};

//Term.cpp
#include "Term.h"

Term::Term() {
this->heso = 0;
this->bac = 0;
this->next = nullptr;
}

Term::Term(int heso, int bac) {


this->heso = heso;
this->bac = bac;
this->next = nullptr;
}

Term::~Term(){
//dtor
}

//Polynomial.h
#pragma once
#include "Term.h"

class Polynomial
{
private:
Term* head;
public:
Polynomial();
virtual ~Polynomial();
void AddTerm(int heso, int bac);
void Input();
void Print() const; // In đa thức
double Evaluate(double x); // Tính giá trị đa thức
Polynomial Add(const Polynomial& other); // Cộng hai đa thức
Polynomial Multiply(const Polynomial& other); // Nhân hai đa thức
};

//Polynomial.cpp
#include "Polynomial.h"
#include <iostream>
using namespace std;

Polynomial::Polynomial() {
this->head = nullptr;
}

Polynomial::~Polynomial() {
//dtor
}

void Polynomial::AddTerm(int heso, int bac) {


if (heso == 0) return;

Term* newTerm = new Term(heso, bac);

// Chèn vào danh sách theo thứ tự bậc giảm dần


if (!head || head->getBac() < bac) {
newTerm->setNext(head);
head = newTerm;
}
else {
Term* curr = head;
while (curr->getNext() && curr->getNext()->getBac() > bac) {
curr = curr->getNext();
}

if (curr->getBac() == bac) {
curr->setHeso(curr->getHeso() + heso); // Gộp hệ số nếu bậc đã tồn tại
delete newTerm;
if (curr->getHeso() == 0) { // Xóa nút nếu hệ số bằng 0
Term* temp = curr->getNext();
delete curr;
curr = temp;
}
}
else {
newTerm->setNext(curr->getNext());
curr->setNext(newTerm);
}
}
}

void Polynomial::Input() {
int heso, bac;
cout << "Nhap da thuc (nhap he so = 0 de ket thuc):\n";
while (true) {
cout << "He so: ";
cin >> heso;
if (heso == 0) break;

cout << "Bac: ";


cin >> bac;

AddTerm(heso, bac);
}
}

void Polynomial::Print() const {


Term* curr = head;
while (curr) {
if (curr != head && curr->getHeso() > 0) {
cout << " + ";
}
cout << curr->getHeso() << "x^" << curr->getBac();
curr = curr->getNext();
}
cout << endl;
}

double Polynomial::Evaluate(double x) {
double result = 0.0;
Term* curr = head;
while (curr) {
result += curr->getHeso() * pow(x, curr->getBac());
curr = curr->getNext();
}
return result;
}

Polynomial Polynomial::Add(const Polynomial& other) {


Polynomial result;
Term* p1 = this->head;
Term* p2 = other.head;

while (p1 || p2) {


if (p1 && (!p2 || p1->getBac() > p2->getBac())) {
result.AddTerm(p1->getHeso(), p1->getBac());
p1 = p1->getNext();
}
else if (p2 && (!p1 || p2->getBac() > p1->getBac())) {
result.AddTerm(p2->getHeso(), p2->getBac());
p2 = p2->getNext();
}
else {
result.AddTerm(p1->getHeso() + p2->getHeso(), p1->getBac());
p1 = p1->getNext();
p2 = p2->getNext();
}
}
return result;
}

Polynomial Polynomial::Multiply(const Polynomial& other) {


Polynomial result;
for (Term* p1 = this->head; p1; p1 = p1->getNext()) {
for (Term* p2 = other.head; p2; p2 = p2->getNext()) {
result.AddTerm(p1->getHeso() * p2->getHeso(), p1->getBac() + p2-
>getBac());
}
}
return result;
}
//main.cpp
#include "Term.h"
#include "Polynomial.h"
#include <iostream>
using namespace std;

int main() {
Polynomial p1, p2;

cout << "Nhap da thuc 1:\n";


p1.Input();

cout << "Nhap da thuc 2:\n";


p2.Input();

cout << "Da thuc 1: ";


p1.Print();

cout << "Da thuc 2: ";


p2.Print();

Polynomial p3 = p1.Add(p2);
cout << "Tong 2 da thuc: ";
p3.Print();

Polynomial p4 = p1.Multiply(p2);
cout << "Tich 2 da thuc: ";
p4.Print();

return 0;
}
2.
//Book.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;

struct Book {
string title; // Tên sách
vector<string> authors; // Danh sách tác giả
string publisher; // Nhà xuất bản
int year; // Năm xuất bản
Book* next;

Book(string t, vector<string> a, string p, int y);


};

//Book.cpp
#include "Book.h"

Book::Book(string t, vector<string> a, string p, int y) {


title = t;
authors = a;
publisher = p;
year = y;
}

//Libary.h
#pragma once
#include "Book.h"

class Library {
private:
Book* head; // Đầu danh sách liên kết

public:
Library() : head(nullptr) {}
~Library();

void AddBook(); // Thêm sách mới


void ListBooks() const; // Liệt kê danh sách sách
int CountBooksByAuthor(const std::string& author) const; // Đếm số sách
theo tác giả
void FindBooksByPublisherYear(const std::string& publisher, int year) const;
// Tìm sách theo NXB và năm
};

//Libary.cpp
#include "Libary.h"

Library::~Library() {
while (head) {
Book* temp = head;
head = head->next;
delete temp;
}
}

void Library::AddBook() {
string title, publisher, author;
int year, numAuthors;
cout << "Nhap ten sach: ";
getline(cin, title);

cout << "Nhap so luong tac gia: ";


cin >> numAuthors;
cin.ignore();

vector<string> authors;
for (int i = 0; i < numAuthors; ++i) {
cout << "Nhap ten tac gia: " << i + 1 << ": ";
getline(cin, author);
authors.push_back(author);
}

cout << "Nhap NXB: ";


getline(cin, publisher);

cout << "Nhap nam xuat ban: ";


cin >> year;
cin.ignore();

Book* newBook = new Book(title, authors, publisher, year);

newBook->next = head;
head = newBook;
}

void Library::ListBooks() const {


Book* current = head;
while (current) {
cout << "Ten sach: " << current->title << "\n";
cout << "Tac gia: ";
for (const auto& author : current->authors) {
cout << author << " ";
}
cout << "\nNXB: " << current->publisher << "\n";
cout << "Nam xuat ban: " << current->year << "\n";
cout << "--------------------------\n";
current = current->next;
}
}

int Library::CountBooksByAuthor(const string& author) const {


int count = 0;
Book* current = head;
while (current) {
for (const auto& a : current->authors) {
if (a == author) {
++count;
break;
}
}
current = current->next;
}
return count;
}

void Library::FindBooksByPublisherYear(const string& publisher, int year)


const {
Book* current = head;
cout << "Danh sach tu NXB " << publisher << " nam " << year << ":\n";
bool found = false;
while (current) {
if (current->publisher == publisher && current->year == year) {
cout << "- " << current->title << "\n";
found = true;
}
current = current->next;
}
if (!found) {
cout << "Khong tim thay sach\n";
}
}

//main.cpp
#include "Book.h"
#include "Libary.h"
int main() {
Library library;
int choice;

do {
cout << "Menu:\n";
cout << "1. Them sach moi\n";
cout << "2. Liet ke danh sach cac sach\n";
cout << "3. Dem so sach cua mot tac gia\n";
cout << "4. Tim sach theo NXB và nam\n";
cout << "0. Thoat\n";
cout << "Nhap lua chon cua ban: ";
cin >> choice;
cin.ignore();

switch (choice) {
case 1:
library.AddBook();
break;
case 2:
library.ListBooks();
break;
case 3: {
string author;
cout << "Nhap ten tac gia: ";
getline(cin, author);
int count = library.CountBooksByAuthor(author);
cout << "So sach cua tac gia " << author << ": " << count << "\n";
break;
}
case 4: {
string publisher;
int year;
cout << "Nhap NXB: ";
getline(cin, publisher);
cout << "Nhap nam xuat ban: ";
cin >> year;
library.FindBooksByPublisherYear(publisher, year);
break;
}
case 0:
cout << "Thoat chuong trinh\n";
break;
default:
cout << "Khong hop le\n";
}
} while (choice != 0);

return 0;
}

Phần II: Stack – Queue


//Stack.h
#ifndef STACK_H
#define STACK_H

#include "linkedlist.h"
#include <iostream>
class Stack {
private:
linkedlist* Linkedlist;
int nNum;

public:
Stack();
~Stack();
void push(int x);
int pop();
void printStack();
int isEmpty();
};

#endif

//Stack.cpp
#include "Stack.h"
using namespace std;

void Stack::push(int x) {
element* p = new element(x);
Linkedlist->InsertFirst(p);
nNum++;
}

int Stack::pop() {
if (Linkedlist->Gethead() == nullptr) {
cout << "STACK RONG, KHONG LAY DUOC PHAN TU" << endl;
return -1; // Nếu Stack rỗng, trả về -1
}
int p = Linkedlist->Gethead()->Getdata();
Linkedlist->DeleteFirst();
nNum--;
return p;
}

void Stack::printStack() {
if (Linkedlist->Gethead() == nullptr) {
cout << "STACK RONG" << endl;
return;
}
cout << "Cac phan tu trong Stack: ";
Linkedlist->Travel(); // Gọi phương thức travel() trong LinkedList để in các
phần tử
}

int Stack::isEmpty()
{
return this->Linkedlist->Gethead() == nullptr;
}

Stack::Stack() {
nNum = 0;
Linkedlist = new linkedlist();
}

Stack::~Stack() {
delete Linkedlist;
}

//Queue.h
#ifndef QUEUE_H
#define QUEUE_H

#include "linkedlist.h"
#include <iostream>

class Queue {
private:
linkedlist* Linkedlist;

public:
Queue();
~Queue();

void enQueue(int x);


int deQueue();
void printQueue();
};

#endif

//Queue.cpp
#include "Queue.h"
using namespace std;

void Queue::enQueue(int x) {
element* p = new element(x);
Linkedlist->InsertTail(p);
}

int Queue::deQueue() {
if (Linkedlist->Gethead() == nullptr) {
cout << "QUEUE RONG, KHONG LAY DUOC PHAN TU" << endl;
return -1; // Nếu Queue rỗng, trả về -1
}
int p = Linkedlist->Gethead()->Getdata();
Linkedlist->DeleteFirst();
return p;
}

void Queue::printQueue() {
if (Linkedlist->Gethead() == nullptr) {
cout << "QUEUE RONG" << endl;
return;
}
cout << "Cac phan tu trong Queue: ";
Linkedlist->Travel(); // Gọi phương thức travel() trong LinkedList để in các
phần tử
}

Queue::Queue() {
Linkedlist = new linkedlist();
}

Queue::~Queue() {
delete Linkedlist;
}

//main.cpp
#include <iostream>
#include "Stack.h"
#include "Queue.h"
using namespace std;

int main() {
// Test Stack
Stack stack;
int value;

cout << "Nhap 3 gia tri vao Stack:" << endl;


for (int i = 0; i < 3; i++) {
cout << "Nhap gia tri: ";
cin >> value;
stack.push(value);
}

cout << "Pop 4 gia tri tu Stack:" << endl;


for (int i = 0; i < 4; i++) {
int poppedValue = stack.pop();
if (poppedValue != -1) {
cout << "Gia tri lay ra: " << poppedValue << endl;
}
}

// Test Queue
Queue queue;

cout << "\nNhap 3 gia tri vao Queue:" << endl;


for (int i = 0; i < 3; i++) {
cout << "Nhap gia tri: ";
cin >> value;
queue.enQueue(value);
}
cout << "Dequeue 4 gia tri tu Queue:" << endl;
for (int i = 0; i < 4; i++) {
int dequeuedValue = queue.deQueue();
if (dequeuedValue != -1) {
cout << "Gia tri lay ra: " << dequeuedValue << endl;
}
}

return 0;
}

Nâng cao
//Stack.cpp
#include "Stack.h"
using namespace std;

void Stack::push(int x) {
element* p = new element(x);
Linkedlist->InsertTail(p);//1
nNum++;
}

int Stack::pop() {
if (Linkedlist->Gethead() == nullptr) {
cout << "STACK RONG, KHONG LAY DUOC PHAN TU" << endl;
return -1; // Nếu Stack rỗng, trả về -1
}
int p = Linkedlist->Gethead()->Getdata();
Linkedlist->DeleteTail();
nNum--;
return p;
}

void Stack::printStack() {
if (Linkedlist->Gethead() == nullptr) {
cout << "STACK RONG" << endl;
return;
}
cout << "Cac phan tu trong Stack: ";
Linkedlist->Travel(); // Gọi phương thức travel() trong LinkedList để in các
phần tử
}

int Stack::isEmpty()
{
return this->Linkedlist->Gethead() == nullptr;
}

Stack::Stack() {
nNum = 0;
Linkedlist = new linkedlist();
}

Stack::~Stack() {
delete Linkedlist;
}

//Queue.cpp
#include "Queue.h"
using namespace std;

void Queue::enQueue(int x) {
element* p = new element(x);
Linkedlist->InsertTail(p);
}

int Queue::deQueue() {
if (Linkedlist->Gethead() == nullptr) {
cout << "QUEUE RONG, KHONG LAY DUOC PHAN TU" << endl;
return -1; // Nếu Queue rỗng, trả về -1
}
int p = Linkedlist->Gethead()->Getdata();
Linkedlist->DeleteFirst();
return p;
}

void Queue::printQueue() {
if (Linkedlist->Gethead() == nullptr) {
cout << "QUEUE RONG" << endl;
return;
}
cout << "Cac phan tu trong Queue: ";
Linkedlist->Travel(); // Gọi phương thức travel() trong LinkedList để in các
phần tử
}

Queue::Queue() {
Linkedlist = new linkedlist();
}

Queue::~Queue() {
delete Linkedlist;
}

//main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;

void convertToBinary(int n) {
Stack stack;
while (n > 0) {
int remainder = n % 2;
stack.push(remainder); // Đay phan du vao Stack
n = n / 2; // Chia n cho 2
}

// In ket qua tu Stack


cout << "So trong he co so 2 la: ";
while (!stack.isEmpty()) {
cout << stack.pop();
}
cout << endl;
}

int main() {
int number;
cout << "Nhap mot so tu he co so 10: ";
cin >> number;

convertToBinary(number);

return 0;
}

2.
Stack:
- Thao tác push và pop lần lượt thực hiện chèn và xóa phần tử ở đầu danh sách
liên kết.
+ Ưu điểm:
 Các thao tác thêm (push) và xóa (pop) diễn ra nhanh chóng với độ phức
tạp O(1).
 Không cần di chuyển các phần tử khác trong danh sách.
+ Nhược điểm:
 Mất thêm không gian để quản lý con trỏ của từng nút (điểm đặc trưng của
danh sách liên kết).
- Sử dụng danh sách liên kết nhưng thao tác push thêm phần tử vào cuối danh
sách liên kết và thao tác pop lấy phần tử từ cuối danh sách liên kết.
+ Ưu điểm:
 Cách tiếp cận này mô phỏng đúng hơn cách hoạt động thực tế của stack
(phần tử thêm cuối là phần tử được xóa đầu tiên - LIFO).
+ Nhược điểm:
 Thao tác pop từ cuối danh sách liên kết có thể tốn thêm thời gian nếu
phải duyệt từ đầu danh sách để tìm phần tử cuối (độ phức tạp O(n) nếu
không có con trỏ tail).
 Đòi hỏi thêm thao tác để quản lý con trỏ cuối.

Queue:
- Thao tác enqueue thêm phần tử vào cuối danh sách và dequeue lấy phần tử
từ đầu danh sách.
+ Ưu điểm:
 Cách cài đặt này đảm bảo các thao tác enqueue và dequeue thực hiện
nhanh chóng, với độ phức tạp O(1) khi sử dụng con trỏ tail để quản lý
phần tử cuối danh sách.
 Phù hợp với cấu trúc dữ liệu queue (FIFO - phần tử thêm trước được xử
lý trước).
+ Nhược điểm:
 Phụ thuộc vào việc duy trì cả con trỏ đầu và con trỏ cuối để đảm bảo hiệu
năng.

- Sử dụng danh sách liên kết nhưng thao tác enqueue thêm phần tử vào đầu
danh sách liên kết và dequeue lấy phần tử từ cuối danh sách liên kết.
+ Ưu điểm:
 Dễ cài đặt vì chỉ cần thao tác trên danh sách liên kết một chiều mà không
cần quản lý thêm con trỏ tail.
+ Nhược điểm:
 Thao tác dequeue từ cuối danh sách liên kết có thể tốn thời gian hơn (độ
phức tạp O(n) nếu phải duyệt danh sách để tìm phần tử cuối).
 Không tuân thủ chặt chẽ với bản chất của queue vì việc lấy phần tử từ
cuối danh sách có thể tạo cảm giác ngược với FIFO (đặc biệt khi không
sử dụng thêm con trỏ tail).

Bài tập ứng dụng


#include <iostream>
#include <queue>
#include <vector>
using namespace std;

bool canReach(const vector<vector<int>>& matrix, int x1, int y1, int x2, int y2)
{
int rows = matrix.size();
int cols = matrix[0].size();
// Kiểm tra tính hợp lệ của ô bắt đầu và ô đích
if (x1 < 0 || x1 >= rows || y1 < 0 || y1 >= cols || x2 < 0 || x2 >= rows || y2 < 0 ||
y2 >= cols)
return false;
if (matrix[x1][y1] == 0 || matrix[x2][y2] == 0)
return false;

// Các hướng di chuyển (trái, phải, lên, xuống)


vector<pair<int, int>> directions = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };

// Queue cho BFS


queue<pair<int, int>> q;
vector<vector<bool>> visited(rows, vector<bool>(cols, false));

q.push({ x1, y1 });


visited[x1][y1] = true;

while (!q.empty()) {
auto [x, y] = q.front();
q.pop();

// Nếu đến được ô đích


if (x == x2 && y == y2)
return true;

// Duyệt các ô kề
for (auto [dx, dy] : directions) {
int nx = x + dx;
int ny = y + dy;

// Kiểm tra ô mới hợp lệ


if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && matrix[nx]
[ny] == 1 && !visited[nx][ny]) {
q.push({ nx, ny });
visited[nx][ny] = true;
}
}
}
// Không tìm thấy đường đi
return false;
}

int main() {
vector<vector<int>> matrix = {
{1, 0, 1, 1},
{1, 1, 0, 1},
{0, 1, 1, 1},
{1, 0, 0, 1}
};

int x1 = 0, y1 = 0; // Tọa độ bắt đầu


int x2 = 3, y2 = 3; // Tọa độ đích

if (canReach(matrix, x1, y1, x2, y2)) {


cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}

return 0;
}

You might also like