Thực tập cơ sở

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 48

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN VÀ

TRUYỀN THÔNG
-----------------------

THỰC TẬP CƠ SỞ
ĐỀ TÀI:
TÌM HIỂU VÀ MÔ PHỎNG THUẬT TOÁN MÃ ĐI TUẦN SỬ DỤNG
NGÔN NGỮ LẬP TRÌNH JAVA

Sinh viên thực hiện: Vũ Ngọc Đức Anh


KTPM K18B

Giảng viên hướng dẫn: Võ Văn Trường


MỤC LỤC

LỜI NÓI ĐẦU.................................................................................................................................3


Chương 1: GIỚI THIỆU NGÔN NGỮ LẬP TRÌNH JAVA..........................................................4
1.1. Java.................................................................................................................4
1.1.1. Lịch sử.....................................................................................................5
1.1.2. Nguyên tắc...............................................................................................7
1.2. Phiên bản........................................................................................................7
1.3.Hệ thống thực thi.............................................................................................9
1.3.1. Java JVM và bytecode.............................................................................9
1.3.2. Không JVM...........................................................................................10
1.3.3. Quản lý bộ nhớ tự động.........................................................................10
1.4. Các lớp đặc biệt............................................................................................12
1.4.1. Applet....................................................................................................12
1.4.2. Servlet....................................................................................................13
1.5. Java swing....................................................................................................14
1.5.1. Ứng dụng của Java Swing.....................................................................14
1.5.2. Sự khác biệt giữa AWT và SWING......................................................15
1.5.3. Cấu trúc phân cấp lớp Java swing.........................................................16
1.5.4. Một số lớp cơ bản trong Java swing......................................................17
Chương 2: THUẬT TOÁN MÃ ĐI TUẦN...................................................................................32
2.1. GIỚI THIỆU ĐỀ TÀI...................................................................................32
2.2. NGHIÊN CỨU LÝ THUYẾT......................................................................33
2.3. MÔ TẢ BÀI TOÁN.....................................................................................34
2.4. GIẢI PHÁP – THUẬT TOÁN ĐÃ CÓ ( ĐỆ QUY QUAY LUI )...............36
2.5.GIẢI PHÁP – THUẬT TOÁN ĐỀ XUẤT (WARNSDORFF)......................37
Chương 3: LẬP TRÌNH VÀ THỬ NGHIỆM...............................................................................38
3.1. Chương trình.................................................................................................38
3.2. Kết quả thử nghiệm......................................................................................38
3.3. Code toàn bộ chương trình...........................................................................41
KẾT LUẬN...................................................................................................................................46
TÀI LIỆU THAM KHẢO.............................................................................................................47
LỜI NÓI ĐẦU

Ngày nay, Tin học ngày càng phát triển nhanh chóng và được ứng dụng
rộng rãi trong mọi lĩnh vực của đời sống xã hội, việc học và nắm bắt công
nghệ mới đặc biệt là công nghệ thông tin ngày càng trở nên bức thiết. Đối
với sinh viên trong ngành càng phải tích cực học tập, nắm vững mọi kiến
thức về công nghệ thông tin.

Sau một thời gian học tập và nghiên cứu về lập trình em đã được giao đề
tài: “Tìm hiểu và mô phỏng thuật toán Mã Đi Tuần” trông lần thực tập cơ
sở này.

Trong quá trình thực hiện đề tài, mặc dù đã ra sức nghiên cứu và cố gắng
nhưng chắc chắn khó tránh khỏi những thiếu sót, em rất mong nhận được
những sự chỉ dẫn, ý kiến đóng góp của quý thầy cô để em ngày càng hoàn
thiện hơn. Em xin gửi lời cảm ơn đến thầy Võ Văn Trường đã giúp đỡ em
trong quá trình thực hiện đề tài này.
Chương 1: GIỚI THIỆU NGÔN NGỮ LẬP TRÌNH JAVA

1.1. Java

Java (phiên âm Tiếng Việt: "Gia-va") là một ngôn ngữ lập trình hướng đối


tượng, dựa trên lớp được thiết kế để có càng ít phụ thuộc thực thi càng tốt. Nó là
ngôn ngữ lập trình có mục đích chung cho phép các nhà phát triển ứng dụng viết
một lần, chạy ở mọi nơi (WORA), nghĩa là mã Java đã biên dịch có thể chạy trên
tất cả các nền tảng hỗ trợ Java mà không cần biên dịch lại. Các ứng dụng Java
thường được biên dịch thành bytecode có thể chạy trên bất kỳ máy ảo Java (JVM)
nào bất kể kiến trúc máy tính bên dưới. Cú pháp của Java tương tự như C và C++,
nhưng có ít cơ sở cấp thấp hơn các ngôn ngữ trên. Java runtime cung cấp các khả
năng động (chẳng hạn như phản ánh và sửa đổi mã thời gian chạy) thường không
có sẵn trong các ngôn ngữ biên dịch truyền thống. Tính đến năm 2019 Java là một
trong những ngôn ngữ lập trình phổ biến nhất được sử dụng theo GitHub, đặc biệt
cho các ứng dụng web máy khách-máy chủ, với 9 triệu nhà phát triển đã được báo
cáo.

Java ban đầu được James Gosling tại Sun Microsystems (sau đó đã được Oracle


mua lại) phát triển và được phát hành vào năm 1995 như một thành phần cốt lõi
của nền tảng Java của Sun Microsystems. Các trình biên dịch Java, máy ảo và thư
viện lớp thực thi gốc và tham chiếu ban đầu được Sun phát hành theo giấy phép
độc quyền. Kể từ tháng 5 năm 2007, tuân theo các thông số kỹ thuật của Quy trình
Cộng đồng Java, Sun đã cấp phép hầu hết các công nghệ Java của mình theo Giấy
phép Công cộng GNU. Oracle cung cấp Máy ảo Java HotSpot của riêng mình, tuy
nhiên việc triển khai tham chiếu chính thức là OpenJDK JVM, là phần mềm mã
nguồn mở miễn phí và được hầu hết các nhà phát triển sử dụng và là JVM mặc
định cho hầu hết các bản phân phối Linux.

