Datové struktury a algoritmy Část 5 Abstraktní datové typy Petr Felkel
Data structures and algorithms Part 5 Abstract data types Petr Felkel
Abstraktní datové typy Abstrahují od jak? Jak jsou data zobrazena v paměti… Jak jsou prováděny operace… Zdůrazňují co? Co s nimi operace s daty provádějí nezávisle na konkrétní implementaci DSA
Abstract data types Abstract from: How? Emphasize: What? How is the data stored in memory? How are the operations executed? Emphasize: What? What do the operations do with the data (independent of any particular implementation)? DSA
Abstraktní datové typy Fronta (Queue) Zásobník (Stack) Pole (Array) Tabulka (Table) Seznam (List) Strom (Tree) Množina (Set) DSA
Seznam (List) Posloupnost údajů Ukazovátko Pouze v místě ukazovátka lze přidat / zrušit / aktualizovat prvek Homogenní, lineární, dynamická DSA
List (Seznam) Sequence of items Marker Insert, delete, update only where points the marker Homogeneous, linear, dynamic DSA
List (Seznam) List Elem read init Bool Nat insert empty, full delete, first,last next,prev length DSA
List (Seznam) init: -> List insert(_,_): Elem, List -> List read(_): List -> Elem delete(_), first(_), last(_) next(_), prev(_): List -> List length(_): List -> Nat empty(_), full(_) atbeg(_), atend(_): List -> Bool DSA
List (Seznam) Pomocný druh Seq = posloupnost bez ukazovátka Pomocné operace: new: -> Seq ... prázdná posloupnost cons(_,_): Elem, Seq -> Seq cons2(_,_): Elem, List -> List ... vlož do čela mark(_): Seq -> List ... ukaz. do čela DSA
List (Seznam) Example: cons2( a, cons2( b, mark( a b c d cons2( a, cons2( b, mark( cons( c, cons( d, new ))))) DSA
List – insert Where to insert? Where to leave the marker? a b c d x a b c d x a b c d x a b c d x DSA
List – delete a b c d Where to leave the marker? a b d On the next On the previous DSA
List (Seznam) var: x,y:Elem, s:Seq, l:List init = mark( new ) insert( x, mark(s) ) = cons2( x, mark(s)) ... Insert BEFORE the pointer insert( x, cons2( y, l ))= cons2( y, insert( x, l )) x x y DSA
List (Seznam) delete( init ) = init delete( mark( cons( x, s))) = mark( s ) ... delete by the pointer delete( cons2( x, l )) = cons2( x, delete( l )) x x x DSA
List (Seznam) next( init ) = init next( mark( cons( x, s ) ) ) = cons2( x, mark( s ) ) next( cons2( x, l ) ) = cons2( x, next( l ) ) x x ... pointer move ..no change before x x DSA
List (Seznam) prev( mark(s) ) = mark(s) prev( cons2( x, mark( s ) ) ) = mark( cons( x, s )) prev( cons2( x, cons2( y, l ))) = cons2( x, prev( cons2( y, l ))) ... move by head x x x y x y ... move inside DSA
List (Seznam) first( mark(s) ) = mark(s) first( cons2( x, l ) ) = first( prev( cons2( x, l ) ) ) ... no move by head x x ... move step by step to front DSA
List (Seznam) last( init ) = init last( mark( cons( x, s ) ) ) = cons2( x, last( mark( s ) ) ) last( cons2( x, l ) ) = cons2( x, last( l ) ) x x ... move back …no change before x x DSA
List (Seznam) read( init ) = error_elem read( cons2( x, l ) = read( l ) read( mark( cons( x, s ))) = x DSA
List (Seznam) length( init ) = 0 length( cons2( x, l )) = succ( length( l ) ) length( mark( cons( x, s ))) = succ( length( mark( s ))) ... elements before the pointer ... elements after the pointer DSA
List (Seznam) empty( l ) = ( length( l ) == 0 ) full( l ) = ( length( l ) == max ) atbeg( mark( s )) = true atbeg( cons2( x, l )) = false atend( mark( new)) = true atend( mark( cons( x, s )))= false atend( cons2( x, l )) = atend( l ) DSA
List implementation In Array In Array O(n) insert, delete O(1) first, last, prev, next 1 2 3 4 5 B A C D tail point (head) Stacks in Array O(1) insert, delete, prev, next O(n) first, last, … 1 2 3 4 5 B A C D (tail) point B A C D point (head) DSA
List implementation In Dynamic memory O(1) insert, O(1)..O(n) delete O(1) first, last, prev, next - memory for pointers tail head B C A point len 3 Linked list Double linked list Circular double linked list tail head B C A point len 3 B C A 3 head tail point len DSA
List implementation Linked list A B C A x B C head tail point len 3 list::insert( elem x ) { item *help = new item; if( point == NULL ){ //point behind help->next = NULL; help->val = x; if( tail == NULL ) //empty list head = help; else //add at end tail->next = help; tail = help; } //point still points behind list! else { //point in the list - trick help->val = point->val; help->next = point->next; point->next = help; point->val = x; point = help; } len++; head tail A B C point len 3 help head tail A x B C point len 3 DSA
List implementation Linked list B C A B D A C B D A help head tail list::delete( ) { item *help; if( point != NULL ){ //behind ignore if( point->next == NULL ) { //last help = head; //find predecessor while( help->next != point ) help = help->next; } help->next = NULL; point = NULL; delete( tail ); tail = help; else {// trick: skip predec.search help = point->next; *point = *help; if( help == tail ) tail = point; delete( help ); len--; tail head B C A point len 3 help tail head B D A point len C help 4 B D A help 3 tail head point len DSA
List implementation Linked list A B C A x B C head tail point len 3 list::prev( ) { item *help; if( point != head){//point can move help = head; while( help->next != point ) help = help->next; point = help; } head tail A B C point len 3 help head tail A x B C point len 4 DSA
List implementation Double linked list B C A head tail point len 3 list::prev( ) { item *help; if( point != head){//point can move point = point->prev; } Prev is the only place to save! tail head B C A point len 3 DSA
List implementation Double linked list B C A head tail point len 3 list::delete( ) { item *help; if( point != NULL ){ //behind ignore help = point->next ; if( head == point ) //first elem head = help; if( tail == point ) //last elem tail = tail->prev; if( help != NULL ) //update prev help->prev = point->prev; //update next if( point->prev != NULL ); point->prev->next = help; delete( point ); point = help; len--; } tail head B C A point len 3 DSA
List implementation Circular double linked list A B C head tail list list::delete( ) { item *help; if( point != list ){ //not at end point->prev->next = point->next; point->next->prev = point->prev; help = point; point = point->next; delete( help ); len--; } list::prev( ) { if( !atBegin() ) //point!=list->head point = point->prev; head A tail B C list point len 3 help DSA
Abstraktní datové typy Fronta (Queue) Zásobník (Stack) Pole (Array) Tabulka (Table) Seznam (List) Strom (Tree) Množina (Set) DSA
Strom (Tree) Kdy? řazení, vyhledávání, vyhodnocování výrazů, ... acyklický souvislý graf kořenový strom orientovaný strom, zvláštní uzel - kořen kořen spojen se všemi uzly orient. cestou binární strom - má 0, (1), 2 následníky uspořádaný binární strom - dvojice <u, u1> a <u, u2> jsou uspořádány DSA
Tree (Strom) When? sorting, searching, evaluation of expressions, ... acyclic connected graph root tree oriented tree, special node - root root connected to all nodes by oriented path binary tree - has 0, (1), 2 successors ordered binary tree - pairs <u, u1> and <u, u2> are ordered DSA
Strom (Tree) uzel - více následníků binární strom - 2 následníci následník - opět strom homogenní, nelineární, dynamická DSA
Tree (Strom) node - more successors binary tree - 2 successors successor - also a tree homogeneous, nonlinear, dynamic DSA
Binární strom (Tree) Tree Elem info empty Bool cons null left, right leaf setright setleft, DSA
Binární strom (Tree) empty: -> Tree leaf(_): Elem -> Tree cons(_,_,_): Elem, Tree, Tree ->Tree left(_), right(_): Tree -> Tree null(_): Tree -> Bool setleft, setright(_,_): Tree, Tree -> Tree setinfo( Tree, Elem ): -> Tree info(_): Tree -> Elem DSA
Binární strom (Tree) var x: Elem; a,b,t: tree leaf( x ) = cons( x, empty, empty) left( empty ) = error_tree left( cons( x, a, b)) = a right( empty ) = error_tree right( cons( x, a, b)) = b DSA
Binární strom (Tree) null( empty ) = true null( cons( x, a, b)) = false setleft( empty, t ) = error_tree setleft( cons( x, a, b ), t ) = cons( x, t, b ) setright( empty, t ) = error_tree setright( cons( x, a, b ), t ) = cons( x, a, t ) DSA
Binární strom (Tree) setinfo( empty, x ) = error_tree setinfo( cons( x, a, b ), y ) = cons( y, a, b ) info( empty ) = error_elem info( cons( x, a, b ) ) = x DSA
Abstraktní datové typy Fronta (Queue) Zásobník (Stack) Pole (Array) Tabulka (Table) Seznam (List) Strom (Tree) Množina (Set) DSA
Parametrické datové typy Nové typy obohacováním původních o druhy a operace často stejné, jen nad jinými základy liší se jen některými prvky => parametrický datový typ odlišné prvky - parametry DSA
Množina typ: MNOŽINA( ELEMENT ) parametr: typ prvků ELEMENT požadavky na parametr: druhy: Elem operace: eq(_,_): Elem, Elem -> Bool použité typy: ELEMENT, přirozená čísla, logické hodnoty druhy: Elem, Bool, Set, Nat DSA
Množina operace: []: Set (prázdná množina) ins(_,_): Elem,Set ->Set (vložení prvku) del(_,_): Elem,Set ->Set (zrušení -“- ) in(_,_) : Elem,Set ->Bool(test přísluš.) card(_) : Set->Nat (počet prvků) DSA
nezáleží na pořadí vkládání Množina bez opakování proměnné: s: Set, x,y: Elem axiomy: ins(x,s) = if in(x,s) then s del(x,[])=[] del(x,ins(y,s))= if eq(x,y) then del(x,s) else ins(y,del(x,s)) bez opakování prvků nezáleží na pořadí vkládání DSA
Množina bez opakování axiomy: (pokračování) in(x,[]) = false in(x,ins(y,s))= if eq(x,y)then true else in(x,s) card([]) = 0 card(ins(x,s)) = if(in(x,s)) card(s) else succ(card(s)) DSA
Množina bez opakování bez opakování prvků axiomy: (pokračování) eq([],[]) = true eq([], ins(x, t)) = false eq(s,t) = eq(t,s) eq(ins(x,s),t) = if in(x,s) then eq(s,t) else if in(x,t) then eq(s,del(x,t)) else false bez opakování prvků DSA
Abstraktní datové typy Fronta (Queue) Zásobník (Stack) Pole (Array) Tabulka (Table) Seznam (List) Strom (Tree) Množina (Set) DSA
Appendix A Bool example DSA
Bool data type - signature Logical value - Bool Diagram: true,false Bool and,eq not Symbolic: see next slide DSA
Bool data type - signature Logical value - Bool Symbolic: druhy: Bool operace: true,false: Bool (constants, nulary) not: Bool -> Bool (unary operation) and: Bool,Bool -> Bool (binary) eq: Bool,Bool -> Bool DSA
Bool data type - signature Prefix notation and(_,_): Bool,Bool -> Bool Infixový notation _&_: Bool,Bool -> Bool priority: not,and ... Must be stated explicitly DSA
Bool data type - axioms var x,y: Bool not(true) = false negation not(false) = true and(x, true) = x and(x,false) = false logical AND and(x,y) = and(y,x) or(x, true) = true or(x,false) = x logical OR or(x,y) = or(y,x) DSA
Bool data type - axioms Equality - ver. 1 eq(true, true) = true eq(true,false) = false eq(false, true) = false eq(false,false) = true DSA
Bool data type - axioms Equality - ver. 2 eq(x, true) = x eq(x, false) = not(x) eq(x, y) = eq(y, x) DSA
Appendix B - Expressions a) constant: f (where f is nulary operation declared: f:d) b) variable: x (where f is a variable declared var x:d) c) operation – prefix notation: f(t1,t2, ... tn) (where f is n-ary operation declared: f: d1, d2, ..., dn -> d and t1, t2, ..., tn are expressions of sorts d1, d2, ..., dn) d) operace – infix notation : t1 f1 t2 f2 ...fn tn+1 (where f (n+1)-ary operation declared _f1_f2_..._fn : d1, d2, ..., dn+1 -> d and t1, t2, ..., tn+1 expressions of sorts d1, d2, ..., dn+1) e) brackets: (t) (where t is an expression of sort d) f) other notations are not expressions. DSA
Expressions (cont.): Herbrand’s universum for a given signature = set of all expressions on given signature Example: {true, false, not(true), not(false), not(not(true)),...} Two classes of equivalence (describe the same value) {true, not(false), not(not(true)),...} ... [true] {false, not(true), not(not(false)),...} ... [false] DSA
Bool - třídy ekvivalence Množina všech výrazů nad signaturou (Herbrandovo univerzum) {true, false, not(true), not(false), not(not(true)),...} Bool: lze rozdělit na 2 třídy ekvivalence: {true, not(false), not(not(true)),...} ... [true] {false, not(true), not(not(false)),...}... [false] Výrazy třídy popisují různý způsob konstrukce stejné hodnoty DSA
Bool - třídy ekvivalence Doplníme axiomy true = [true] false = [false] not([x])=[not(x)] and([x],[y]) = [and(x, y)] Axiomy s třídami ekvivalence => tvoří model datového typu DSA
Prameny / References Jan Honzík: Programovací techniky, skripta, VUT Brno, 19xx Karel Richta: Datové struktury, skripta pro postgraduální studium, ČVUT Praha, 1990 Bohuslav Hudec: Programovací techniky, skripta, ČVUT Praha, 1993 DSA
Prameny / References Steven Skiena: The Algorithm Design Manual, Springer-Verlag New York, 1998 http://www.cs.sunysb.edu/~algorith Gang of four (Cormen, Leiserson, Rivest, Stein): Introduction to Algorithms, MIT Press, 1990 Code exapmples: M.A.Weiss: Data Structures and Problem Solving using JAVA, Addison Wesley, 2001, code web page: http://www.cs.fiu.edu/~weiss/dsj2/code/code.html DSA