1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng Cấu trúc dữ liệu: Ngăn xếp - TS. Lê Minh Trung & Th.S Lương Trần Ngọc Khiết

44 11 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 44
Dung lượng 11,68 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Bài giảng Cấu trúc dữ liệu: Ngăn xếp cung cấp cho người học những kiến thức như: Sử dụng mảng; Sử dụng con trỏ; Ứng dụng của ngăn xếp. Mời các bạn cùng tham khảo!

Trang 1

TS Lê Minh Trung ThS Lương Trần Ngọc Khiết Khoa Công nghệ Thông tin- Đại học Sư phạm TP HCM

Trang 2

Ngăn Xếp (Stack)

 Sử dụng mảng

 Sử dụng con trỏ

 Ứng dụng của ngăn xếp

Trang 3

Mô tả stack

 Một stack là một cấu trúc

dữ liệu mà việc thêm vào và loại bỏ được thực hiện tại một đầu (gọi là đỉnh – top của stack).

 Là một cấu trúc vào sau ra

trước – LIFO (Last In

First Out)

Trang 4

Hoạt động của Stack

 Stack rỗng:

 Đẩy (push) Q vào:

 Đẩy A vào:

 Lấy (pop) ra một => được A:

 Lấy ra một => được Q và stack rỗng:

Q

QA

QA

Q

Trang 5

Hoạt động của Stack

Trang 6

Thiết kế của Stack

template < class NodeType > //NodeType là kiểu dữ liệu tùy ý

class Stack

{

public :

Stack( void ); //phương thức khởi tạo

Stack( const Stack < NodeType > &source); //phương thức khởi tạo

~Stack( void ); //phương thức hủy

bool IsEmpty() const ;

void Push( const NodeType &item); //thêm phần tử vào đỉnh stack

void Pop(); //gỡ phần tử ra khỏi đỉnh stack

void Clear(); //xóa dữ liệu của stack

void operator=( const Stack < NodeType > &source);

};

Trang 8

Cài đặt Stack sử dụng mảng

Trang 9

const int MAX=20; //stack có tối đa MAX phần

bool IsEmpty() const;//kiểm tra stack rỗng

bool IsFull() const; //kiểm tra stack đầy

void Push(const NodeType &item);

NodeType &Peek() const;

void Pop();

void Clear();

private:

NodeType data[MAX]; //mảng chứa dữ liệu

int top; //đỉnh của stack

};

Thiết kế Stack dùng mảng

Trang 10

Các phương thức

template<class NodeType>

Stack<NodeType>::Stack(void)

{

top =-1;

}

template<class NodeType>

void Stack<NodeType>::Clear()

{

top =-1;

}

template<class NodeType>

bool Stack<NodeType>::IsEmpty() const

