Presentation is loading. Please wait.

Presentation is loading. Please wait.

Data Structures Part 2 Stacks, Queues, Trees, and Graphs Briana B. Morrison CSE 1302C Spring 2010.

Similar presentations


Presentation on theme: "Data Structures Part 2 Stacks, Queues, Trees, and Graphs Briana B. Morrison CSE 1302C Spring 2010."— Presentation transcript:

1 Data Structures Part 2 Stacks, Queues, Trees, and Graphs Briana B. Morrison CSE 1302C Spring 2010

2 2 CSE 1302C Topics Stacks Queues Trees and Graphs

3 3 CSE 1302C Classic Data Structures Now we'll examine some classic data structures Classic linear data structures include queues and stacks Classic nonlinear data structures include trees and graphs

4 4 CSE 1302C A Stack Using a Linked List A stack is a linear data structure that organizes items in a last in, first out (LIFO) manner. Items are added and removed from only one end of a stack Analogies: cafeteria trays are typically organized in a stack, a stack of bills to be paid The tray at the top of the stack was put on the stack last, and will be taken off the stack first.

5 5 CSE 1302C Stacks Stacks often are drawn vertically: poppush

6 6 CSE 1302C Stacks Some stack operations: –push - add an item to the top of the stack –pop - remove an item from the top of the stack –peek (or top) - retrieves the top item without removing it –empty - returns true if the stack is empty A stack can be represented by a singly- linked list A stack can be represented by an array, but the new item should be placed in the next available place in the array rather than at the end

7 7 CSE 1302C A Stack can be Implemented using a Linked List In a stack implemented as a linked list: –To push, we insert at the beginning of the linked list. –To pop, we delete the first item in the linked list. Thus, deletion is not based on value; we always delete the first item in the list.

8 8 CSE 1302C PlayerStackLinkedList Methods Return valueMethod name and argument list voidpush( Player p ) inserts Player p at the top of the stack Playerpop( ) returns and removes the first Player of the list. If the list is empty, the method throws a DataStructureException. Playerpeek( ) returns a copy of the first Player on the list without deleting it. If the list is empty, the method throws a DataStructureException.

9 9 CSE 1302C A Stack Can be Implemented using an Array If we know in advance the maximum number of objects on the stack, we can represent the stack using an array. –This is easier to implement than a linked list. We add items to the stack starting at index 0. We maintain an index top, short for top of the stack. The last element inserted is at index top.

10 10 CSE 1302C Array Representing a Stack There are three items on the stack: indexPlayer object top2 (8, Gino, Diablo ) 1 ( 7, Sarah, Mario ) 0 ( 2, Jin, Golf )

11 11 CSE 1302C Stack after Inserting Player (6, Steve, NFL ) Now there are four items on the stack: indexPlayer object top3 ( 6, Steve, NFL ) 2 (8, Gino, Diablo ) 1 ( 7, Sarah, Mario ) 0 ( 2, Jin, Golf )

12 12 CSE 1302C Our Stack After Popping Once Now there are three items on the stack. Player ( 6, Steve, NFL ) is not on the stack. indexPlayer object 3 ( 6, Steve, NFL ) top2 (8, Gino, Diablo ) 1 ( 7, Sarah, Mario ) 0 ( 2, Jin, Golf )

13 13 CSE 1302C Instance Variables for Stack We will have three instance variables: –A constant STACK_SIZE, representing the capacity of the stack. –An array stack, storing the elements of the stack. –An int top, representing the top of the stack. public class ArrayStack { private static final int STACK_SIZE = 100; private Player [] stack; private int top; …. }

