Data Structures: Steven Skiena
Data Structures: Steven Skiena
http://www.cs.sunysb.edu/skiena
String/Character I/O
There are several approaches to reading in the text input required by many of these problems. Either you can: Repeatedly get single characters (perhaps using a library function like getchar); Repeatedly get strings (perhaps using a library function like scanf) and break them down into single characters. Read the entire line as a string (perhaps using a library function like gets), and then parsing it by accessing characters in the string. Perhaps more modern ways using streams are easier, perhaps not.
Pointer Structures
Linked structures provide great exibility in how memory is used, but are often unnecessary when the largest possible size structure is known in advance. Except for argument passing, pointers were not used in any of the example programs in the book. Pointer structures are often more complex to work with and debug than arrays (KISS).
Applications of Stacks
Processing parenthesized formulas (push on a (, pop on )) Recursive program calls (push on a procedure entry, pop on a procedure exit), and Depth-rst traversals of graphs (push on discovering a vertex, pop on leaving it for the last time). Most important is when the insertion order does not matter at all, since stacks are a very simple container.
Queues
Queues maintain rst-in, rst-out order. Enqueue(x,q) Insert item x at the back of queue q . Dequeue(q) Return (and remove) front item from queue q Initialize(q), Full(q), Empty(q) Analogous to these operation on stacks. Applications include (1) implementing buffers, (2) simulating waiting lines, and (3) representing card decks for shufing. Implementations include circular queues and linked lists.
Dictionaries
Dictionaries permit content-based retrieval, unlike the position-based retrieval of stacks and queues. Insert(x,d) Insert item x into dictionary d. Delete(x,d) Remove item x (or the item pointed to by x) from dictionary d. Search(k,d) Return an item with key k if one exists in dictionary d. Classical dictionary implementations include (1) sorted arrays, (2) binary search trees, and (3) hash tables. Hash tables are often the right answer in practice, for reasons of simplicity and performance.
Priority Queues
Priority queues are data structures on sets of items supporting three operations: Insert(x,p) Insert item x into priority queue p. Maximum(p) Return the item with the largest key in priority queue p. ExtractMax(p) Return and remove the item with the largest key in p.
Sets
Sets (or more strictly speaking subsets) are unordered collections of elements drawn from a given universal set U . Member(x,S) Is an item x an element of subset S ? Union(A,B) Construct subset A B of all elements in subset A or in subset B . Intersection(A,B) Construct subset A B of all elements in subset A and in subset B . Insert(x,S), Delete(x,S) Insert/delete element x into/from subset S .
Bit Vectors
An n-bit vector or array can represent any subset S from an n-element universe. Bit i will be 1 iff i S . Element insertion and deletion operations simply ip the appropriate bit. Intersection and union are done by and-ing or or-ing the corresponding bits together.
Object Libraries
A general library of abstract data types cannot really exist in C language because functions in C cant tell the type of their arguments. Thus we would have to dene separate routines such as push int() and push char() for every possible data type.
Java Libraries
Useful standard Java objects appear in the java.util package. Almost all of java.util is available on the judge. Appropriate implementations of the basic data structures include:
Data Structure Stack Queue Dictionaries Priority Queue Sets Abstract class No interface List Map SortedMap Set Concrete class Stack ArrayList, LinkedList HashMap, Hashtable TreeMap HashSet Methods pop, push, empty, peek add, remove, clear put, get, contains firstKey, lastKey, headMap add, remove, contains
52 4
char values[] = "23456789TJQKA"; char suits[] = "cdhs"; int rank_card(char value, char suit) { int i,j; /* counters */ for (i=0; i<(NCARDS/NSUITS); i++) if (values[i]==value) for (j=0; j<NSUITS; j++) if (suits[j]==suit) return( i*NSUITS + j ); printf("Warning: bad input value=%d, suit=%d\n",value,suit); } char suit(int card) { return( suits[card % NSUITS] ); } char value(int card) { return( values[card/NSUITS] ); }
110208 (Yahtzee)
How do we assign dice roles to categories so as to maximize our score? Do we need to try all possibilities, or can we be more clever?