{

return top==-1; //stack rỗng}

template<class NodeType>

bool Stack<NodeType>::IsFull() const

{

return top== MAX-1; //stack đầy}

Trang 11

Các phương thức

template < class NodeType >

void Stack < NodeType >::Push( const NodeType & item ) {

Trang 12

Các phương thức

template<class NodeType>

void Stack<NodeType>::Push(const NodeType &item){

template<class NodeType>

void Stack<NodeType>::Pop(){

Trang 14

}catch(exception &e){

cout<< e.what(); cout<<endl;

}

}

Trang 16

Cài đặt Stack sử dụng con trỏ

Trang 17

Thiết kế Node

Node

Cần:

Dữ liệu Con trỏ để trỏ đến node sau Constructor

Trang 18

Thiết kế Node

template < class NodeType >

struct Node

{

Node(); //phương thức khởi tạo

Node( NodeType item, Node < NodeType > *ptr= NULL ); //phương

thức khởi tạo };

Trang 19

Thiết kế Node

#include "Node.h"

template < class NodeType >

Node < NodeType >::Node(){}

template < class NodeType >

Node < NodeType >::Node( NodeType item , Node < NodeType >

* ptr = nullptr ) {

this ->item= item ;

this ->next = ptr ;

}

Trang 20

Ví dụ với Node liên kết

b

p1

c p2

Trang 21

Stack liên kết

Trang 22

Stack(void); //phương thức khởi tạo

Stack(const Stack < NodeType > &source); //phương thức khởi tạo

~Stack(void); //phương thức hủy

bool IsEmpty() const;

void Push(const NodeType &item); //thêm phần tử vào đỉnh stack

void Pop(); //gỡ phần tử ra khỏi đỉnh stack

NodeType &Peek() const; //xem phần tử trên đỉnh stack

void Clear(); //xóa dữ liệu của stack

void operator=(const Stack < NodeType > &source); //so sánh bằng

private:

Node < NodeType > *top;

Node < NodeType > *Copy(const Stack < NodeType > &source); //copy từ stack source tới

vùng dữ liệu mới và trả về con trỏ tới vùng này

};

Trang 23

Thêm vào một stack liên kết

Giải thuật

 1 Tạo ra một node mới với giá trị cần thêm vào

 2 Trỏ nó đến đỉnh hiện tại của stack

 3 Trỏ đỉnh của stack vào node mới

new_node new_top

top_node

Trang 24

Phương thức Push

template < class NodeType >

void Stack < NodeType >::Push( const NodeType & item )

Trang 25

Bỏ đỉnh của một stack liên kết

Giải thuật:

 1 Gán một con trỏ để giữ đỉnh của stack

 2 Trỏ đỉnh của stack vào node ngay sau đỉnh hiện tại

 3 Xóa node cũ đi

old_top

top_node

old top middle old last

Trang 26

Phương thức Pop

template < class NodeType >

void Stack < NodeType >::Pop(){

Node < NodeType > *oldTop = top; top = oldTop ->next;

delete oldTop;

}

Trang 27

Sự không an toàn con trỏ trong C++

 Kết thúc biến stack nhưng bộ nhớ còn lại:

 delete stack0;

 Gán hai stack: cả hai dùng chung một vùng dữ liệu

 stack2 = stack1;

Trang 28

Đảm bảo an toàn con trỏ trong C++

Destructor (phương thức hủy):

 Sẽ được gọi ngay trước khi đối tượng kết thúc thời gian sống

 Dùng xóa hết vùng dữ liệu

Copy constructor:

 Sẽ được gọi khi khởi tạo biến lúc khai báo, hoặc truyền dữ liệu bằng tham trị

 Sao chép nguồn thành một vùng dữ liệu mới

Assignment operator (toán tử gán):

 Sẽ được gọi khi gán đối tượng này vào đối tượng khác

 Xóa vùng dữ liệu của đích và đồng thời sao chép nguồn thành một vùng dữ liệu mới

Trang 29

Hủy vùng nhớ đã được cấp cho Stack

template < class NodeType >

void Stack < NodeType >:: Clear()

{

while (!IsEmpty())Pop();

}

template < class NodeType >

Stack < NodeType >::~Stack( void )

{

Clear();

}

Trang 31

Sao chép vùng dữ liệu

Giải thuật:

1 Tạo một đỉnh của danh sách mới với dữ liệu của đỉnh nguồn

2 Giữ một con trỏ đuôi chỉ vào cuối danh sách mới

2 Duyệt qua danh sách nguồn

2.1 Tạo một node mới với dữ liệu từ node nguồn hiện tại 2.2 Nối vào cuối danh sách mới

2.3 Con trỏ đuôi là node mới

Trang 32

Sao chép vùng dữ liệu

template<class NodeType>

Node<NodeType> *Stack<NodeType>::Copy(const Stack<NodeType> &source){

Node<NodeType> *sTop, *sCur, *newTop, *newCur;

sTop = sCur = source.top;

if(sTop==nullptr)return nullptr;

newTop = newCur = new Node<NodeType>(sTop->item);

while (sCur->next !=nullptr)

{

sCur = sCur ->next;

newCur->next = new Node<NodeType>(sCur->item);

newCur = newCur ->next;

}

return newTop;

}

Trang 33

Copy constructor và toán tử gán

template < class NodeType >

Stack < NodeType >::Stack( const Stack < NodeType > & source ) {

top = Copy( source );

}

template < class NodeType >

void Stack < NodeType >::operator=( const Stack < NodeType >

& source ) {

Clear(); //xóa dữ liệu cũ của stack

top = Copy( source ); //trỏ tới dữ liệu mới

}

Trang 34

Phương thức khác

template < class NodeType >

bool Stack < NodeType >::IsEmpty() const

{

return (top== nullptr );

}

template < class NodeType >

NodeType & Stack < NodeType >::Peek() const

{

return top ->item;

}

Trang 35

Stack<string> sString, sStr;

sString.Push("you !"); sString.Push("love"); sString.Push("I");sStr = sString;

Trang 36

} catch ( exception &e){

cout<< e.what()<< endl;

}

cin.get();

}