Tính đến tháng 9 năm 2020, phiên bản mới nhất là Java 15, với Java 11, một phiên
bản hỗ trợ dài hạn (LTS), được phát hành vào 25 tháng 9 năm 2018. Oracle phát
hành bản cập nhật miễn phí cho công chúng với phiên bản kế thừa Java 8 LTS vào
tháng 1 năm 2019 cho mục đích sử dụng thương mại, mặc dù nếu không nó sẽ vẫn
hỗ trợ Java 8 với các bản cập nhật công khai cho mục đích sử dụng cá nhân vô thời
hạn. Các nhà cung cấp khác đã bắt đầu cung cấp các bản miễn phí của OpenJDK 8
và 11 mà vẫn đang nhận được bảo mật và các nâng cấp khác.

Oracle (và những công ty khác) khuyên người dùng nên gỡ cài đặt các phiên bản
Java đã lỗi thời vì những rủi ro nghiêm trọng do các vấn đề bảo mật chưa được giải
quyết. Vì Java 9, 10, 12, 13 và 14 không còn được hỗ trợ, Oracle khuyên người
dùng nên chuyển ngay sang phiên bản mới nhất (hiện tại là Java 15) hoặc bản phát
hành LTS.

1.1.1. Lịch sử

James Gosling, Mike Sheridan và Patrick Naughton khởi xướng dự án ngôn ngữ


Java vào tháng 6 năm 1991. Java ban đầu được thiết kế cho truyền hình tương tác,
nhưng nó quá tiên tiến đối với ngành truyền hình cáp kỹ thuật số vào thời điểm
đó. Ban đầu ngôn ngữ này được gọi là Oak theo tên một cây sồi bên ngoài văn
phòng của Gosling. Sau đó, dự án có tên là Green và cuối cùng được đổi tên
thành Java, từ cà phê Java, loại cà phê đến từ Indonesia. Gosling đã thiết kế Java
với cú pháp kiểu C/C++ mà các lập trình viên hệ thống và ứng dụng đã quen thuộc.

Sun Microsystems đã phát hành bản triển khai công khai đầu tiên dưới dạng Java
1.0 vào năm 1996. Nó hứa hẹn khả năng Viết một lần, Chạy mọi nơi (WORA),
cung cấp thời gian chạy miễn phí trên các nền tảng phổ biến. Khá an toàn và có
tính năng bảo mật có thể định cấu hình, nó cho phép các hạn chế truy cập mạng và
tệp. Các trình duyệt web lớn đã sớm kết hợp khả năng chạy các ứng dụng
Java trong các trang web và Java nhanh chóng trở nên phổ biến. Trình biên dịch
Java 1.0 được viết lại bằng Java bởi Arthur van Hoff để tuân thủ nghiêm ngặt đặc
tả ngôn ngữ Java 1.0. Với sự ra đời của Java 2 (ban đầu được phát hành với tên gọi
J2SE 1.2 vào tháng 12 năm 1998 – 1999), các phiên bản mới có nhiều cấu hình
được xây dựng cho các loại nền tảng khác nhau. J2EE bao gồm các công nghệ và
API cho các ứng dụng doanh nghiệp thường chạy trong môi trường máy chủ, trong
khi các API đặc trưng của J2ME được tối ưu hóa cho các ứng dụng di động. Phiên
bản dành cho máy tính để bàn được đổi tên thành J2SE. Năm 2006, vì mục đích
tiếp thị, Sun đã đổi tên các phiên bản J2 mới lần lượt là Java EE, Java ME và Java
SE.

Năm 1997, Sun Microsystems đã tiếp cận cơ quan tiêu chuẩn ISO/IEC JTC 1 và
sau đó là Ecma International để chính thức hóa Java, nhưng sau đó công ty nhanh
chóng rút khỏi quy trình này. Java vẫn là một tiêu chuẩn thực tế, được kiểm soát
thông qua Quy trình cộng đồng Java. Đã có lúc, Sun cung cấp hầu hết các triển
khai Java của mình mà không tính phí, bất chấp trạng thái phần mềm độc
quyền của họ. Sun đã tạo ra doanh thu từ Java thông qua việc bán giấy phép cho
các sản phẩm chuyên biệt như Hệ thống Doanh nghiệp Java.

Vào ngày 13 tháng 11 năm 2006, Sun đã phát hành phần lớn máy ảo Java (JVM)
của mình dưới dạng phần mềm mã nguồn mở và miễn phí (FOSS), theo các điều
khoản của Giấy phép Công cộng GNU (GPL). Vào ngày 8 tháng 5 năm 2007, Sun
đã hoàn thành quá trình, cung cấp tất cả mã cốt lõi của JVM theo các điều khoản
phân phối phần mềm miễn phí / nguồn mở, ngoại trừ một phần nhỏ mã mà Sun
không giữ bản quyền.

Phó chủ tịch Rich Green của Sun nói rằng vai trò lý tưởng của Sun đối với Java là
như một nhà truyền giáo. Sau khi Tập đoàn Oracle mua lại Sun Microsystems vào
năm 2009–10, Oracle đã tự mô tả mình là người quản lý công nghệ Java với cam
kết không ngừng thúc đẩy cộng đồng tham gia và minh bạch. Điều này không ngăn
được Oracle đệ đơn kiện Google ngay sau đó vì đã sử dụng Java bên trong Android
SDK.

Ngày 2 tháng 4 năm 2010, James Gosling từ chức tại Oracle.


Vào tháng 1 năm 2016, Oracle đã thông báo rằng môi trường thời gian chạy Java
dựa trên JDK 9 sẽ ngừng cung cấp plugin trình duyệt.

Phần mềm Java chạy trên mọi thứ, từ máy tính xách tay đến trung tâm dữ
liệu, bảng điều khiển trò chơi đến siêu máy tính khoa học.

1.1.2. Nguyên tắc

Có 5 mục tiêu chính trong việc xây dựng ngôn ngữ Java:

 Nó phải đơn giản, hướng đối tượng và quen thuộc.


 Nó phải mạnh mẽ và an toàn.
 Nó phải là kiến trúc trung lập và di động.
 Nó phải thực thi với hiệu suất cao.
 Nó phải được thông dịch, phân luồng và động.

1.2. Phiên bản

Các phiên bản Java đã phát hành:

Version Date

JDK Beta 1995

JDK1.0 ngày 23 tháng 1 năm 1996 

JDK 1.1 ngày 19 tháng 2 năm 1997

J2SE 1.2 ngày 8 tháng 12 năm 1998

J2SE 1.3 ngày 8 tháng 5 năm 2000

J2SE 1.4 ngày 6 tháng 2 năm 2002

J2SE 5.0 ngày 30 tháng 9 năm 2004


Java SE 6 ngày 11 tháng 12 năm 2006

Java SE 7 ngày 28 tháng 7 năm 2011

Java SE 8 ngày 18 tháng 3 năm 2014

Java SE 9 ngày 21 tháng 9 năm 2017

Java SE 10 ngày 20 tháng 3 năm 2018

Java SE 11 ngày 25 tháng 9 năm 2018 

Java SE 12 ngày 19 tháng 3 năm 2019

Java SE 13 ngày 17 tháng 9 năm 2019

Java SE 14 ngày 17 tháng 3 năm 2020

Java SE 15 ngày 15 tháng 9 năm 2020

Java SE 16 ngày 16 tháng 3 năm 2021

Java SE 17 ngày 14 tháng 9 năm 2021

Sun đã xác định và hỗ trợ bốn phiên bản Java nhắm mục tiêu các môi trường ứng
dụng khác nhau và phân đoạn nhiều API của nó để chúng thuộc về một trong các
nền tảng. Các nền tảng là:

 Java Card cho thẻ thông minh.


 Nền tảng Java, Phiên bản Micro (Java ME) - nhắm mục tiêu môi
trường với tài nguyên hạn chế.
 Nền tảng Java, Phiên bản Tiêu chuẩn (Java SE) - nhắm mục tiêu môi
trường máy trạm.
 Nền tảng Java, Phiên bản Doanh nghiệp (Java EE) - nhắm mục tiêu
các môi trường doanh nghiệp hoặc Internet phân tán lớn.

Các lớp trong Java API được tổ chức thành các nhóm riêng biệt gọi là gói. Mỗi gói
chứa một tập hợp các giao diện, lớp, gói con và ngoại lệ liên quan.

Sun cũng cung cấp một phiên bản có tên là Personal Java đã được thay thế bằng
các cặp cấu hình Java ME dựa trên tiêu chuẩn sau này.

1.3.Hệ thống thực thi

1.3.1. Java JVM và bytecode

Một mục tiêu thiết kế của Java là tính di động, có nghĩa là các chương trình được
viết cho nền tảng Java phải chạy tương tự nhau trên bất kỳ sự kết hợp nào giữa
phần cứng và hệ điều hành với hỗ trợ thời gian chạy thích hợp. Điều này đạt được
bằng cách biên dịch mã ngôn ngữ Java sang một đại diện trung gian được gọi
là Java bytecode, thay vì trực tiếp tới mã máy cụ thể về kiến trúc. Các lệnh mã
bytecode trong Java tương tự như mã máy, nhưng chúng được thiết kế để thực thi
bởi một máy ảo (VM) được viết riêng cho phần cứng máy chủ. Người dùng
cuối thường sử dụng Java Runtime Environment (JRE) được cài đặt trên máy của
họ cho các ứng dụng Java độc lập hoặc trong trình duyệt web cho các ứng dụng
Java.

Các thư viện tiêu chuẩn cung cấp một cách chung để truy cập các tính năng dành
riêng cho máy chủ như đồ họa, phân luồng và mạng.

Việc sử dụng bytecode phổ biến làm cho việc chuyển cổng trở nên đơn giản. Tuy
nhiên, chi phí của việc thông dịch bytecode thành các lệnh máy làm cho các
chương trình được thông dịch hầu như luôn chạy chậm hơn các chương trình thực
thi gốc. Các trình biên dịch Just-in-time (JIT) biên dịch mã byte thành mã máy
trong thời gian chạy đã được giới thiệu từ giai đoạn đầu. Bản thân Java độc lập với
nền tảng và được điều chỉnh cho phù hợp với nền tảng cụ thể mà máy ảo
Java (JVM) chạy trên nó, máy này sẽ dịch mã bytecode của Java sang ngôn ngữ
máy của nền tảng.

1.3.1.1. Hiệu suất

Các chương trình được viết bằng Java nổi tiếng là chậm hơn và đòi hỏi nhiều bộ
nhớ hơn các chương trình được viết bằng C++. Tuy nhiên, tốc độ thực thi của các
chương trình Java được cải thiện đáng kể với sự ra đời của tính năng biên dịch
đúng lúc vào năm 1997/1998 cho Java 1.1, việc bổ sung các tính năng ngôn ngữ hỗ
trợ phân tích mã tốt hơn (chẳng hạn như các lớp bên trong, lớp StringBuilder, các
xác nhận tùy chọn, v.v.) và tối ưu hóa trong máy ảo Java, chẳng hạn
như HotSpot trở thành mặc định cho JVM của Sun vào năm 2000. Với Java 1.5,
hiệu suất đã được cải thiện với việc bổ sung gói java.util.concurrent, bao gồm khóa
các triển khai miễn phí của ConcurrentMaps và các bộ sưu tập đa lõi khác và nó đã
được cải thiện hơn nữa với Java 1.6.

1.3.2. Không JVM

Một số nền tảng cung cấp hỗ trợ phần cứng trực tiếp cho Java; có những bộ điều
khiển vi mô có thể chạy Java bytecode trong phần cứng thay vì máy ảo Java phần
mềm, và một số bộ xử lý dựa trên ARM có thể có hỗ trợ phần cứng để thực thi
Java bytecode thông qua tùy chọn Jazelle của chúng, mặc dù hỗ trợ hầu hết đã bị
loại bỏ trong các triển khai hiện tại của ARM.

1.3.3. Quản lý bộ nhớ tự động

Java sử dụng bộ thu gom rác tự động (AGC) để quản lý bộ nhớ trong vòng đời đối
tượng. Lập trình viên xác định thời điểm các đối tượng được tạo và thời gian chạy
Java chịu trách nhiệm khôi phục bộ nhớ khi các đối tượng không còn được sử
dụng. Khi không còn tham chiếu đến một đối tượng, bộ nhớ không thể truy cập sẽ
đủ điều kiện để được giải phóng tự động bởi bộ thu gom rác. Một cái gì đó tương
tự như rò rỉ bộ nhớ vẫn có thể xảy ra nếu mã của lập trình viên giữ một tham chiếu
đến một đối tượng không còn cần thiết, thường là khi các đối tượng không còn cần
thiết được lưu trữ trong các bộ chứa vẫn đang được sử dụng. Nếu các phương thức
cho một đối tượng không tồn tại được gọi, một ngoại lệ con trỏ null sẽ được đưa ra.