14 14 CSE 1302C Constructor for our Stack The constructor does two things: –It instantiates the array, stack. –It initializes top to -1 to reflect that the stack is empty. If top were initialized to 0, then there would be an element on the stack, at index 0. public ArrayStack( ) { stack = new Player[STACK_SIZE]; top = -1; // stack is empty }

15 15 CSE 1302C Utility Methods for our Stack We will have three utility methods: –isEmpty, returning true if the stack is empty. –isFull, returning true if the stack is full. –toString, returning a String representation of the stack. public bool isEmpty( ) { return ( top == -1 ); } public bool isFull( ) { return ( top == ( STACK_SIZE – 1 ) ); }

16 16 CSE 1302C toString Method for our Stack public String toString( ) { String stackString = ""; for ( int i = top; i >= 0; i-- ) stackString += ( i + ": " + stack[i] + "\n" ); return stackString; }

17 17 CSE 1302C push Method for our Stack public boolean push( Player p ) { if ( !isFull( ) ) { stack[++top] = p; return true; } else return false; }

18 18 CSE 1302C pop Method for our Stack public Player pop { if ( !isEmpty( ) ) return ( stack[top--] ); else throw new DSException ( "Stack empty: cannot pop" ); }

19 19 CSE 1302C Common Error Trap Do not confuse the top of the stack with the last index in the array. Array elements with array indexes higher than top are not on the stack.

20 20 CSE 1302C Queues A queue is similar to a list but adds items only to the rear of the list and removes them only from the front It is called a FIFO data structure: First-In, First- Out Analogy: a line of people at a bank tellers window enqueue dequeue

21 21 CSE 1302C Queues We can define the operations for a queue –enqueue - add an item to the rear of the queue –dequeue (or serve) - remove an item from the front of the queue –empty - returns true if the queue is empty As with our linked list example, by storing generic Object references, any object can be stored in the queue Queues often are helpful in simulations or any situation in which items get backed up while awaiting processing

22 22 CSE 1302C Queues A queue can be represented by a singly- linked list; it is most efficient if the references point from the front toward the rear of the queue A queue can be represented by an array, using the remainder operator (%) to wrap around when the end of the array is reached and space is available at the front of the array

23 23 CSE 1302C A Queue can be Implemented using a Linked List In a queue implemented as a linked list, we enqueue by inserting at the end of the linked list. In a stack implemented as a linked list, we dequeue by deleting the first item in the linked list. Again, deletion is not based on value; it is based on position.

24 24 CSE 1302C A Linked List Class Implementing a Queue Because a queue inserts items at the end of the list, we will add an instance variable, tail, (a PlayerNode reference), representing the last node in the list. In this way, we do not have to traverse the list every time we insert an item. We will need to update that reference every time an item is inserted.

25 25 CSE 1302C A Linked List Implementing a Queue Here is an example of a queue of Player objects represented by a linked list. 2 Jin Golf 8 Gino Diablo 5 Ajay Sonic head null 7 Sarah Mario tail

26 26 CSE 1302C Return valueMethod name and argument list voidenqueue( Player p ) inserts Player p at the end of the list Playerdequeue( ) returns and removes the first Player of the list. If the list is empty, the method throws a DataStructureException Playerpeek( ) returns a copy of the first Player on the list without deleting it. If the list is empty, the method throws a DataStructureException

27 27 CSE 1302C Inserting in a (non-empty) Linked List Representing a Queue Our original list: 2 Jin Golf 8 Gino Diablo 5 Ajay Sonic head null 7 Sarah Mario tail

28 28 CSE 1302C Inserting in a (non-empty) Linked List Representing a Queue Step 1: Instantiate a new node: PlayerNode pn = new PlayerNode( p ); // here, p is Player( 6, Steve, NFL ) 2 Jin Golf 8 Gino Diablo 5 Ajay Sonic head null 7 Sarah Mario 6 Steve NFL null tail pn

29 29 CSE 1302C Inserting in a Linked List Representing a Queue Step 2: Attach the new node at the end of the list : tail.setNext( pn ); 2 Jin Golf 8 Gino Diablo 5 Ajay Sonic head 7 Sarah Mario 6 Steve NFL null tail

30 30 CSE 1302C Inserting in a Linked List Representing a Queue Step 3: Update tail: tail = tail.getNext( ); 2 Jin Golf 8 Gino Diablo 5 Ajay Sonic head 7 Sarah Mario 6 Steve NFL null tail

31 31 CSE 1302C A Linked List Class Implementing a Queue A queue has a front and a back, represented by head and tail, respectively. Could they be inverted, i.e. could head represent the back of the queue and tail represent the front of the queue? This would be highly inefficient because when we delete, we would need to traverse the list in order to update tail. Indeed, we cannot go backward in the list from tail in order to access the next-to-last node (which becomes tail after the deletion).

32 32 CSE 1302C Array Representation of Queues We can also represent a queue using an array. The first (inefficient) idea is to represent the queue with a standard array; two indexes, front and back, represent the front and back of the queue. To enqueue, we could increment back by 1 and store the player at array index back. To dequeue, we could return the element at index front and increment front by 1. The problem with this approach is that the number of available elements in the array will shrink over time.

33 33 CSE 1302C Queue after Inserting First 5 Elements // Player( 5, Ajay, Sonic ) was enqueued first. indexPlayer object 7 6 5 back4 ( 6, Steve, NFL ) 3 (8, Gino, Diablo ) 2 ( 7, Sarah, Mario ) 1 ( 2, Jin, Golf ) front0 ( 5, Ajay, Sonic )

34 34 CSE 1302C Queue after Dequeueing Once Element at index 0 is no longer usable. indexPlayer object 7 6 5 back4 ( 6, Steve, NFL ) 3 (8, Gino, Diablo ) 2 ( 7, Sarah, Mario ) front1 ( 2, Jin, Golf ) 0 ( 5, Ajay, Sonic )

35 35 CSE 1302C Using a Circular Array The solution is to consider the array as a circular array. After back reaches the last array index, we start enqueueing again at index 0. If the array has size 8, the index "after" 7 is 0. The useful capacity of the array never shrinks. If the array has size 8, the useful capacity of the array is always 8.

36 36 CSE 1302C An Empty Queue

37 37 CSE 1302C Enqueueing One Element

38 38 CSE 1302C Enqueueing a Second Element

39 39 CSE 1302C Enqueueing a Third Element

40 40 CSE 1302C Enqueueing a Fourth Element

41 41 CSE 1302C Dequeueing Once

42 42 CSE 1302C Dequeueing Again

43 43 CSE 1302C Full Queue In a queue implemented as a circular array, how do we know when the queue is full? When the queue is full, we have the following relationship between front and back: ( back + 1 – front ) % QUEUE_SIZE == 0

44 44 CSE 1302C A Full Queue

45 45 CSE 1302C Empty Queue When the queue is empty, we also have the same relationship between front and back! ( back + 1 – front ) % QUEUE_SIZE == 0

46 46 CSE 1302C An Empty Queue

47 47 CSE 1302C Queue Full or Empty? So when ( back + 1 – front ) % QUEUE_SIZE == 0 Is the queue full or empty? We cannot tell. There is an easy way to solve this problem: Keep track of the number of items in the queue.

48 48 CSE 1302C Instance Variables for our Queue We will have five instance variables: –A constant representing the capacity of the queue. –An array, storing the elements of the queue. –An int, front, representing the front of the queue. –An int, back, representing the back of the queue. –An int, numberOfItems, storing the number of items in the queue. public class ArrayQueue { private static final int QUEUE_SIZE = 8; private Player [] queue; private int front; private int back; private int numberOfItems; … }

49 49 CSE 1302C Constructor for our Queue The constructor does four things: –instantiates the array, queue. –initializes front to 0 –initializes back to QUEUE_SIZE – 1 –initializes numberOfItems to 0 to reflect that the queue is empty. public ArrayQueue( ) { queue = new Player[QUEUE_SIZE]; front = 0; back = QUEUE_SIZE - 1; numberOfItems = 0; }

50 50 CSE 1302C Utility Methods for our Queue We will have three utility methods: –isEmpty, returning true if the the queue is empty. –isFull, returning true if the the queue is full. –toString, returning a String representation of the queue. public boolean isEmpty( ) { return ( numberOfItems == 0 ); } public boolean isFull( ) { return ( numberOfItems == QUEUE_SIZE ); }

51 51 CSE 1302C toString Method for our Queue public String toString( ) { String queueString = ""; if ( back >= front ) { for ( int i = front; i <= back; i++ ) queueString += queue[i] + "\n"; } else { for ( int i = front; i < QUEUE_SIZE; i++ ) queueString += queue[i] + "\n"; for ( int i = 0; i <= back; i++ ) queueString += queue[i] + "\n"; } return queueString; }

52 52 CSE 1302C enqueue Method for our Queue public boolean enqueue( Player p ) { if ( !isFull( ) ) { queue[( back + 1 )% QUEUE_SIZE] = p; back = ( back + 1 ) % QUEUE_SIZE; numberOfItems++; return true; } else return false; }

53 53 CSE 1302C dequeue Method for our Queue public Player dequeue throws DataStructureException { if ( !isEmpty( ) ) { front = ( front + 1 ) % QUEUE_SIZE; numberOfItems--; return queue[( QUEUE_SIZE + front – 1 ) % QUEUE_SIZE]; } else throw new DataStructureException ( "Queue empty: cannot dequeue" ); }

54 54 CSE 1302C Common Error Trap Do not confuse array index 0 and QUEUE_SIZE - 1 with front and back. In a queue represented by a circular array, the indexes 0 and QUEUE_SIZE - 1 are irrelevant.

55 55 CSE 1302C Implementing a Stack or a Queue as an Array vs as a Linked List ArrayLinked List Easily expandableNoYes Direct access to every itemYesNo Easy to codeYesNo

56 56 CSE 1302C Trees A tree is a non-linear data structure that consists of a root node and potentially many levels of additional nodes that form a hierarchy Nodes that have no children are called leaf nodes Nodes except for the root and leaf nodes are called internal nodes In a general tree, each node can have many child nodes

57 57 CSE 1302C Binary Trees In a binary tree, each node can have no more than two child nodes A binary tree can be defined recursively. Either it is empty (the base case) or it consists of a root and two subtrees, each of which is a binary tree Trees are typically are represented using references as dynamic links, though it is possible to use fixed representations like arrays For binary trees, this requires storing only two links per node to the left and right child

58 58 CSE 1302C Tree Example - Starcraft

59 59 CSE 1302C Dungeon Siege 2

60 60 CSE 1302C Diablo 2

61 61 CSE 1302C Fallout 3

62 62 CSE 1302C Visiting Every Node void PrintTree (Node current) { if (current != null) { Console.WriteLine(current.data) PrintTree(current.left); PrintTree(current.right); } Of course we could order the 3 statements of work in any order, visiting the nodes in a different order. Not to be missed: http://oracleofbacon.org/http://oracleofbacon.org/

63 63 CSE 1302C Graphs A graph is a non-linear structure Unlike a tree or binary tree, a graph does not have a root Any node in a graph can be connected to any other node by an edge Analogy: the highway system connecting cities on a map

64 64 CSE 1302C Digraphs In a directed graph or digraph, each edge has a specific direction. Edges with direction sometimes are called arcs Analogy: airline flights between airports

65 65 CSE 1302C Representing Graphs Both graphs and digraphs can be represented using dynamic links or using arrays. As always, the representation should facilitate the intended operations and make them convenient to implement

66 66 CSE 1302C Collection Classes The C# standard library contains several classes that represent collections, often referred to as the Generic Collection Their underlying implementation is implied in the class names such as ArrayList and LinkedList

67 67 CSE 1302C Stacks The System.Collections.Generic; package contains a Stack class Like ArrayList operations, the Stack operations operate on Object references

68 68 CSE 1302C Questions?


Download ppt "Data Structures Part 2 Stacks, Queues, Trees, and Graphs Briana B. Morrison CSE 1302C Spring 2010."

Similar presentations


Ads by Google