Trang 39

Ước lượng biểu thức

 Cho trước biểu thức: (2+4)*5 – (3-2)*4

Biểu thức trung tố (infix)

1 Có thể biểu diễn biểu thức ở dạng khác mà không

cần dấu ( ) hay không?

o 2 4 + 5 * 3 2 – 4 *

-o Biểu thức tiền tố (postfix)

2 Lượng giá biểu thức như thế nào?

o 2 4 + 5 * 3 2 – 4 *  6 5 * 3 2 – 4 *  30 3 2 – 4 *

- 30 1 4 * - - 30 4 - - 26

Trang 40

Lượng giá biểu thức postfix

 Đọc lần lượt các thành phần của biểu thức từ trái sang phải, với

mỗi thành phần được đọc thực hiện các bước sau:

Nếu thành phần được đọc là toán hạng od thì đẩy nó vào ngăn xếp, tức là S Push (od).

Nếu thành phần được đọc là phép toán op thì lấy ra các toán

hạng ở đỉnh ngăn xếp:

od 2 = S.PopAndPeek( )

od 1 = S.PopAndPeek( )

Thực hiện phép toán op với các toán hạng là od 1 và od 2, kết

quả được đẩy vào ngăn xếp:

r = od 1 op od 2

S Push(r)

Lặp lại hai bước trên cho tới khi thành phần cuối cùng của

biểu thức được đọc qua Khi đó ngăn xếp chứa kết quả của biểu thức.

Trang 41

1 3

2 8 5

4 54 5

3 5 12

17

Trang 42

Chuyển đổi infix thành postfix

Thứ tự ưu tiên của toán tử: (), * / , +

-1. Nếu thành phần được đọc là toán hạng thì viết nó vào biểu thức postfix.

2. Nếu thành phần được đọc là phép toán (phép toán hiện thời), thì thực hiện các

bước sau:

1. Nếu ngăn xếp không rỗng thì nếu phần tử ở đỉnh ngăn xếp là phép toán có

quyền ưu tiên cao hơn hay bằng phép toán hiện thời, thì phép toán đó

được kéo ra khỏi ngăn xếp và viết vào biểu thức postfix Lặp lại bước này

2. Nếu ngăn xếp rỗng hoặc phần tử ở đỉnh ngăn xếp là dấu mở ngoặc hoặc

phép toán ở đỉnh ngăn xếp có quyền ưu tiên thấp hơn phép toán hiện thời, thì phép toán hiện thời được đẩy vào ngăn xếp.

3. Nếu thành phần được đọc là dấu mở ngoặc thì nó được đẩy vào ngăn xếp.

4. Nếu thành phần được đọc là dấu đóng ngoặc thì thực hiện các bước sau:

1. (Bước lặp) Loại các phép toán ở đỉnh ngăn xếp và viết vào biểu thức postfixcho tới khi đỉnh ngăn xếp là dấu mở ngoặc

2. Loại dấu mở ngoặc khỏi ngăn xếp

5. Sau khi toàn bộ biểu thức infix được đọc, loại các phép toán ở đỉnh ngăn xếp vàviết vào biểu thức postfix cho tới khi ngăn xếp rỗng

Trang 43

Ví dụ

Input: a * ( b – c + d) + e / f

a b c – d + * e f / +

Trang 44

CÁM ƠN VÌ ĐÃ LẮNG NGHE!

Ngày đăng: 09/08/2021, 17:43

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm