nghiên cứu về kỹ thuật mã hóa của huffman
Trang 1MỤC LỤC
MỤC TIÊU ĐỀ TÀI
Có khá nhiều kỹ thuật nén dữ liệu như: dùng mã ký hiệu, mã đóng gói, mã theo độ dài,
nén dữ liệu với mô hình nguồn, kỹ thuật từ điển….Trong đề tài này, chúng ta sẽ nghiên
cứu về kỹ thuật mã hóa của Huffman
Để hiểu rõ hơn về kĩ thuật này, chúng ta sẽ đi từng bước
Giới thiệu chung về mã Huffman
Tìm hiểu thuật toán Huffman để hiểu rõ về cây Huffman và cách tạo cây
Xây dựng chương trình nén dữ liệu dùng mã Huffman
Giải quyết các vấn đề phát sinh, từ thực tế rút ra những nhận xét về chương trình
nén dùng mã Huffman
Trang 2Ý NGHĨA KHOA HỌC THỰC TIỄN
Vài năm trước, ổ cứng 40 Mb đã được xem là khá rộng rãi cho cả hệ điều hành, chương trình soạn thảo văn bản, chương trình tạo lập bảng tính (kiểu Lotus 123) và các file dữ liệu Ngày nay, khi mỗi chương trình đều cần vài Mb, thậm chí hàng chục Mb
bộ nhớ thì 40Mb trở nên quá ít ỏi Chẳng hạn chỉ riêng MS-Windows đã cần khoảng 10Mb, thêm chương trình soạn thảo nghiêm chỉnh - MS Word for Windows chẳng hạn, lại mất khoảng 8 Mb nữa
Cách giải quyết thông thường khi thiếu bộ nhớ là bớt ra đĩa mềm hoặc gắn thêm
ổ đĩa cứng Nhưng còn phương pháp khá hiệu quả là nén dữ liệu Với chương trình nén thích hợp, có thể sẽ dễ dàng thậm chí tự động - thu gọn kích thước của file File văn bản có thể nén được trên 50%, file bảng tính hoặc dữ liệu DBF trên 70%
Nhu cầu trao đổi dữ liệu giữa mọi người ngày một tăng, dữ liệu mà chúng ta muốn chia sẻ, trao đổi ngày một lớn hơn, phức tạp hơn và đa dạng hơn Để giải quyết
Trang 3vấn đề này bài toán nén dữ liệu đã ra đời, mục đích của nó là làm giảm kích thước của
dữ liệu gốc nhằm giúp cho việc xử lý dữ liệu nhanh hơn (sao chép, di chuyển, tải lên, tải xuống,…) Có hai phương pháp nén dữ liệu là nén dữ liệu có hao hụt (lossy compression) và nén bảo toàn (lossless compression) Thực tế thì cả hai phương pháp nén đều cho ra kết quả tương tự nhau Bởi khi nén có hao hụt ta thường tìm những dữ liệu ít cần thiết để loại bỏ nên bằng mắt thường hầu như ta không nhận ra việc hao hụt
đó Thông thường, hầu hết các tập tinh trong máy tính có rất nhiều thông tin dư thừa, việc thực hiện nén tập tin thực chất là mã hoá lại các tập tin để loại bỏ các thông tin dư thừa
Nhìn chung không thể có phương phát nén tổng quát nào cho kết quả tốt đối với tất cả các loại tập tin vì nếu không ta sẽ áp dụng n lần phương pháp nén này để đạt được một tập tin nhỏ tuỳ ý! Kỹ thuật nén tập tin thường được áp dụng cho các tập tin văn bản (Trong đó có một số kí tự nào đó có xác suất xuất hiện nhiều hơn các kí tự khác), các tập tin ảnh bitmap (Mà có thể có những mảng lớn đồng nhất), các tập tin dùng để biểu diễn âm thanh dưới dạng số hoá và các tín hiệu tương tự (analog signal) khác (Các tín hiệu này có thể có các mẫu được lặp lại nhiều lần) Ðối với các tập tin nhị phân như tập tin chương trình thì sau khi nén cũng không tiết kiệm được nhiều
PHẠM VI NGHIÊN CỨU
Nghiên cứu thuật toán Huffman
Thuật toán tổng quát
Cách xây dựng cây Huffman
Trang 4 Phương pháp nén dùng thuật toán Huffman.
Kiểm tra thực tế và đưa ra kết luận về phương pháp nén này
LỜI MỞ ĐẦU
Trong thời đại công nghệ thông tin ngày nay, nén dữ liệu là quá trình mã hóa thông tin dùng ít bit hơn so với thông tin chưa được mã hóa bằng cách dùng một hoặc kết hợp của các phương pháp nào đó Dựa theo nguyên tắc này giúp tránh các hiện tượng kênh truyền bị quá tải và việc truyền tin trở nên kinh tế hơn
Nén dữ liệu, đơn giản, ngôn ngữ, được đại diện với tối thiểu là tín hiệu kỹ thuật
số vai trò của nó là: để nhanh chóng truyền tín hiệu khác nhau, như Fax, Modem truyền thông, trong các dòng thông tin liên lạc hiện có đồng thời mở thêm các dịch vụ
đa phương tiện, chẳng hạn như kinh doanh giá trị gia tăng; crunch khả năng lưu trữ dữ liệu, chẳng hạn như CD-ROM, VCD và DVD vv; máy phát điện năng thấp hơn, mà đối với hệ thống thông tin di động đa phương tiện đặc biệt quan trọng Từ thời gian này, truyền thông,, băng thông truyền tải, không gian lưu trữ và năng lượng phát thải thậm chí, có thể trở thành đối tượng dữ liệu nén
Trang 5Nén dữ liệu giúp tiết kiệm các tài nguyên như dung lượng bộ nhớ, băng thông, thời gian Ngược lại, dữ liệu đã được nén cần phải được giải nén để đọc (thực thi, nghe, xem v.v…), quá trình này cũng đòi hỏi các tài nguyên nhất định
Nén dữ liệu trước khi truyền đi cũng là một trong các phương pháp nhằm tăng tốc độ truyền dữ liệu Trong các modem hiện đại, việc thực hiện nén dữ liệu trước khi truyền
đi có thể được thực hiện ngay trong modem theo các giao thức V42bis, MNP5 Phương pháp này đòi hỏi hai modem phải có cùng một giao thức nén dữ liệu, điều này nhiều khi khó thoã mãn
Có một phương pháp khác là thực hiện nén các tập tin ngay tại các máy vi tính trước khi truyền đi, tại các máy tính nhận, các tập tin lại được giải nén để phục hồi lại dạng ban đầu Phương pháp này có ưu điểm là bên phát và bên thu chỉ cần có chung phần mềm nén và giải nén, ngoài ra còn có thể áp dụng được để truyền dữ liệu qua các modem không hỗ trợ nén dữ liệu hoặc truyền dữ liệu trực tiếp qua cổng COM của máy tính
Nén được thực hiện bằng cách sử dụng thuật toán nén (công thức) mà sắp xếp lại và tổ chức lại dữ liệu thông tin để nó có thể được lưu trữ nhiều hơn về kinh tế Bằng cách mã hóa thông tin, dữ liệu có thể được lưu trữ bằng cách sử dụng các bit ít hơn Này
được thực hiện bằng cách sử dụng một nén giải nén chương trình làm thay đổi cấu trúc của các dữ liệu tạm thời Nén làm giảm thông tin bằng cách sử dụng những cách khác nhau và hiệu quả hơn của đại diện các thông tin Các phương pháp có thể bao gồm đơn giản loại bỏ các không gian, sử dụng hai ký tự để đại diện cho một chuỗi
ký tự lặp đi lặp lại hoặc thay thế các chuỗi bit lớn hơn bởi những cái nhỏ hơn Một số thuật toán nén đi xa như để xóa thông tin hoàn toàn để đạt được kích thước file nhỏ hơn Tùy thuộc vào thuật toán được sử dụng, các tập tin có thể được đầy đủ liên quan đến giảm kích thước ban đầu của họ
Đề tài này nghiên cứu về một thuật toán nén kinh điển, đó là thuật toán nén sử dụng kĩ thuật mã hóa Huffman Để làm rõ đề tài nay, chúng ta sẽ giải quyết các vấn đề trong phần nội dung
Trang 6Em xin gửi lời cảm ơn tới thầy giáo Nguyễn Văn Thọ - người đã giúp em hoàn thành đồ án chuyên ngành
Đà Nẵng, tháng 10 năm 2010
SVTH
NGUYỄN HỮU HÙNG
CHƯƠNG 1 : MÃ HÓA HUFFMAN
1.1 GIỚI THIỆU CHUNG VỀ MÃ HÓA HUFFMAN.
Thuật toán được đề xuất bởi David A.Huffman (9/8/1925 – 7/10/1999), khi ông còn là sinh viên tại MIT, và công bố năm 1952 trong bài báo "A Method for the Construction of Minimum-Redundancy Codes" Sau này Huffman đã trở thành một giảng viên ở MIT và sau đó ở khoa Khoa học máy tính của đai học California, Santa Cruz, Trường Kỹ nghệ Baskin Mã Huffman là một thuật toán mã hóa dùng để nén dữ liệu Nó dựa trên bảng tần suất xuất hiện các kí tự cần mã hóa để xây dựng một bộ mã nhị phân cho các kí tự đó sao cho dung lượng (số bít) sau khi mã hóa là nhỏ nhất 1.2 MÃ TIỀN TỐ
Trang 7- Để mã hóa các kí hiệu (kí tự, chữ số, ) ta thay chúng bằng các xâu nhị phân, được gọi là từ mã của kí hiệu đó Chẳng hạn bộ mã ASCII, mã hóa cho 256 kí hiệu là biểu diễn nhị phân của các số từ 0 đến 255, mỗi từ mã gồm 8 bít Trong ASCII từ mã của kí
tự "a" là 1100001, của kí tự "A" là 1000001 Trong cách mã hóa này các từ mã của tất
cả 256 kí hiệu có độ dài bằng nhau (mỗi từ mã 8 bít) Nó được gọi là mã hóa với độ dài không đổi
- Khi mã hóa một tài liệu có thể không sử dụng đến tất cả 256 kí hiệu Hơn nữa trong tài liệu chữ cái "a" chỉ có thể xuất hiện 1000000 lần còn chữ cái "A" có thể chỉ xuất hiện 2, 3 lần Như vậy ta có thể không cần dùng đủ 8 bít để mã hóa cho một ký hiệu, hơn nữa độ dài (số bít) dành cho mỗi kí hiệu có thể khác nhau, kí hiệu nào xuất hiện nhiều lần thì nên dùng số bít ít, ký hiệu nào xuất hiện ít thì có thể mã hóa bằng từ mã dài hơn Như vậy ta có việc mã hóa với độ dài thay đổi Tuy nhiên, nếu mã hóa với độ dài thay đổi, khi giải mã ta làm thế nào phân biệt được xâu bít nào là mã hóa của ký hiệu nào Một trong các giải pháp là dùng các dấu phẩy (",") hoặc một kí hiệu quy ước nào đó để tách từ mã của các kí tự đứng cạnh nhau Nhưng như thế số các dấu phẩy sẽ chiếm một không gian đáng kể trong bản mã Một cách giải quyết khác dẫn đến khái niệm mã tiền tố
- Mã tiền tố là bộ các từ mã của một tập hợp các kí hiệu sao cho từ mã của mỗi ký hiệu không là tiền tố (phần đầu) của từ mã một ký hiệu khác trong bộ mã ấy
- Đương nhiên mã hóa với độ dài không đổi là mã tiền tố
- Ví dụ: Giả sử mã hóa từ "LILEE", tập các ký hiệu cần mã hóa gồm 3 chữ cái
"L","I","E"
Nếu mã hóa bằng các từ mã có độ dài bằng nhau ta dùng ít nhất 2 bit cho một chữ cái chẳng hạn "L"=00, "E"=01, "I"=10 Khi đó mã hóa của cả từ là 0010000101
Để giải mã ta đọc hai bit một và đối chiếu với bảng mã
Nếu mã hóa "L"=0, "E"=01, "I"=11 thì bộ từ mã này không là mã tiền tố ví từ
mã của "A" là tiền tố của từ mã của "R" Để mã hóa cả từ LILEE phải đặt dấu ngăn cách vào giữa các từ mã 0.11.0.01.01
Trang 8Nếu mã hóa "L"=0, "E"=10, "I"=11 thì bộ mã này là mã tiền tố Với bộ mã tiền
tố này khi mã hóa xâu "LILEE" ta có 01101010
Hoặc
Ví dụ, muốn mã hóa từ "PETE", với 3 ký tự “E”, “P”, “T” Ta có:
- Nếu mã hóa bằng các từ mã có độ dài bằng nhau, ta dùng ít nhất 2 bit cho một ký tự Chẳng hạn “E”=00, “P”=01, “T”=10 Khi đó mã hóa của cả từ là 0001010010
- Nếu mã hóa “E”=0, “P”=01, “T”=11 thì bộ từ mã này không là mã tiền tố Vì từ mã của “E” là tiền tố của từ mã của “P”
- Nếu mã hóa “E”=0, “P”=10, “T”=11 thì bộ mã này là mã tiền tố Khi đó, để mã hóa xâu “PETE” ta có 01010011
CHƯƠNG 2 : GIẢI THUẬT HUFFMAN VÀ
XÂY DỰNG CHƯƠNG TRÌNH
2.1 GIẢI THUẬT HUFFMAN.
Các tập tin của máy tính được lưu dưới dạng các kí tự có chiều dài không đổi là
8 bits Trong nhiều tập tin, xác suất xuất hiện các kí tự này là nhiều hơn các kí tự khác,
từ đó ta thấy ngay rằng nếu chỉ dùng một vài bit để biểu diễn cho các kí tự có xác suất
Trang 9xuất hiện lớn và dùng nhiều bit hơn để biểu diễn cho các kí tự có xác suất xuất hiện nhỏ thì có thể tiết kiệm được độ dài tập tin một cách đáng kể
Ví dụ, để mã hoá một chuỗi như sau:
"ABRACADABRA"
Nếu mã hoá chuỗi trên trong dạng mã nhị phân 5 bit ta sẽ có dãy bit sau: 0000100010100100000100011000010010000001000101001000001
Ðể giải mã thông điệp này, chỉ đơn giản là đọc ra 5 bits ở từng thời điểm và chuyển đổi nó tương ứng với việc mã hoá nhị phân đã được định nghĩa ở trên Trong
mã chuẩn này, chữ D xuất hiện chỉ một lần sẽ cần số lượng bit giống chữ A xuất hiện nhiều lần
Ta có thể gán các chuỗi bit ngắn nhất cho các kí tự được dùng phổ biến nhất, giả
sử ta gán: A là 0, B là 1, R là 01, C là 10 và D là 11 thì chuỗi trên được biễu diễn như sau:
0 1 01 0 10 0 11 0 1 01 0
Ví dụ này chỉ dùng 15 bits so với 55 bits như ở trên, nhưng nó không thực sự là một mã vì phải lệ thuộc vào khoảng trống để phân cách các kí tự Nếu không có dấu phân cách thì ta không thể giải mã được thông điệp này Ta cũng có thể chọn các từ mã sao cho thông điệp có thể được giải mã mà không cần dấu phân cách, ví dụ như: A là
11, B là 00, C là 010, D là 10 và R là 011, các từ mã này gọi là các từ mã có tính prefix (Không có từ mã nào là tiền tố của từ mã khác) Với các từ mã này ta có thể mã hoá thông điệp trên như sau:
1100011110101110110001111
Với chuỗi đã mã hoá này ta hoàn toàn có thể giải mã được mà không cần dấu phân cách Nhưng bằng cách nào để tìm ra bảng mã một cách tốt nhất? Vào năm 1952, D.Huffman đã phát minh ra một cách tổng quát để tìm ra bảng mã này một cách tốt nhất
- Bước đầu tiên trong việc xây dựng mã Huffman là đếm số lần xuất hiện của mỗi kí tự trong tập tin sẽ được mã hoá
Trang 10- Bước tiếp theo là xây dựng một cây nhị phân với các tần số được chứa trong các nút Hai nút có tấn số bé nhất được tìm thấy và một nút mới được tạo ra với hai nút con là các nút đó với giá trị tần số của nút mới bằng tổng tần suất của hai nút con Tiếp theo hai nút mới với tần số nhỏ nhất lại được tìm thấy và một nút mới nữa lại được tạo ra theo cách trên Lặp lại như vậy cho đến khi tất cả các nút được tổ hợp thành một cây duy nhất
- Sau khi có cây nhị phân, bảng mã Huffman được phát sinh bằng cách thay thế các tần
số ở nút đáy bằng các kí tự tương ứng
2.2 XÂY DỰNG CHƯƠNG TRÌNH
Thuật toán này vẫn dựa trên ý tưởng của Huffman là sử dụng một vài bit (bit code) để biểu diễn một kí tự
Độ dài “mã bit” cho các kí tự không giống nhau:
Kí tự xuất hiện nhiều lần→biểu diễn bằng mã ngắn
Kí tự xuất hiện ít → biểu diễn bằng mã dài
Tạo sẵn một cây “tối thiểu” ban đầu, dữ liệu nén sẽ được cập nhật dần vào cây
2.2.1 Thuật toán nén:
Bước 1: Tìm hai ký tự có trọng số nhỏ nhất ghép lại thành một, trọng số của ký tự mới bằng tổng trọng số của hai ký tự đem ghép
Bước 2: Trong khi số lượng ký tự trong danh sách còn lớn hơn một thì thực hiện bước một, nếu không thì thực hiện bước ba
Trang 11Bước 3: Tách ký tự cuối cùng và tạo cây nhị phân với quy ước bên trái mã 0, bên phải mã 1
2.2.2 Các vấn đề trong việc xây dựng chương trình
2.2.2.1 Các cấu trúc dữ liệu sử dụng trong chương trình:
typedef struct node
{ char Data ;// Kí tự alpha
int TSuat ;// Tần suất kí tự alpha
node * Left ;// Con trỏ trái
node * Right ;// Con trỏ phải
};
typedef node * HTree ;
struct list
{ char alpha ;// Kí tự alpha
int ts ;// Tần suất
char code[max] ;// Mảng lưu trữ mã nhị phân
};
- Kiểu dữ liệu của mảng node[] dùng để cài đặt cây Huffman Các node tương ứng với ký tự (node.alph nếu có) node.Left, node.Right, tương ứng là chỉ số của nút
con trái, con phải, Node.TSuat chứa tổng tần số các nút lá thuộc nhánh của nó
2.2.2.2 Lập bộ ký tự (a[i].alph) và tần số tương ứng (a[i].ts) từ một xâu ký tự
(s):
- Đọc ký tựđầu tiên của xâu cho vào a[0].alpha tương ứng là a[0].ts bằng 1
- Duyệt từng ký tự còn lại của xâu, nếu gặp ký tự nào đã có trong mảng a[i].alph
thì tăng a[i].ts lên 1, nếu chưa có ký tựđó thì thêm phần tử mới vào mảng và cho
tần số tương ứng bằng 1
2.2.2.3 C ài đặt cây Huffman và tần số (chứa trong mảng a[])
- Sắp xếp lại các a
- Khởi tạo các node, node.alph và node.TSuat tương ứng với a.alph và a.ts sau khi
đã sắp xếp Các thành phần còn lại có giá trị là NULL (chưa xác định)
Trang 12- Tạo cây Huffman bằng cách chèn thêm nút mới đồng thời sắp xếp lại theo thứ tự tần
số tăng dần
2.2.2.4 Mã hóa:
- Đọc từng ký tự của chuỗi (hoặc file), gặp phần tử nào thì hiển thị xâu mã hóa tương ứng hoặc ghi thêm xâu mã hóa tương ứng của ký tự đó vào file đã mã hóa (fileout)
2.2.2.5 Giải mã:
- Duyệt cây Huffman từ trên xuống, gặp 0 thì nhảy xuống con trái, gặp 1 thì nhảy xuống con phải, cho tới khi gặp node có thành phần alph khác NULL
- Nếu gặp node có thành phần alph khác NULL thì hiển thị ký tự của node đó và nhảy
về gốc
HÌNH 3.1 : Lưu đồ thuật toán