Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 43 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
43
Dung lượng
688,57 KB
Nội dung
05/10/2014 BÀI 12 MỘT SỐ CẤU TRÚC DỮ LIỆU TRONG JAVA Nội dung • Danh sách liên kết (Linked List) • Ngăn xếp (Stack) • Hàng đợi (Queue) • Cây (Tree) 05/10/2014 DANH SÁCH LIÊN KẾT (LINKED-LIST) Mảng vs Danh sách liên kết(DSLK) • Hạn chế mảng Unused spaces X Thêm phần tử A Xóa phần tử B Y 05/10/2014 Mảng vs Danh sách liên kết X A B I want to add Y after A Y ? Ý tưởng xây dựng DSLK • Mỗi phần tử danh sách, gọi nút, chứa tham chiếu trỏ đến nút • Các phần tử khơng nằm nhớ: • Mảng: Các phần tử nằm nhớ element next ak next ai+1 … … nút danh sách (nhưng không thiết phải nhớ) Một nút danh sách… element element next Tham chiếu next null: khơng có nút 05/10/2014 Nhắc lại: Tham chiếu x 20 int x = 20; Integer y = new Integer(20); y 20 Integer ClassName myObject; Bộ nhớ stack new MyClass(); myObject = new MyClass(); myObject Đối tượng Bộ nhớ heap myObject tham chiếu Nhắc lại: Tham chiếu(tiếp) Integer y = new Integer(20); y Integer w; w = new Integer(20); if (w == y) System.out.println("1 w == y"); 20 Integer w w = y; 20 Integer if (w == y) System.out.println("2 w == y"); • Kết hiển thị gì? 05/10/2014 Nhắc lại (tham chiếu) • Mơ tả e nhớ class Employee { private String name; private int salary; } (A) e Employee e = new Employee("Alan", 2000); Alan (C) e 2000 2000 (B) e (D) e Alan Alan 2000 Alan 2000 Xây dựng DSLK Java • Sử dụng kỹ thuật lập trình tổng qt • Giao diện IList định nghĩa phương thức IList.java import java.util.*; public interface public boolean public int public E public boolean public void public E public void IList { isEmpty(); size(); getFirst() throws NoSuchElementException; contains(E item); addFirst(E item); removeFirst() throws NoSuchElementException; print(); } 10 05/10/2014 ListNode ListNode.java class ListNode { /* data attributes */ private E element; private ListNode next; /* constructors */ public ListNode(E item) { this(item, null); } public ListNode(E item, ListNode n) { element = item; next = n; } /* get the next ListNode */ public ListNode getNext() { return next; } /* get the element of the ListNode */ public E getElement() { return element; } /* set the next reference */ public void setNext(ListNode n) { next = n }; } 11 Xây dựng DSLK • Giả sử danh sách có phần tử < a0, a1, a2, a3 > • head trỏ đến phần tử danh sách • Khi duyệt danh sách: head head null a0 a1 a2 a3 BasicLinkedList.java import java.util.*; class BasicLinkedList implements IList { private ListNode head = null; private int num_nodes = 0; //Khai báo phương thức } 12 05/10/2014 Xây dựng DSLK import java.util.*; class BasicLinkedList implements IList { private ListNode head = null; private int num_nodes = 0; BasicLinkedList.java public boolean isEmpty() { return (num_nodes == 0); } public int size() { return num_nodes; } public E getFirst() throws NoSuchElementException { if (head == null) throw new NoSuchElementException("can't get from an empty list"); else return head.getElement(); } public boolean contains(E item) { for (ListNode n = head; n != null; n = n.getNext()) if (n.getElement().equals(item)) return true; return false; } 13 addFirst(): thêm phần tử vào DS • Thêm đầu BasicLinkedList list = new BasicLinkedList (); list.addFirst(“a3”); list.addFirst(“a2”); list.addFirst(“a1”); list.addFirst(“a0”); list head a0 a1 a2 a3 14 05/10/2014 addFirst() DSLK Rỗng Trước thêm Sau thêm: list.addFirst(99) num_nodes head num_nodes head nút head 99 num_nodes 1 nhiều nút num_nodes head n public void addFirst(E item) { head = new ListNode (item, head); num_nodes++; } 15 removeFirst(): Xóa phần tử DSLK rỗng Before: list After: list.removeFirst() num_nodes head nút head num_nodes can’t remove node head 1 nhiều nút num_nodes 1 num_nodes head n public E removeFirst() throws NoSuchElementException { ListNode node; if (head == null) throw new NoSuchElementException("can't remove"); else { node = head; head = head.getNext(); num_nodes ; return node.getElement(); } } 16 05/10/2014 print() Hiển thị danh sách BasicLinkedList.java public void print() throws NoSuchElementException { if (head == null) throw new NoSuchElementException("Nothing to print "); ListNode ln = head; System.out.print("List is: " + ln.getElement()); for (int i=1; i < num_nodes; i++) { ln = ln.getNext(); System.out.print(", " + ln.getElement()); } System.out.println("."); } 17 Collections Framework: LinkedList • Là lớp triển khai giao diện List Collections Framework • Danh sách chiều • Các phương thức triển khai từ List: add(), clear(), contains(), remove(), size(), toArray() • Các phương thức riêng LinkedList • void addFirst(E e): thêm vào đầu danh sách • void addLast(E e): thêm vào cuối danh sách • Iterator descendingIterator(): trả Iterator để duyệt danh sách từ cuối lên • E element(): trả đối tượng đầu danh sách • E get(int index): trả đối tượng vị trí xác định index • listIterator(int index): trả Iterator để duyệt từ vị trí index 18 05/10/2014 LinkedList – Các phương thức • E getFirst() • E getLast() • E removeFirst() • E removeLast() • void push(E e): tương tự addFisrt() • E pop(): tương tự removeFisrt() • E peek(): tương tự getFisrt() • E peekFisrt(): tương tự getFirst() • E peekLast(): tương tự getLast() 19 LinkedList – Ví dụ import java.util.*; TestLinkedListAPI.java public class TestLinkedListAPI { static void printList(LinkedList alist) { System.out.print("List is: "); for (int i = 0; i < alist.size(); i++) System.out.print(alist.get(i) + "\t"); System.out.println(); } // Print elements in the list and also delete them static void printListv2(LinkedList alist) { System.out.print("List is: "); while (alist.size() != 0) { System.out.print(alist.element() + "\t"); alist.removeFirst(); } System.out.println(); } 20 10 05/10/2014 Cây thuật tốn đệ quy • Các thuật tốn đệ quy cài đặt đơn giản làm việc hiệu cấu trúc • Tính kích thước: size (Cây) = + size(Cây trái) + size (Cây phải) • Tính chiều cao: height(Cây) = + Max(height(Cây trái), height(Cây phải)) • 57 Cây nhị phân • Là mà nút khơng có q con: nút trái nút phải • Cây nhị phân đầy đủ: nút có nút • Cây trái: gồm nút trái tồn • Cây phải: gồm nút phải toàn • Định nghĩa đệ quy: nhị phân có nút gốc hai trái phải nhị phân • Ứng dụng: nhị phân biểu thức, nhị phân tìm kiếm + x / - a Cây biểu diễn biểu thức: 2x(a - 1) + b/3 b 58 29 05/10/2014 Xây dựng nhị phân public interface IBinaryTree { IBinaryTree.java //Check whether tree is empty public boolean isEmpty(); //Remove all of nodes public void clear(); //Return the size of the tree public int size(); //Return the height of the tree public int height(); //Visit tree using in-order traversal public void visitInOrder(); //Visit tree using pre-order traversal public void visitPreOrder() //Visit tree using pos-order traversal public void visitPosOrder 59 Xây dựng nhị phân Java • Giải pháp 1: sử dụng mảng để lưu trữ nút • Chỉ số nút: i index item left right • Chỉ số nút cha (nếu có): (i-1)/2 A • Chỉ số nút trái(nếu có): 2*i + 1 B • Chỉ số nút phải(nếu có): 2*i + A B D C E G • Khơng hiệu F C -1 D -1 -1 E -1 null -1 -1 F -1 -1 null -1 -1 null -1 -1 G -1 -1 10 null -1 -1 60 30 05/10/2014 Xây dựng nhị phân Java • Giải pháp 2: Sử dụng danh sách liên kết • Mỗi nút có tham chiếu trỏ đến trái phải left A B D right C E F G 61 Xây dựng nhị phân Java public class BinaryNode { private E element; private BinaryNode left; private BinaryNode right; BinaryNode.java //Constructors public BinaryNode(){ this(null,null,null); } public BinaryNode(E item){ this(item, null,null); } public BinaryNode(E item, BinaryNode l, BinaryNode r){ element = item; left = l; right = r; } 62 31 05/10/2014 Xây dựng nhị phân Java(tiếp) //getter methods BinaryNode.java //Return true if has left child public static boolean hasLeft(BinaryNode t){ return t.left != null; } // Return true if has right child public static boolean hasRight(BinaryNode t){ return t.right != null; } // Add left child public void addLeft(BinaryNode l){ left = l; } //Add right child public void addRight(BinaryNode r){ right = r; } 63 Xây dựng nhị phân Java(tiếp) BinaryTree.java public class BinaryTree implements IBinaryTree{ private BinaryNode root; //Constructors public BinaryTree(){ root = null; } public BinaryTree(E rootItem){ root = new BinaryNode(rootItem, null, null); } //getter methods public BinaryNode getRoot(){ return root; } //setter methods public void setRoot(BinaryNode r){ root = r;} public boolean isEmpty() { return root == null; } public void clear() { root = null; } 64 32 05/10/2014 Tính kích thước root • Sử dụng đệ quy • Trường hợp sở: root == null ST = • Bước đệ quy: ST = + SL + SR • ST: Kích thước • SL: Kích thước trái • SR: Kích thước phải R L BinaryNode.tree //Return the size of the binary tree public int size(){ return size(root); } private int size(BinaryNode n){ if(n == null) return 0; else return + size(n.getLeft()) + size(n.getRight()); } 65 Đệ quy tính kích thước Ngăn xếp gọi phương thức A sizeG() return sizeDFE() sizeCB() G() return = + size return FED() 2 + size = sizeA() = return + size CB() B D C E F G 66 33 05/10/2014 Tính chiều cao root • Sử dụng đệ quy • Trường hợp sở: root == null HT = -1 • Bước đệ quy HT = + max(HL , HR) HT HL HR L R • HT: Chiều cao • HL: Chiều cao trái • HR: Chiều cao phải BinaryTree.java //Return the size of the binary tree rooted at n public int height(){ return height(root); } private int height(BinaryNode n){ if(n == null) return -1; else return + Math.max(height(n.getLeft()), height(n.getRight())); } Duyệt theo thứ tự 67 parent • Duyệt theo thứ tự giữa(in order): sử dụng đệ quy • Nếu có trái, duyệt trái • Duyệt nút cha • Nếu có phải, duyệt phải R L • Ví dụ: D, B, G,E, A, C, F BinaryTree.java public void visitInOrder(){ visitInOrder(root); } private void visitInOrder(BinaryNode n){ if(n.hasLeft()) visitInOrder(n.getLeft()); System.out.println(n.getElement()); if(n.hasRight()) visitInOrder(n.getRight()); } A B D C E F G 68 34 05/10/2014 Duyệt theo thứ tự trước parent • Duyệt theo thứ tự trước(pre order): sử dụng đệ quy • Duyệt nút cha • Nếu có trái, duyệt trái • Nếu có phải, duyệt phải R L • Ví dụ: A, B, D, E, G, C, F BinaryTree.java public void visitPreOrder(){ visitPreOrder(root); } private void visitPreOrder(BinaryNode n){ System.out.println(n.getElement()); if(n.hasLeft()) visitPreOrder(n.getLeft()); if(n.hasRight()) visitPreOrder(n.getRight()); } A B D C E F G 69 Duyệt theo thứ tự sau parent • Duyệt theo thứ tự trước(pre order): sử dụng đệ quy • Nếu có trái, duyệt trái • Nếu có phải, duyệt phải • Duyệt nút cha R L • Ví dụ: D, G, E, B, F, C, A public void visitPosOrder(){ BinaryTree.java visitPosOrder(root); } private void visitPosOrder(BinaryNode n){ if(n.hasLeft()) visitPosOrder(n.getLeft()); if(n.hasRight()) visitPosOrder(n.getRight()); System.out.println(n.getElement()); } A B D C E F G 70 35 05/10/2014 Thử nghiệm BinaryTreeDemo.java public class BinaryTreeDemo { public static void main(String[] args) { IBinaryTree tree = new BinaryTree("A"); BinaryNode left = new BinaryNode("B"); tree.getRoot().addLeft(left); left.addLeft(new BinaryNode("D")); left.addRight(new BinaryNode("E")); BinaryNode right; right = left.getRight(); right.addLeft(new BinaryNode("G")); right = new BinaryNode("C"); tree.getRoot().addRight(right); right.addRight(new BinaryNode("F")); 71 Thử nghiệm (tiếp) BinaryTreeDemo.java System.out.println(“The size of tree:” + tree.size()); System.out.println(“The height of tree:” + tree.height()); System.out.println("Visit tree by in-order"); tree.visitInOrder(); System.out.println("Visit tree by pre-order"); tree.visitPreOrder(); System.out.println("Visit tree by pos-order"); tree.visitPosOrder(); } } 72 36 05/10/2014 Bài tập • Viết phương thức tìm kiếm • Gợi ý: thực tương tự phương thức duyệt 73 Cây nhị phân tìm kiếm • Cây nhị phân tìm kiếm: • Là nhị phân • Mọi trái nhỏ cha • Mọi phải lớn cha • Cho phép tìm kiếm với độ phức tạp O(log(n)) • Tìm kiếm nhị phân thường: O(n) 6 3 Cây nhị phân tìm kiếm 9 Khơng phải nhị phân tìm kiếm 74 37 05/10/2014 Xây dựng nhị phân tìm kiếm IBinarySearchTree.java public interface IBinarySearchTree{ //Insert into a subtree public void insert(E item) throws DuplicateItemException; //Find a node public BinaryNode find(E item); //Visit tree using in-order traversal public void visitInOrder(); //Visit tree using pre-order traversal public void visitPreOrder() //Visit tree using pos-order traversal public void visitPosOrder 75 Xây dựng nhị phân tìm kiếm BinarySearchTree.java public class BinaryTree extends BinaryTree implement IBinaryTree{ private BinaryNode root; private Comparator comparator; //Constructors public BinarySearchTree(Comparator c){ root = null; comparator = c; } public BinarySearchTree(BinaryNode r, Comparator c){ root = r; comparator = c; } //declares other methods } 76 38 05/10/2014 Thêm nút vào • Sử dụng đệ quy • Trường hợp sở: nút duyệt null thêm nút vào vị trí duyệt • Bước đệ quy: • Nếu nút lớn hơn, thêm vào trái • Nếu nút nhỏ hơn, thêm vào phải • Nếu nút thơng báo lỗi trùng nút 77 Thêm nút vào BinarySearchTree.java public void insert(E item) throws DuplicateItemException { root = insert(item, root); } private BinaryNode insert(E item, BinaryNode t) throws DuplicateItemException { if(t == null) t = new BinaryNode(item); else if(comparator.compare(item, t.getElement()) < 0) t.addLeft(insert(item, t.getLeft())); else if(comparator.compare(item, t.getElement()) > 0) t.addRight(insert(item, t.getRight())); else throw new DuplicateItemException(item.toString()); return t; } 78 39 05/10/2014 Tìm kiếm nhị phân • Sử dụng vòng lặp : nút duyệt khác null thực thủ tục đệ quy • Bước sở: Nếu nút duyệt mang giá trị tìm kiếm trả lại nút duyệt • Bước đệ quy: • Nếu giá trị nhỏ nút duyệt, tìm trái • Nếu giá trị lớn nút duyệt, tìm phải 79 Tìm kiếm nhị phân BinarySearchTree.java public BinaryNode find(E item) { return find(item, root); } private BinaryNode find(E item, BinaryNode t) { while(t != null){ if(comparator.compare(item, t.getElement()) < 0) t = t.getLeft(); else if (comparator.compare (item, t.getElement()) > 0) t = t.getRight(); else return t; } return null; } 80 40 05/10/2014 Ví dụ thử nghiệm BinarySearchTreeDemo.java public class BinarySearchTreeDemo { public static class IntComparator implements Comparator{ @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); } } public static void main(String[] args) throws DuplicateItemException{ Comparator c = new IntComparator(); BinarySearchTree tree = new BinarySearchTree(c); tree.insert(6); tree.insert(3); tree.insert(7); tree.insert(1); tree.insert(5); tree.insert(4); tree.insert(9); 81 Ví dụ thử nghiệm(tiếp) BinarySearchTreeDemo.java tree.visitInOrder(); if (tree.find(5) != null) System.out.println("Found item!"); else System.out.println("Could not found item!"); if (tree.find(8) != null) System.out.println("Found item!"); else System.out.println("Could not found item!"); } } 82 41 05/10/2014 Bài tập Viết phương thức: • Tìm nút có giá trị lớn • Tìm nút có giá trị nhỏ • Xóa nút khỏi 83 TreeSet • TreeSet lớp Collections Framework cài đặt tổng quát • Các nút có thứ tự theo định nghĩa người dùng • Các phương thức chung: size(), remove()… • Các phương thức • TreeSet() • TreeSet(Comparator comp) : khởi tạo với so sánh để xếp • TreeSet(Collection c): khởi tạo với nút đối tượng Collection • boolean add(E e): trả true thêm nút • boolean remove(E e): trả true xóa nút 84 42 05/10/2014 TreeSet - Các phương thức • void clear(): xóa tồn • boolean contain(Objects o): trả true tìm • • • • • • thấy Iterator descendingIterator(): trả Iterator để theo thứ tự giảm dần Iterator iterator(): trả Iterator để theo thứ tự tăng dần E first(): trả phần tử nhỏ E last(): trả phần tử lớn E floor(E e): trả nút lớn nhỏ e E higher(E e): trả nút nhỏ lớn e 85 Tài liệu tham khảo • Bài giảng sử dụng hình ảnh mã nguồn minh họa cho nội dung DSLK, ngăn xếp hàng đợi từ giảng Đại học QG Singapore (NUS) • Nội dung tham khảo từ sách “Data Structures & Problem Solving Using Java”, Mark Allen Weiss 86 43 ... (D) e Alan Alan 2000 Alan 2000 Xây dựng DSLK Java • Sử dụng kỹ thuật lập trình tổng quát • Giao diện IList định nghĩa phương thức IList .java import java. util.*; public interface public boolean... tử < a0, a1, a2, a3 > • head trỏ đến phần tử danh sách • Khi duyệt danh sách: head head null a0 a1 a2 a3 BasicLinkedList .java import java. util.*; class BasicLinkedList implements IList {... NoSuchElementException; print(); } 10 05/10/2014 ListNode ListNode .java class ListNode { /* data attributes */ private E element; private ListNode next; /* constructors */ public ListNode(E item) { this(item,