Một trong những ý tưởng đằng sau mô hình quản lý bộ nhớ tự động của Java là các
lập trình viên có thể không phải chịu gánh nặng khi phải thực hiện quản lý bộ nhớ
thủ công. Trong một số ngôn ngữ, bộ nhớ để tạo các đối tượng được cấp phát ngầm
trên ngăn xếp hoặc được cấp phát và phân bổ rõ ràng từ heap. Trong trường hợp
thứ hai, trách nhiệm quản lý bộ nhớ thuộc về lập trình viên. Nếu chương trình
không phân bổ một đối tượng, một rò rỉ bộ nhớ sẽ xảy ra. Nếu chương trình cố
gắng truy cập hoặc phân bổ bộ nhớ đã được phân bổ, kết quả là không xác định và
khó dự đoán, và chương trình có thể trở nên không ổn định hoặc gặp sự cố. Điều
này có thể được khắc phục một phần bằng cách sử dụng các con trỏ thông minh,
nhưng chúng làm tăng thêm chi phí và sự phức tạp. Lưu ý rằng việc thu gom rác
không ngăn chặn rò rỉ bộ nhớ logic, tức là những nơi bộ nhớ vẫn được tham chiếu
nhưng không bao giờ được sử dụng.

Việc thu gom rác có thể xảy ra bất cứ lúc nào. Lý tưởng nhất, nó sẽ xảy ra khi một
chương trình không hoạt động. Nó được đảm bảo sẽ được kích hoạt nếu không có
đủ bộ nhớ trống trên heap để cấp phát một đối tượng mới; điều này có thể khiến
một chương trình bị dừng trong giây lát. Không thể quản lý bộ nhớ rõ ràng trong
Java.

Java không hỗ trợ số học con trỏ kiểu C/C++, trong đó địa chỉ đối tượng có thể
được thao tác số học (ví dụ: bằng cách thêm hoặc trừ một phần bù). Điều này cho
phép bộ thu gom rác di chuyển các đối tượng được tham chiếu và đảm bảo an toàn
và bảo mật kiểu.

Giống như trong C++ và một số ngôn ngữ hướng đối tượng khác, các biến của kiểu
dữ liệu nguyên thủy của Java hoặc được lưu trữ trực tiếp trong các trường (đối với
các đối tượng) hoặc trên ngăn xếp (đối với các phương thức) chứ không phải trên
heap, điều này thường đúng đối với dữ liệu không nguyên thủy các loại (nhưng hãy
xem phân tích thoát). Đây là một quyết định có ý thức của các nhà thiết kế của
Java vì lý do hiệu suất.

Java chứa nhiều loại trình thu gom rác. Theo mặc định, HotSpot sử dụng bộ thu
gom rác quét song song. Tuy nhiên, cũng có một số trình thu gom rác khác có thể
được sử dụng để quản lý đống rác. Đối với 90% ứng dụng trong Java, bộ thu gom
rác đồng thời Mark-Sweep (CMS) là đủ. Oracle đặt mục tiêu thay thế CMS bằng
Garbage-First Collector (G1).

Giải quyết được vấn đề quản lý bộ nhớ không giúp lập trình viên bớt gánh nặng xử
lý đúng cách các loại tài nguyên khác, như kết nối mạng hoặc cơ sở dữ liệu, xử lý
tệp, v.v., đặc biệt là khi có lỗi.

1.4. Các lớp đặc biệt

1.4.1. Applet

Java applet là các chương trình được nhúng vào trong các ứng dụng khác, thường
là trong một trang web hiển thị trong trình duyệt web. API của Java applet hiện
không còn được dùng nữa kể từ ngày 9 tháng 1 năm 2017.

Một Java applet là một ứng dụng nhỏ được viết bằng ngôn ngữ lập
trình Java hoặc một ngôn ngữ lập trình khác biên dịch sang Java bytecode và được
gửi đến người dùng dưới dạng Java bytecode. Người dùng chạy Java applet từ
một trang web và applet sau đó được thực thi trong một máy ảo Java (JVM) trong
một quy trình tách biệt với chính trình duyệt web. Một Java applet có thể xuất hiện
trong một khung của trang web, một cửa sổ ứng dụng mới, Sun 's appletviewer,
hoặc một công cụ độc lập cho applet thử nghiệm.

1.4.2. Servlet

Công nghệ Java servlet cung cấp cho các nhà phát triển Web một cơ chế nhất quán,
đơn giản để mở rộng chức năng của máy chủ Web và để truy cập các hệ thống kinh
doanh hiện có. Servlet là các thành phần Java EE phía máy chủ tạo ra các phản hồi
(thường là các trang HTML) cho các yêu cầu (thường là các yêu cầu HTTP)
từ máy khách.

Ở một mức độ nào đó, API của Java servlet đã được thay thế bởi hai công nghệ
Java cho dịch vụ web:

 Java API cho RESTful Web Services (JAX-RS 2.0) hữu ích cho
AJAX, JSON và dịch vụ REST, và

 Java API cho XML Web Services (JAX-WS) hữu ích cho dịch vụ


web SOAP.

Java Servlet API cho phép nhà phát triển phần mềm thêm những nội dung động
vào Web server sử dụng nền tảng Java. Nó phát sinh nội dung thông thường
là HTML, đôi khi cũng có thể là các ngôn ngữ khác như XML. Servlets là bản sao
Java của các kỹ thuật trình bày nội dung Web động khác như
là PHP, CGI và ASP.NET. Servlets có thể duy trì tình trạng thông qua các giao
dịch của máy chủ bằng việc sử dụng HTTP cookies, các giá trị session hoặc URL
rewriting.

Servlet API, được chứa trong gói Java kế thừa từ Bản mẫu:Javadoc:EE, định nghĩa
những tương tác cần thiết giữa một Web container và một servlet. A Web
container là một thành phần cơ bản và cần thiết của Web Server để tương tác với
các Servlet. The Web container chịu trách nhiệm quản lý vòng đời của các Servlet,
ánh xạ đường dẫn đến một Servlet cụ thể và đảm bảo rằng có thể truy cập vào.

1.5. Java swing

Java Swing là cách gọi rút gọn khi người ta nhắc đến Swing của Java
Foundation (JFC). Nó là bộ công cụ GUI mà Sun Microsystems phát triển để xây
dựng các ứng dụng tối ưu dùng cho window (bao gồm các thành phần như nút,
thanh cuộn,…).

