Tirgul 12 Quicksort Linked Lists 1 Quicksort n

  • Slides: 37
Download presentation
Tirgul 12 Quicksort Linked Lists 1

Tirgul 12 Quicksort Linked Lists 1

Quicksort n n n Select a pivot element Rearrange the elements so that those

Quicksort n n n Select a pivot element Rearrange the elements so that those smaller than the pivot are before it and those larger than the pivot are after it The pivot is now in its final position Recursively sort the segments before/after the pivot Base cases: sorting 0, 1, or 2 elements 2

Quicksort example 5 27 12 3 18 11 7 19 pivot 5 7 3

Quicksort example 5 27 12 3 18 11 7 19 pivot 5 7 3 11 12 27 18 19 smaller than pivot larger than pivot 3 5 7 11 12 27 18 19 3 5 7 11 12 18 19 27 3

Quicksort private static void quicksort(int[] a, int lo, int hi) { if (hi >

Quicksort private static void quicksort(int[] a, int lo, int hi) { if (hi > lo+1) { // at least 3 elements int m = partition(a, lo, hi); quicksort(a, lo, m-1); partition selects a pivot, quicksort(a, m+1, hi); shuffles the array, and returns the pivot’s index } else // base case: 0, 1, or 2 elements if (hi == lo+1 && a[lo] > a[hi]) swap(a, lo, hi); } 4

Partition Selects a pivot from the given array segment, shuffles the segment so that

Partition Selects a pivot from the given array segment, shuffles the segment so that elements smaller (larger) than the pivot appear before (after) it, then returns the pivot’s index private static int partition(int[] a, int lo, int hi) { // select a pivot and place it in a[lo] swap(a, lo, select. Pivot(a, lo, hi)); // shuffle the rest of the elements int m = shuffle(a, lo+1, hi, a[lo]); // move the pivot to its correct location swap(a, lo, m); return m; // return the pivot’s index } 5

Shuffle Recursively rearranges the given array segment so that all elements smaller than the

Shuffle Recursively rearranges the given array segment so that all elements smaller than the pivot come before all elements larger than it. Returns the index where the pivot should go. private static int shuffle(int[] a, int lo, int hi, int pivot){ if (hi == lo) // base case if (a[lo] < pivot) return lo; else return lo-1; else if (a[lo] <= pivot) // a[lo] in correct half return shuffle(a, lo+1, hi, pivot); else { // a[lo] in wrong half swap(a, lo, hi); return shuffle(a, lo, hi-1, pivot); } } 6

Quicksort complexity n n The runtime of partition is always O(n) How many recursive

Quicksort complexity n n The runtime of partition is always O(n) How many recursive calls to quicksort? Worst case: the pivot is always the largest or smallest element T(n) = T(n-1) + O(n) = O(n 2) Best case: the pivot is always the median element T(n) = 2 T(n/2) + O(n) = O(n log n) 7

Linked Lists n n n Separate the logical order of items from their physical

Linked Lists n n n Separate the logical order of items from their physical order in memory Each item points to the location of the next item Each item in the list is called a node Dynamically allocate nodes as needed Linked lists may also be used to implement other data structures, like queues and stacks 8

Linked List Nodes class Node { int data; Node next; } head next 17

Linked List Nodes class Node { int data; Node next; } head next 17 data Does it make sense for Node to be an independent class? null next 10945 616 -14 data 9

Nested classes n n A class defined inside another class is called a nested

Nested classes n n A class defined inside another class is called a nested class A nested class may be public, protected, private, or package private static nested classes do not have access to members of the enclosing class The outside world accesses static nested classes like data members: Outer. Nested nested = new Outer. Nested(); 10

Inner classes n n n Non-static nested classes are called inner classes, and have

Inner classes n n n Non-static nested classes are called inner classes, and have access to members of the enclosing class (even private ones) Every inner class object is associated with the instance of the outer class which created it The outside world instantiates the inner class via an instance of the outer class: Outer. Inner inner = outer. new Inner(); 11

Why use nested classes? n Logical grouping of classes n n Increased encapsulation n

Why use nested classes? n Logical grouping of classes n n Increased encapsulation n If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together The outer class’s members can remain private and still be accessed by inner classes The nested classes themselves can be hidden from the outside world More readable, maintainable code n Places the code closer to where it is used 12

Iterators n n Provide an efficient way to traverse a data structure while protecting

Iterators n n Provide an efficient way to traverse a data structure while protecting its encapsulation Data structure provides an object implementing an iterator interface: public interface Int. List. Iterator { public boolean has. Next(); public int next(); } Returns true iff there are more Gets the next item in the list items to iterate over 13

Using iterators n n The iterator class must have access to the data structure’s

Using iterators n n The iterator class must have access to the data structure’s internal members, so it is usually defined as an inner class or part of the same package Using an iterator to print a list: Int. List. Iterator it = list. iterator(); while (it. has. Next()) System. out. println(it. next()); 14

Linked List implementation public class Int. List { protected static class Node { int

Linked List implementation public class Int. List { protected static class Node { int data; Nested class Node next; Node(int d, Node n){data=d; next=n; } } The first Node in the list protected Node _head; public Int. List() {_head=null; } 15

Linked List implementation Recursively returns a copy of the sub-list starting with the given

Linked List implementation Recursively returns a copy of the sub-list starting with the given node protected static Node clone(Node node) { if (node==null) return null; return new Node(node. data, clone(node. next)); } public Int. List(Int. List list) { Copy constructor _head = clone(list. _head); } 16

Linked List implementation public void add. First(int d){ _head = new Node(d, _head); }

Linked List implementation public void add. First(int d){ _head = new Node(d, _head); } public int remove. First(){ int d = _head. data; _head = _head. next; return d; What does this method assume? } 17

Linked List implementation public boolean is. Empty(){ return _head==null; } public String to. String(){

Linked List implementation public boolean is. Empty(){ return _head==null; } public String to. String(){ String s = “”; for (Node n=_head; n!=null; n=n. next) s += n. data + “ “; Loop over all nodes return s; in the list } 18

Linked List implementation protected class My. Iterator implements Int. List. Iterator { Inner class

Linked List implementation protected class My. Iterator implements Int. List. Iterator { Inner class Node _current; My. Iterator() {_current=_head; } public boolean has. Next() {…} public int next() {…} } public Int. List. Iterator iterator() { return new My. Iterator(); Return an iterator } for this list 19

Stack n n n A stack is a Last-In-First-Out (LIFO) data structure The stack

Stack n n n A stack is a Last-In-First-Out (LIFO) data structure The stack interface is: push, pop, is. Empty Implementing a stack using a linked list is trivial 20

Queue n n n A queue is a First-In-First-Out (FIFO) data structure The queue

Queue n n n A queue is a First-In-First-Out (FIFO) data structure The queue interface is: enqueue, dequeue, is. Empty In order to implement a queue using a linked list, we need a remove. Last method n n Iterate over the entire list, or Use a doubly-linked list with a tail data member pointing to the last node 21

remove. Last (no tail) public int remove. Last() { if (_head. next == null)

remove. Last (no tail) public int remove. Last() { if (_head. next == null) // singleton return remove. First(); Node before = _head; Node after = _head. next; while (after. next != null) { before = after; after = after. next; } What does this method assume? before. next = null; return after. data; } 22

A doubly-linked list with a tail public class Int. List { protected static class

A doubly-linked list with a tail public class Int. List { protected static class Node { int data; Node next, prev; Node(int d, Node p, Node n) { data=d; prev=p; next=n; } } protected Node _head, _tail; public Int. List() { _head = _tail = null; } 23

A doubly-linked list with a tail public void add. First(int d) { Node node

A doubly-linked list with a tail public void add. First(int d) { Node node = new Node(d, null, _head); if (_head == null) // list was empty _tail = node; else // connect old head to new node _head. prev = node; // update head _head = node; } 24

A doubly-linked list with a tail public int remove. First() { int d =

A doubly-linked list with a tail public int remove. First() { int d = _head. data; _head = _head. next; if (_head == null) // list is now empty _tail = null; else { // disconnect old head _head. prev. next = null; _head. prev = null; } What does this return d; method assume? } 25

A doubly-linked list with a tail public int remove. Last(){ int d = _tail.

A doubly-linked list with a tail public int remove. Last(){ int d = _tail. data; _tail = _tail. prev; if (_tail == null) // list is now empty _head = null; else { // disconnect old tail _tail. next. prev = null; _tail. next = null; } What does this return d; method assume? } 26

Count. Int. List n n Each integer will appear at most once in the

Count. Int. List n n Each integer will appear at most once in the list Maintain a counter of how many times each number was added Keep the list sorted The input 5, 2, 7, 5, 5, 7 results in the following Count. Int. List: data 2 5 7 count 1 3 2 null 27

Count. Int. List public class Count. Int. List { protected static class Node {

Count. Int. List public class Count. Int. List { protected static class Node { int data; int count Node next; Node(int d, Node n) { data=d; count=1; next=n; } } protected Node _head; public Count. Int. List() {_head=null; } 28

Count. Int. List protected Node lower. Bound(int d) { if(_head == null || d

Count. Int. List protected Node lower. Bound(int d) { if(_head == null || d < _head. data) return null; Node before = _head; Node after = _head. next; while(after != null && after. data <= d){ before = after; after = after. next; In order to add new data d, we need to find the Node } containing the largest data ≤ d return before; } 29

Count. Int. List Add the given data to the Count. Int. List public void

Count. Int. List Add the given data to the Count. Int. List public void add(int d) { Node prev = lower. Bound(d); if(prev==null) // add new Node at head _head = new Node(d, _head); else if (prev. data==d) prev. count++; //update existing Node else // add new Node after prev. next = new Node(d, prev. next); } 30

Student grade DB public class Student { We want a DB of students sorted

Student grade DB public class Student { We want a DB of students sorted by their private String _name; grades in each subject private int[] _grades; public Student(String name, int[] grades) {…} public Student(Student s) {…} public int get. Grade(int subject) { return _grades[subject]; } public String get. Name() {return _name; } } 31

A multi-linked list name grades next[] Alice Bob {99, 75, 99} null {80, 75}

A multi-linked list name grades next[] Alice Bob {99, 75, 99} null {80, 75} {75, 99, 80} null head[1] Charlie head[2] head[0] 32

Grades DB public class Grades. DB { public static final int SUBJECT_NUM = 3;

Grades DB public class Grades. DB { public static final int SUBJECT_NUM = 3; protected static class Node { Student data; Node[] next = new Node[SUBJECT_NUM]; Node(Student s) {data = new Student(s); } int grade(int i) {return data. get. Grade(i); } } protected Node[] _head = new Node[SUBJECT_NUM]; 33

Grades DB public void add(Student stud) { Add a student to the DB Node

Grades DB public void add(Student stud) { Add a student to the DB Node node = new Node(stud); for (int i=0; i<SUBJECT_NUM; i++) add(i, node); } protected void add(int i, Node node) { Add a node Node prev = lower. Bound(i, node. data); to list #i if (prev==null) { // add node at head node. next[i] = _head[i]; _head[i] = node; } else { // add node after prev node. next[i] = prev. next[i]; prev. next[i] = node; } } 34

Grades DB Return the node which should come before the given student in list

Grades DB Return the node which should come before the given student in list #i protected Node lower. Bound(int i, Student stud) { int grade = stud. get. Grade(i); if (_head[i]==null || grade < _head[i]. grade(i)) return null; Node before = _head[i]; Node after = _head[i]. next[i]; while (after!=null && after. grade(i)<=grade) { before = after; after = after. next[i]; } return before; } 35

Grades DB Return the student names sorted by their grade in the given subject

Grades DB Return the student names sorted by their grade in the given subject public String get. Ranking(int subject) { String ranking = “”; for (Node n = _head[subject]; n!=null; n = n. next[subject]) ranking += n. data. get. Name() + ‘ ‘; return ranking; } For example, get. Ranking(2) returns “Bob Charlie Alice” 36

Linked Lists vs. Arrays Operation Linked List Array Insert at head O(1) O(n) Insert

Linked Lists vs. Arrays Operation Linked List Array Insert at head O(1) O(n) Insert at middle O(n), O(1) given a reference O(n) Remove from head O(1) O(n) Remove from middle O(n), O(1) given a reference O(n) Append O(n), O(1) given a reference O(n+m) Find k-th element O(k) O(1) Search unsorted O(n) Search sorted O(n) O(log n) 37