Swing được xây dựng trên AWT API và hoàn toàn được viết bằng Java. Tuy
nhiên, nó lại khác với AWT ở chỗ bộ công cụ này thuộc loại nền tảng độc lập, bao
gồm các thành phần nhẹ và phức tạp hơn AWT.

Các gói javax.swing bao gồm các lớp cho Java Swing API như JMenu, JButton,
JTextField, JRadioButton, JColorChooser,…

Việc xây dựng ứng dụng sẽ trở nên dễ dàng hơn với Java Swing vì chúng ta có các
bộ công cụ GUI giúp đỡ công việc.

Swing được chính thức phát hành vào tháng 3/1998. Nó đi kèm với thư viện Swing
1.0 với hơn 250 lớp, 80 giao tiếp.

Hiện nay con số này đã được tăng lên, ở phiên bản Swing 1.4 có 451 lớp và 85
giao tiếp.

Các bản phát hành Java 2 (SDK 1.2 và các phiên bản mới hơn) đều bao gồm Swing
trong runtime environment.

1.5.1. Ứng dụng của Java Swing

Java Swing được dùng để hỗ trợ tạo giao diện đồ hoạ người dùng (với Java).

Bộ công cụ này cung cấp các bộ điều khiển nâng cao như thanh trượt, colorpicker,
Tree, TabbedPane và bảng điều khiển,..

Swing có những đặc điểm:


 Độc lập với thiết bị

 Có thể tuỳ chỉnh, mở rộng

 Khá nhẹ

 Có thể cấu hình

Ngoài ra bạn cũng có thể tùy chỉnh các điều khiển xoay một cách dễ dàng mà
không ảnh hưởng đến các thành phần khác.

1.5.2. Sự khác biệt giữa AWT và SWING

No. Java AWT Java Swing

Phụ thuộc
nền tảng
(Platform Độc lập với nền tảng (Platform
1) Dependent) Independent)

Thành phần
của AWT
2) nặng Thành phần của Swing khá nhẹ

AWT không
hỗ
trợ pluggable
3) look and feel. Swing hỗ trợ pluggable look and feel.

4) AWT có ít Swing cung cấp nhiều thành phần và các


thành phần thành phần cũng mạnh mẽ hơn AWT
như: bảng, danh sách, cuộn màn hình,
hơn Swing trình chọn màu,..

AWT không
tuân theo cấu
trúc MVC
(Model View
5) Controller) Swing theo cấu trúc MVC

1.5.3. Cấu trúc phân cấp lớp Java swing

Phân cấp của API Java swing như liệt kê ở hình dưới đây:
Chú thích: Tất cả các thành phần trong swing được kế thừa từ lớp Jcomponent như
JButton, JComboBox, JList, JLabel đều có thể được thêm vào lớp Container.

Container là các window như Frame và Dialog. Các container này chỉ có thể thêm
một thành phần vào chính nó.

1.5.4. Một số lớp cơ bản trong Java swing

JButton Class – Lớp JButton


Nó được dùng để tạo ra một nút (button) có tên.

Việc sử dụng ActionListener sẽ dẫn đến một số hành động khi nút được nhấn.

Nó kế thừa lớp AbstractButton và độc lập với nền tảng.

Ví dụ:
1 import javax.swing.*;

2 public class example{

3 public static void main(String args[]) {

4 JFrame a = new JFrame(“example”);

5 JButton b = new JButton(“click me”);

6 b.setBounds(40,90,85,20);

7 a.add(b);

8 a.setSize(300,300);

9 a.setLayout(null);

10 a.setVisible(true);

11 }

12 }

Output:

Một nút button có tên


JTextField Class – Lớp JTextField
Nó kế thừa lớp JTextComponent và dùng để cho phép chỉnh sửa dòng đơn

Ví dụ:

1 import javax.swing.*;

2 public class example{

3 public static void main(String args[]) {

4 JFrame a = new JFrame(“example”);

5 JTextField b = new JTextField(“edureka”);

6 b.setBounds(50,100,200,30);

7 a.add(b);

8 a.setSize(300,300);

9 a.setLayout(null);

10 a.setVisible(true);

11 }

12 }

Output:
JTextField Class

JScrollBar Class – lớp JScrollBar


Dùng để thêm thanh cuộn (cả ngang và dọc)

Ví dụ:
1 import javax.swing.*;

2 class example{

3 example(){

4 JFrame a = new JFrame(“example”);

5 JScrollBar b = new JScrollBar();

6 b.setBounds(90,90,40,90);

7 a.add(b);

8 a.setSize(300,300);

9 a.setLayout(null);

10 a.setVisible(true);

11 }

12 public static void main(String args[]){

13 new example();

14 }

15 }

Output:
JScrollBar Class

JPanel Class – Lớp JPanel


Kế thừa lớp JComponent, cung cấp không gian cho một ứng dụng (có thể đính kèm
bất kỳ thành phần nào khác).
1 import java.awt.*;

2 import javax.swing.*;

3 public class Example{

4 Example(){

5 JFrame a = new JFrame(“example”);

6 JPanel p = new JPanel();

7 p.setBounds(40,70,200,200);

8 JButton b = new JButton(“click me”);

9 b.setBounds(60,50,80,40);

10 p.add(b);

11 a.add(p);

12 a.setSize(400,400);

13 a.setLayout(null);

14 a.setVisible(true);

15 }

16 public static void main(String args[])

17 {

18 new Example();

19 }

20 }

Output:
Panel Class

JMenu Class – Lớp JMenu


Kế thừa lớp JMenuItem, là một thành phần menu kéo xuống (hiển thị từ thanh menu).

1 import javax.swing.*;

2 class Example{

3 JMenu menu;

4 JMenuItem a1,a2;

5 Example()

6 {

7 JFrame a = new JFrame(“Example”);

8 menu = new JMenu(“options”);

9 JMenuBar m1 = new JMenuBar();

10 a1 = new JMenuItem(“example”);

11 a2 = new JMenuItem(“example1”);
12 menu.add(a1);

13 menu.add(a2);

14 m1.add(menu);

15 a.setJMenuBar(m1);

16 a.setSize(400,400);

17 a.setLayout(null);

18 a.setVisible(true);

19 }

20 public static void main(String args[])

21 {

22 new Example();

23 }

24 }

Output:
Lớp JMenu

JList Class – Lớp JList


Kế thừa lớp JComponent, đối tượng của lớp Jlist đại diện cho danh sách các mục văn
bản.

Next

1 import javax.swing.*;

2 public class Example

3 {

4 Example(){

5 JFrame a = new JFrame(“example”);

6 DefaultListModel<String> l = new DefaultListModel< >();

7 l.addElement(“first item”);

8 l.addElement(“second item”);

9 JList<String> b = new JList< >(l);

10 b.setBounds(100,100,75,75);

11 a.add(b);

12 a.setSize(400,400);

13 a.setVisible(true);

14 a.setLayout(null);

15 }

16 public static void main(String args[])

17 {
18 new Example();

19 }

20 }

Output:

Lớp JList

JLabel Class – Lớp JLabel


Được dùng để đặt văn bản trong vùng chứa, lớp JLabel cũng kế thừa lớp JComponent.

1 import javax.swing.*;

2 public class Example{

3 public static void main(String args[])

4 {

5 JFrame a = new JFrame(“example”);

6 JLabel b1;
7 b1 = new JLabel(“edureka”);

8 b1.setBounds(40,40,90,20);

9 a.add(b1);

10 a.setSize(400,400);

11 a.setLayout(null);

12 a.setVisible(true);

13 }

14 }

Output:

Lớp JLabel

JComboBox Class- Lớp JComboBox


Kế thừa lớp JComponent, dùng để hiển thị menu lựa chọn bật lên.

1 import javax.swing.*;
2 public class Example{

3 JFrame a;

4 Example(){

5 a = new JFrame(“example”);

6 string courses[] = { “core java”,”advance java”, “java servlet”};

7 JComboBox c = new JComboBox(courses);

8 c.setBounds(40,40,90,20);

9 a.add(c);

10 a.setSize(400,400);

11 a.setLayout(null);

12 a.setVisible(true);

13 }

14 public static void main(String args[])

15 {

16 new Example();

17 }

18 }

Output:
Lớp JComboBox

Layout Manager – Trình quản lý bố cục


Để sắp xếp các thành phần bên trong vùng chứa, chúng ta sử dụng Layout Manager.

Có một số bố cục như sau:


1. Border layout – Bố cục đường viền

2. Flow layout – Bố cục luồng

3. GridBag layout – Bố cục dạng khung

Border Layout

Trình quản lý bố cục mặc định tất cả JFrame là Border Layout.

Nó đặt các thành phần ở tối đa 5 vị trí: trên, dưới, trái, phải và trung tâm.
Trình quản lý bố cục mặc định

Flow Layout

Bố cục này đặt các thành phần lần lượt vào một hàng.

Bố cục mặc định JPanel.

Đây là bố cục mặc định cho mọi JPanel.

GridBag Layout
GridBag Layout đặt các thành phần trong một lưới, nó cho phép các thành phần này
trải dài hơn 1 ô.

GridBag Layout

Ví dụ: Dưới đây là một khung chat ở dạng Flow Layout

1 import javax.swing.*;

2 import java.awt.*;

3 class Example {

4 public static void main(String args[]) {

5 JFrame frame = new JFrame(“Chat Frame”);

6 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

7 frame.setSize(400, 400);

8 JMenuBar ob = new JMenuBar();

9 JMenu ob1 = new JMenu(“FILE”);

10 JMenu ob2 = new JMenu(“Help”);

11 ob.add(ob1);

12 ob.add(ob2);

13 JMenuItem m11 = new JMenuItem(“Open”);


14 JMenuItem m22 = new JMenuItem(“Save as”);

15 ob1.add(m11);

16 ob1.add(m22);

17 JPanel panel = new JPanel(); // the panel is not visible in output

18 JLabel label = new JLabel(“Enter Text”);

19 JTextField tf = new JTextField(10); // accepts upto 10 characters

20 JButton send = new JButton(“Send”);

21 JButton reset = new JButton(“Reset”);

22 panel.add(label); // Components Added using Flow Layout

23 panel.add(label); // Components Added using Flow Layout

24 panel.add(tf);

25 panel.add(send);

26 panel.add(reset);

27 JTextArea ta = new JTextArea();

28 frame.getContentPane().add(BorderLayout.SOUTH, panel);

29 frame.getContentPane().add(BorderLayout.NORTH, tf);

30 frame.getContentPane().add(BorderLayout.CENTER, ta);

31 frame.setVisible(true);

32 }

33 }

Output:
Khung chat ở dạng Flow Layout

Chương 2: THUẬT TOÁN MÃ ĐI TUẦN

2.1. GIỚI THIỆU ĐỀ TÀI

“Mã đi tuần” (Knight’s Tour) là một bài toán liên


quan đến một quân mã trên một bàn cờ vua. Quân
mã được đặt tại một vị trí trống bất kỳ trên bàn cờ và
duy chuyển theo luật của cờ vua. Nó nhảy qua mỗi ô
trên bàn cờ chính xác một lần. Hành trình của quân
mã được gọi là “Hành trình đóng” (Closed Tour)
nếu vị trí kết thúc của quân mã tấn công được vị trí
xuất phát của nó (để quân mã có thể đi tuần tiếp một
vòng nữa ngay lập tức). Nếu không thì được gọi là
hành trình mở.

Lập trình để giải quyết bài toán là một vấn đề phổ biến của các sinh viên thuộc các
ngành Khoa học Máy tính. Những biến thể của bài toán “Mã đi tuần” bao gồm
việc giải quyết bài toán trên các kiểu bàn cờ khác kiểu 8*8 (n*n, hình chữ nhật,…).
Ở phạm vi đồ án này, em chỉ phát triển hành trình đóng của quân mã.

2.2. NGHIÊN CỨU LÝ THUYẾT

Bài toán “Mã đi tuần” là một trong nhiều ví dụ tổng


quát của đường đi Hamilton trong lý thuyết đồ thị.
Việc tìm hành trình đóng của con mã tương tự như
việc tìm hành trình đóng của chu trình Hamilton.

Các tài liệu tham khảo sớm nhất để giải quyết bài
toán xuất hiện từ thế kỷ thứ IX. Nhưng giải thuật
đầu tiên đầy đủ cho bài toán về hành trình của quân mã là “Giải thuật
Warnsdorff” (Warnsdorff’s algorithm), công bố lần đầu năm 1823 bởi H. C.
Warnsdorff. Thuật toán Warnsdorff được biết đến như là phương pháp Heuristic
của “Mã đi tuần”.

Trên bàn cờ cỡ 8 * 8 có đúng 26,534,728,821,064 lời giải. Và số cách giải là 9.862


đối với bàn cờ cỡ 6 * 6. Không có lời giải hành trình đóng cho các bàn cờ có cỡ
nhỏ hơn.

2.3. MÔ TẢ BÀI TOÁN

 Xác định thông tin vào (Input) :


 Một bảng vuông (bàn cờ) kích thước
n*n.
 Tọa độ xuất phát của quân mã N(x,y).
 Xác định thông tin ra (Output) :
 Một bảng vuông (bàn cờ) có đánh dấu vị trí theo thứ tự từ 1 (vị trí
xuất phát) đến n*n (vị trí kết thúc) của quân mã.
 Từ vị trí thứ k sang vị trí thứ k+1 phải theo đúng luật di chuyển quân
mã trong cờ vua.
 Xác định vị trí di chuyển từ 2 đến n*n sao cho quân mã :
 Di chuyển đúng luật.
 Mỗi ô chỉ được đi qua 1 lần.
 XÂY DỰNG CẤU TRÚC DỮ LIỆU CHO BÀI TOÁN

- Biểu diển bàn cờ bằng một ma trận K[n][n].

- Giá trị của mỗi ô K[i][j] (0 <= i,j < n) trên bàn cờ như sau :

 K[i][j] = 0 : Ô (i,j) chưa được quân mã đi qua.

 K[i][j] = t : Ô (i,j) được quân mã đi đến ở nước thứ t (1 <= t <= n*n).

- Cấu trúc dữ liệu cho mỗi bước đi của quân mã :

Nước đi có thể của con mã được phân tích như sau :

 Từ 1 vị trí (i,j) trên bàn cờ thì có tối đa 8 vị trí (u,v) khác nhau cho
quân mã nhảy tới. Việc thu được vị trí (u,v) từ (i,j) có thể được giải quyết bằng
phương pháp cộng thêm độ chênh lệch về tọa độ chứa sẵn trong 2 mảng phụ hằng
sau :

ver[ ] = {+2, -1, -1, -2, -2, +1, +1, +2};

hor[ ] = {-1, +2, -2, -1, +1, -2, +2, +1};

Ví dụ : Vị trí (u1,v1) = (i + ver[1], j + hor[1]) ,….

 Vị trí (u,v) cần tìm bị ràng buộc bởi 2 điều kiện :

Thứ 1, (u,v) phải còn nằm trong bàn cờ, tức là (0 <= u < n) và (0 <=
v < n).

Thứ 2, K[u][v] phải bằng 0, tức là vị trí này chưa được quân mã đi
qua.

2.4. GIẢI PHÁP – THUẬT TOÁN ĐÃ CÓ ( ĐỆ QUY QUAY LUI )

Thông thường, ta sẽ nghĩ đến thuật toán đệ quy quay lui để giải quyết bài toán
“Mã đi tuần” (phương pháp vét cạn). Ta sẽ xét đến những hạn chế còn mắc phải
của phương pháp này sau. Thuật toán đệ quy quay lui như sau :

- Bắt đầu từ vị trí xuất phát (1).

- Từ vị trí thứ (k) ta đi tìm vị trí thứ (k+1).

- Sử dụng 2 mảng phụ để tìm các khả năng của vị trí thứ (k+1). Với mỗi khả
năng (k+1) ta thực hiện :

 Nếu là vị trí thứ n*n và hành trình đóng thì có được kết quả.

 Nếu chưa là vị trí thứ n*n thì tiếp tục tìm vị trí thứ (k+2).

 Nếu hết đường đi tại vị trí thứ (k+1), tức là cả 8 khả năng đều bất khả
thi thì quay lại, tìm theo hướng (k+1) khác.
Những hạn chế còn mắc phải của thuật toán đệ quy quay lui :

- Vì sử dụng vét cạn nên chỉ áp dụng được với những bài toán với bàn cờ có
kích cỡ nhỏ.

- Trường hợp xấu nhất độ phức tạp của bài toán có thể là O(n64)

Để xử lý các hạn chế trên, ta xét thuật toán Warnsdorff sau :

2.5.GIẢI PHÁP – THUẬT TOÁN ĐỀ XUẤT (WARNSDORFF)

Các thuật ngữ :

- Khanang[i][j] : Khả năng (số đỉnh) mà tại ví trí (i,j) có thể đi được.

- Uutien[ ] : Mảng sắp xếp độ ưu tiên của các khả năng.

Thuật toán Warnsdorff như sau :

Nhận thấy ở thuật toán đệ quy quay lui, hạn chế là do ta không phân biệt độ ưu
tiên của các hướng đi có thể có từ vị trí (i,j). Có tối đa 8 vị trí (u,v) mà từ (i,j) có
thể nhảy tới, ta phải chọn ra hướng đi nào tốt nhất, dể nhất để hướng cho quân mã.
Ta xác định thứ tự ưu tiên của các (u,v) như sau :

- Ở mỗi vị trí (u,v) trên ta tính số Khanang[u][v] của nó.

- Sắp xếp số Khanang[u][v] của mỗi vị trí (u,v).

- Vị trí (u,v) có số Khanang[u][v] bé nhất là tốt nhất, ta đặt Uutien[0] là vị trí


(u,v) đó,…vị trí có Khanang[u][v] lớn nhất là ít được ưu tiên nhất.

Như vậy, từ vị trí thứ (i,j), quân mã sẽ nhảy lần lượt các đến (u,v) có độ ưu tiên đã
sắp xếp.
Chương 3: LẬP TRÌNH VÀ THỬ NGHIỆM

3.1. Chương trình

Chương trình bài toán “Mã đi tuần” được viết bằng ngôn ngữ lập trình Java. Code và
toàn bộ chương trình được đính kèm theo.

3.2. Kết quả thử nghiệm

Chạy chương trình ta được kết quả như sau:

Quân mã sẽ xuất phát tại vị trí (1,1) và di chuyển theo luật cờ vua.
Nhưng ô quân mã đã đi qua sẽ được chuyển sang màu đỏ.
Sau khi đi hết hành trình ( đi hết 64 ô ) thì chương trình đổi màu xanh cho ô xuất phát và
hiện bảng thông báo Tour over gồm số nước đi và vị trí xuất phát.
3.3. Code toàn bộ chương trình

package MaDiTuan;

import java.awt.*;

import java.net.URL;

import javax.swing.*;

public class KnightsTourHeuristic extends JFrame {

private static final long serialVersionUID = 1L;

private Container contents;

private static JButton[][] squares = new JButton[8][8];

private static int squaresTouched = 0;

private static int min = 0;

private static int position = 0;

private static boolean hasMoves = true;

private final static int[] horizontal = { 2, 1, -1, -2, -2, -1, 1, 2 };

private final static int[] vertical = { -1, -2, -2, -1, 1, 2, 2, 1 };

private static int startingRow;

private static int startingColumn;

private static int currentRow = 1;

private static int currentColumn = 1;


private static ImageIcon knight = new
ImageIcon(KnightsTourHeuristic.class.getResource("blackKnight.png"));

private static int[][] accessibility = { { 2, 3, 4, 4, 4, 4, 3, 2 }, { 3, 4,


6, 6, 6, 6, 4, 3 },

{ 4, 6, 8, 8, 8, 8, 6, 4 }, { 4, 6, 8, 8, 8, 8, 6, 4 }, { 4, 6,
8, 8, 8, 8, 6, 4 },

{ 4, 6, 8, 8, 8, 8, 6, 4 }, { 3, 4, 6, 6, 6, 6, 4, 3 }, { 2, 3,
4, 4, 4, 4, 3, 2 } };

public KnightsTourHeuristic() {

super("Knight's Tour");

contents = getContentPane();

contents.setLayout(new GridLayout(8, 8));

// create the board

// upper left corner of board is (0,0)

for (int i = 0; i < 8; i++) {

for (int j = 0; j < 8; j++) {

squares[i][j] = new JButton();

if ((i + j) % 2 != 0)

squares[i][j].setBackground(Color.black);

if ((i + j) % 2 == 0)

squares[i][j].setBackground(Color.white);

contents.add(squares[i][j]);
}

startingRow = currentRow;

startingColumn = currentColumn;

squares[currentRow][currentColumn].setIcon(knight);

squares[currentRow][currentColumn].setBackground(Color.red);

setSize(600, 600);

setResizable(false);

URL knight =
KnightsTourHeuristic.class.getResource("blackKnight.png");

Image knights = Toolkit.getDefaultToolkit().createImage(knight);

setIconImage(knights);

setLocationRelativeTo(null);

setDefaultCloseOperation(EXIT_ON_CLOSE);

setVisible(true);

try {

Thread.sleep(1500);

} catch (InterruptedException e) {

e.printStackTrace();

while (hasMoves) {

moveKnight(currentRow, currentColumn);
try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

private static boolean processValidMoves(int i, int j) {

min = 8;

int validMoveCount = 0;

for (int x = 0; x < 8; x++) {

if (i + vertical[x] < 8 && i + vertical[x] >= 0 && j +


horizontal[x] < 8 && j + horizontal[x] >= 0

&& squares[i + vertical[x]][j +


horizontal[x]].getBackground() != Color.red) {

validMoveCount++;

if (accessibility[i + vertical[x]][j + horizontal[x]] <=


min) {

min = accessibility[i + vertical[x]][j +


horizontal[x]];

position = x;

}
}

if (validMoveCount <= 0) {

hasMoves = false;

squares[startingRow][startingColumn].setBackground(Color.blue);

squaresTouched++;

JOptionPane.showMessageDialog(null, "The knight touched " +


squaresTouched + " squares. Starting position: "

+ startingRow + "," + startingColumn, "Tour


Over", JOptionPane.PLAIN_MESSAGE);

return hasMoves;

private static void moveKnight(int i, int j) {

if (!processValidMoves(i, j))

return;

squares[i][j].setIcon(null);

currentRow += vertical[position];

currentColumn += horizontal[position];

squares[currentRow][currentColumn].setIcon(knight);

squares[currentRow][currentColumn].setBackground(Color.red);

squaresTouched++;

}
KẾT LUẬN

“Mã đi tuần” là một ví dụ điển hình về việc kết hợp giữa Giải thuật và Cấu trúc dữ
liệu để giải quyết bài toán.

Phương pháp Đệ quy quay lui cho phép ta tìm được đường đi của quân mã chỉ bằng vài
dòng lệnh, nhưng bên cạnh đó độ phức tạp của đệ quy là khá lớn. Nên đối với những cấu
trúc có kích cỡ lớn, đồ sộ thì việc sử dụng Đệ quy tỏ ra chậm và chiếm dụng bộ nhớ. Việc
kết hợp đệ quy với những thuật toán thông minh để giải quyết nhanh một bài toán là một
bước tiến trong kỹ thuật lập trình.

Thuật toán Warnsdorff được biết đến như là phương pháp Heuristic của “Mã đi tuần”.
Giải thuật chọn ra và sắp xếp độ tối ưu (mức ưu tiên) của các con đường mà quân mã cần
lựa chọn. Điều đó hướng đến việc tìm ra kết quả nhanh nhất, ít chiếm dụng bộ nhớ nhất
và tất nhiên, độ phức tạp là ít nhất.

Qua quá trình nghiên cứu, thực hiện để hoàn thành đề tài này, em đã thấy được tầm quan
trọng, những ưu điểm mà Giải thuật mang lại. Nếu nói : Cấu trúc dữ liệu là một con
đường, thì Giải thuật có thể được ví như là phương tiện giao thông giúp ta duy chuyển
nhanh trên con đường ấy. Em sẽ cố gắng để ngày càng hoàn thiện khả năng tư duy cũng
như kỹ năng lập trình để ngày càng tiến bộ hơn trên lĩnh vực Công Nghệ thông tin.

Một lần nữa, em xin cảm ơn quý thầy cô đã giúp đỡ chúng em hoàn thành đề tài này.
TÀI LIỆU THAM KHẢO
1. http://en.wikipedia.org/wiki/Knight%27s_tour - Wikipedia.
2. https://vi.wikipedia.org/wiki/Java_(ng%C3%B4n_ng%E1%BB%AF_l
%E1%BA%ADp_tr%C3%ACnh) - Wikipedia.
3. PDF – Giáo Trình Cấu Trúc Dữ Liệu – Phan Chí Tùng – ĐHBK Đà Nẵng.
4. Phân tích Thiết kế Thuật Toán – Nguyễn Văn Linh – Đại học Cần Thơ –
2003.

You might also like