Project_documentation in space n
Project_documentation in space n
(Cohort-1)”
1
Contents
1 Introduction 4
3 DataStructureVisualizer 11
3.1 User interface (UI) . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2 Visualization . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Button functions . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4 Data structure visualizer code . . . . . . . . . . . . . . . . . . 12
2
List of Figures
1 The starting look of the application . . . . . . . . . . . . . . . 33
2 The adding of elements . . . . . . . . . . . . . . . . . . . . . . 34
3 The deleting of elements . . . . . . . . . . . . . . . . . . . . . 34
4 Randomizing an array . . . . . . . . . . . . . . . . . . . . . . 34
5 Random array . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6 Bubble sort visualized . . . . . . . . . . . . . . . . . . . . . . 35
7 Linked List . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8 Binary tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
9 Inorder traversal . . . . . . . . . . . . . . . . . . . . . . . . . 36
10 Inorder traversal saved in the file . . . . . . . . . . . . . . . . 36
11 Graphs visualized . . . . . . . . . . . . . . . . . . . . . . . . 37
12 DFS visualized . . . . . . . . . . . . . . . . . . . . . . . . . . 37
13 DFS traversal saved in the file . . . . . . . . . . . . . . . . . 37
3
1 Introduction
The Data Structure Visualizer aims to be an interactive tool designed to make
data structure concepts more digestible for students and professionals. By
providing a rich graphical user interface, the program makes complex data
structures such as arrays, binary trees, graphs, and different sorting algo-
rithms more intuitive. Users can select different data structures and perform
several operations like adding or deleting certain elements, inserting random
data, and visualizing some popular sorting algorithms such as Bubble Sort,
Selection Sort, and Insertion Sort. Furthermore, the program also includes
things like graph traversal methods and tree traversal methods. Each anima-
tion is done step by step, helping the user to understand the process clearly.
Another feature of this application is also the adjustable speed animation,
which gives the user a more in-depth look of every single step.
4
2.3 Binary Tree class
The binary tree class will provide all the necessary method to implement a
binary search tree, as well as the tree traversals. Firstly, each element in the
tree will enter following a level order manner. This way it insures that the
binary tree remains balanced. Furthermore, methods such as randomization
and deletion are also part of the class Binary Tree. Lastly, the class will also
include the three main types of traversal in a tree.
• Selection Sort: Finds the smallest element in the unsorted section and
swaps it with the first unsorted element
5
• Insertion Sort: Builds a sorted section by inserting elements into their
correct position. Each algorithm returns intermediate steps to enable
step-by-step visualization
def i n s e r t ( s e l f , v a l u e ) :
i f not s e l f . r o o t :
s e l f . r o o t = Node ( v a l u e )
return
6
queue . append ( node . l e f t )
queue . append ( node . r i g h t )
def g e t t r a v e r s a l s t e p s ( s e l f , t r a v e r s a l t y p e ) : #t h e
t r a v e r s a l t y e s of t r e e s are inorder , preorder ,
postorder
steps = [ ]
i n o r d e r ( node . l e f t )
s t e p s . append ( node )
i n o r d e r ( node . r i g h t )
def p r e o r d e r ( node ) : #p r e o r d e r t r a v e r s a l r o o t , l e f t ,
right
i f node :
s t e p s . append ( node )
p r e o r d e r ( node . l e f t )
p r e o r d e r ( node . r i g h t )
def p o s t o r d e r ( node ) : #p o s t o r d e r t r a v e r s a l l e f t ,
right , root
i f node :
p o s t o r d e r ( node . l e f t )
p o s t o r d e r ( node . r i g h t )
s t e p s . append ( node )
traversal functions = {
7
” inorder ” : inorder ,
” preorder ” : preorder ,
” postorder ” : postorder
}
i f t r a v e r s a l t y p e in t r a v e r s a l f u n c t i o n s :
t r a v e r s a l f u n c t i o n s [ traversal type ] ( s e l f . root )
return s t e p s
return None
c l a s s Graph : #I m p l e m e n t a t i o n o f a graph
def init ( self ) :
s e l f . a d j a c e n c y l i s t = {}
def add edge ( s e l f , s r c , d e s t ) :
i f s r c not in s e l f . a d j a c e n c y l i s t : # A l l t h e noded
are s t o r e d in the adjacency l i s t
s e l f . adjacency list [ src ] = [ ]
i f d e s t not in s e l f . a d j a c e n c y l i s t : # t h e
d e s t i n a t i o n nodes and t h e s o u r c e nodes a r e
stored in the adjacency l i s t
s e l f . a d j a c e n c y l i s t [ dest ] = [ ]
s e l f . a d j a c e n c y l i s t [ s r c ] . append ( d e s t )
s e l f . a d j a c e n c y l i s t [ d e s t ] . append ( s r c )
def g e t d f s s t e p s ( s e l f , s t a r t ) : #Depth f i r s t s e a r c h
t r a v e r s a l o f t h e graph
v i s i t e d = set ( )
steps = [ ]
def d f s ( node ) : #i m p l e m e n t a t i o n o f d f s
i f node not in v i s i t e d :
v i s i t e d . add ( node )
s t e p s . append ( node )
f o r n e i g h b o r in s e l f . a d j a c e n c y l i s t [ node ] :
dfs ( neighbor )
dfs ( start )
return s t e p s
8
def g e t b f s s t e p s ( s e l f , s t a r t ) : # g e t t h e s e t e d t o k e e p
t r a c k o f t h e v i s i t e d nodes and t h e queue t o k e e p
t r a c k o f t h e nodes t o be v i s i t e d
v i s i t e d = set ( )
queue = [ s t a r t ]
steps = [ ]
v i s i t e d . add ( s t a r t )
while queue :
node = queue . pop ( 0 )
s t e p s . append ( node )
f o r n e i g h b o r in s e l f . a d j a c e n c y l i s t [ node ] :
i f n e i g h b o r not in v i s i t e d :
v i s i t e d . add ( n e i g h b o r )
queue . append ( n e i g h b o r )
return s t e p s
def d f s ( s e l f , s t a r t v e r t e x ) : #i m p l e m n t a t i o n o f d e p t h
f i r s t search
v i s i t e d = set ( )
steps = [ ]
def d f s r e c u r s i v e ( v e r t e x ) : #s o l i v i n g i t r e c u r s i v e l y
v i s i t e d . add ( v e r t e x )
s t e p s . append ( v e r t e x )
f o r n e i g h b o r in s e l f . graph [ v e r t e x ] :
i f n e i g h b o r not in v i s i t e d :
d f s r e c u r s i v e ( neighbor )
9
s e l f . comparing = comparing i f comparing i s not None
else [ ]
s e l f . swapping = swapping i f swapping i s not None
else [ ]
steps = [ ]
a r r a y = a r r . copy ( )
i f a l g o r i t h m == ” bubble ” :
#i m p l e m e n t a t i o n o f t h e b u u b l e s o r t s o r t a l g o r i t h m s .
Swap a d a j c e n t e l e m e n t s i f t h e c u r r e n t e l e m e n t
i s g r e a t e r than t h e n e x t e l e m e n t
n = len ( a r r a y )
f o r i in range ( n ) :
f o r j in range ( 0 , n − i − 1 ) :
# Add comparison s t e p
s t e p s . append ( S o r t S t e p ( a r r a y . copy ( ) ,
comparing =[ j , j + 1 ] ) )
e l i f a l g o r i t h m == ” s e l e c t i o n ” :
#i m p l e m e n t a t i o n o f t h e s e l e c t i o n s o r t a l g o r i t h m .
Find t h e minimum e l e m e n t i n t h e a r r a y and swap
i t with the f i r s t element
n = len ( a r r a y )
f o r i in range ( n ) :
min idx = i
f o r j in range ( i + 1 , n ) :
# Add comparison s t e p
s t e p s . append ( S o r t S t e p ( a r r a y . copy ( ) ,
comparing =[ min idx , j ] ) )
10
i f array [ j ] < array [ min idx ] :
min idx = j
i f m i n i d x != i :
# Add swap s t e p
array [ i ] , array [ min idx ] = array [ min idx ] ,
array [ i ]
s t e p s . append ( S o r t S t e p ( a r r a y . copy ( ) ,
swapping =[ i , m i n i d x ] ) )
e l i f a l g o r i t h m == ” i n s e r t i o n ” :
#i m p l e m e n t a t i o n o f t h e i n s e r t i o n s o r t a l g o r i t h m .
I n s e r t an e l e m e n t from t h e u n s o r t e d a r r a y t o i t s
correct p o s i t i o n in the sorted
n = len ( a r r a y )
f o r i in range ( 1 , n ) :
key = a r r a y [ i ]
j = i − 1
while j >= 0 and key < a r r a y [ j ] :
# Add comparison s t e p
s t e p s . append ( S o r t S t e p ( a r r a y . copy ( ) ,
comparing =[ j , j + 1 ] ) )
array [ j + 1] = array [ j ]
j −= 1
a r r a y [ j + 1 ] = key
s t e p s . append ( S o r t S t e p ( a r r a y . copy ( ) , swapping =[ j
+ 1, i ]) )
return s t e p s
3 DataStructureVisualizer
The DataStructureVisualizer file is the graphical interface program that will
be displayed to the user. The main focus of the file is the usage of the Tkinter
library. The library insures that each data structure will be shown correctly
and that the algorithms and the operations will be animated correctly. In
this part we have three main components, the user interface, Visualization,
and button functions.
11
3.1 User interface (UI)
The program has a structured and intuitive layout. Firstly, it starts with the
Data structure selection, which is done with radio buttons between Array,
List, Tree, and graph. Secondly, it shows different operations that you can
do to a specific data structure like to add an element, delete an element and
randomize it. Special buttons like tree traversals and graph traversals only
become available when you press the correct data structure. If we choose the
Array data structure, the sorting algorithms will become available to press.
Below all the different options, the slider which will dictate the animation
speed will be available. Lastly, a button to save the results of the current
traversal or sorting operation into a file for future reference will be available.
3.2 Visualization
The visualization updates dynamically to reflect the state of the current
selected data structure. In the case of the array, the elements are displayed
using rectangle shapes with numerical values inside. The same can be said
for linked list, with the exception of including the arrow symbol to visualize
a pointer. In Binary trees, the nodes and edges are drawn in a hierarchical
manner in order to display the parent-child relationship. In graphs, similar
visualization is also used, using nodes and arrows to symbolize direction.
12
#i m p p l e m e n t a t i o n v u s u a k i z a t i o n u s i n g t k i t e r
import t k i n t e r a s tk
from t k i n t e r import ttk , messagebox , s i m p l e d i a l o g #
messagebox used f o r showing message and s i m p l e d i a l o g f o r
t a k i n g i n p u t from u s e r
from d a t a s t r u c t u r e import BinaryTree , g e t s o r t i n g s t e p s ,
Graph #i m p o r t f i r m t h e o t h e r f i l e o f t h e s t r u c u r e s t h a t
w i l l output
import math #math l i b r a r y f o r g r a p h s
import random #random f o r r a n d o m i z i n g t h e d a t a i n t h e
structures
from t k i n t e r import ttk , messagebox , s i m p l e d i a l o g ,
filedialog
class DataStructureVisualizer :
def i n i t ( s e l f , root ) :
s e l f . root = root
s e l f . r o o t . t i t l e ( ” Data S t r u c t u r e V i s u a l i z e r ” )
# Main d a t a s t r u c t u r e v a r i a b l e s
s e l f . c u r r e n t s t r u c t u r e = None
s e l f . data = [ ]
s e l f . b i n a r y t r e e = BinaryTree ( )
s e l f . graph = Graph ( )
s e l f . a n i m a t i o n s p e e d = tk . DoubleVar ( v a l u e =1.0)
s e l f . is animating = False
s e l f . animation steps = [ ]
s e l f . current step = 0
# UI Elements
s e l f . create ui ()
#randomize a r r a y w i l l f i r s t t a k e t h e i n p u t from t h e u s e r
and t h e n randomize t h e a r r a y u s i n g number from 1 t o 100
def r a n d o m i z e a r r a y ( s e l f ) :
count = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ” Enter
number o f e l e m e n t s t o randomize : ” , minvalue =1,
maxvalue =20)
i f count :
s e l f . data = [ random . r a n d i n t ( 1 , 1 0 0 ) f o r in
range ( count ) ]
13
s e l f . update visualization ()
def c r e a t e u i ( s e l f ) :
# C r e a t e a frame f o r s e l e c t i n g d a t a s t r u c t u r e
s t r u c t u r e f r a m e = t t k . LabelFrame ( s e l f . r o o t , t e x t=”
S e l e c t Data S t r u c t u r e ” ) #g i v i n g i t a l a b e l
s t r u c t u r e f r a m e . g r i d ( row=0, column =0, padx =10 , pady
=10 , s t i c k y=” nsew ” ) #s e t t i n g t h e p o s i t i o n o f t h e
frame
#r a d i o b u t t o n s f o r t h e d a t a s t r u c t u r e s
s e l f . s t r u c t u r e v a r = tk . S t r i n g V a r ( v a l u e=” Array ” )
s t r u c t u r e s = [ ” Array ” , ” L i s t ” , ” Tree ” , ”Graph” ]
#i m p l e m e n t i n g t h e r a d i o b u t t o n s
f o r s t r u c t in s t r u c t u r e s :
t t k . Radiobutton ( s t r u c t u r e f r a m e , t e x t=s t r u c t ,
v a r i a b l e= s e l f . s t r u c t u r e v a r ,
v a l u e=s t r u c t , command= s e l f .
c h a n g e s t r u c t u r e ) . pack (
anchor=”w” )
# Frame f o r o p e r a t i o n s
o p e r a t i o n f r a m e = t t k . LabelFrame ( s e l f . r o o t , t e x t=”
Operations ” )
o p e r a t i o n f r a m e . g r i d ( row=1, column =0, padx =10 , pady
=10 , s t i c k y=” nsew ” )
# B u t t o n s f o r a d d i n g and d e l e t i n g e l e m e n t s
t t k . Button ( o p e r a t i o n f r a m e , t e x t=”Add Element ” ,
command= s e l f . a d d e l e m e n t ) . pack ( f i l l =”x” ,
pady=5)
t t k . Button ( o p e r a t i o n f r a m e , t e x t=” D e l e t e Element ” ,
command= s e l f . d e l e t e e l e m e n t ) . pack ( f i l l =”x” ,
pady=5)
# Randomize b u t t o n ( dynamic f u n c t i o n a l i t y )
s e l f . r a n d o m i z e b u t t o n = t t k . Button ( o p e r a t i o n f r a m e ,
t e x t=” Randomize ” , command= s e l f .
randomize structure )
s e l f . r a n d o m i z e b u t t o n . pack ( f i l l =”x” , pady=5)
14
# Tree t r a v e r s a l b u t t o n s
s e l f . t r e e b u t t o n s f r a m e = t t k . LabelFrame (
o p e r a t i o n f r a m e , t e x t=” Tree T r a v e r s a l s ” )
s e l f . t r e e b u t t o n s f r a m e . pack ( f i l l =”x” , pady=5)
t t k . Button ( s e l f . t r e e b u t t o n s f r a m e , t e x t=” I n o r d e r ” ,
command=lambda : s e l f . t r a v e r s e t r e e ( ” i n o r d e r
” ) ) . pack ( f i l l =”x” , pady=2)
t t k . Button ( s e l f . t r e e b u t t o n s f r a m e , t e x t=” P r e o r d e r ”
,
command=lambda : s e l f . t r a v e r s e t r e e ( ”
p r e o r d e r ” ) ) . pack ( f i l l =”x” , pady=2)
t t k . Button ( s e l f . t r e e b u t t o n s f r a m e , t e x t=” P o s t o r d e r
”,
command=lambda : s e l f . t r a v e r s e t r e e ( ”
p o s t o r d e r ” ) ) . pack ( f i l l =”x” , pady=2)
# Sorting buttons
s e l f . s o r t b u t t o n s f r a m e = t t k . LabelFrame (
o p e r a t i o n f r a m e , t e x t=” S o r t i n g ” )
s e l f . s o r t b u t t o n s f r a m e . pack ( f i l l =”x” , pady=5)
# Graph−s p e c i f i c b u t t o n s
s e l f . g r a p h b u t t o n s f r a m e = t t k . LabelFrame (
o p e r a t i o n f r a m e , t e x t=”Graph T r a v e r s a l s ” )
s e l f . g r a p h b u t t o n s f r a m e . pack ( f i l l =”x” , pady=5)
15
t t k . Button ( s e l f . g r a p h b u t t o n s f r a m e , t e x t=”Add Edge
”,
command= s e l f . add edge ) . pack ( f i l l =”x” , pady
=5)
t t k . Button ( s e l f . g r a p h b u t t o n s f r a m e , t e x t=”DFS” ,
command=lambda : s e l f . t r a v e r s e g r a p h ( ” d f s ” ) )
. pack ( f i l l =”x” , pady=2)
t t k . Button ( s e l f . g r a p h b u t t o n s f r a m e , t e x t=”BFS” ,
command=lambda : s e l f . t r a v e r s e g r a p h ( ” b f s ” ) )
. pack ( f i l l =”x” , pady=2)
# Animation s p e e d c o n t r o l
s p e e d f r a m e = t t k . LabelFrame ( o p e r a t i o n f r a m e , t e x t=
” Animation Speed ” )
s p e e d f r a m e . pack ( f i l l =”x” , pady=5)
s p e e d s l i d e r = t t k . S c a l e ( s p e e d f r a m e , f r o m =0.1 , t o
=2.0 ,
v a r i a b l e= s e l f .
a n i m a t i o n s p e e d , o r i e n t=
” horizontal ”)
s p e e d s l i d e r . pack ( f i l l =”x” , pady=5)
# Save t o f i l e b u t t o n
t t k . Button ( o p e r a t i o n f r a m e , t e x t=” Save T r a v e r s a l t o
F i l e ” , command= s e l f . s a v e t o f i l e ) . pack ( f i l l =”x”
, pady=5)
# Frame f o r v i s u a l i z i n g t h e s t r u c t u r e
s e l f . v i s u a l f r a m e = t t k . LabelFrame ( s e l f . r o o t , t e x t=
” Visualization ”)
s e l f . v i s u a l f r a m e . g r i d ( row=0, column =1, rowspan =2,
padx =10 , pady =10 , s t i c k y=” nsew ” )
s e l f . v i s u a l c a n v a s = tk . Canvas ( s e l f . v i s u a l f r a m e ,
bg=” w h i t e ” , h e i g h t =400 , width =600)
s e l f . v i s u a l c a n v a s . pack ( f i l l =” both ” , expand=True )
16
s e l f . r o o t . g r i d r o w c o n f i g u r e ( 1 , w e i g h t =1)
# Update b u t t o n s t a t e s b a s e d on t h e i n i t i a l
structure
s e l f . update button states ()
def s a v e t o f i l e ( s e l f ) :
i f not s e l f . a n i m a t i o n s t e p s :
messagebox . s h o w i n f o ( ” Save ” , ”No t r a v e r s a l o r
s o r t i n g s t e p s a v a i l a b l e to save . ” )
return
f i l e p a t h = f i l e d i a l o g . asksaveasfilename (
d e f a u l t e x t e n s i o n=” . t x t ” ,
filetypes
=[( ”
Text
files”,
” ∗. txt
”) , (”
All
files”,
” ∗.∗ ”)
])
i f not f i l e p a t h :
return
try :
with open ( f i l e p a t h , ”w” ) a s f i l e :
f o r s t e p in s e l f . a n i m a t i o n s t e p s :
i f isinstance ( step , str ) :
f i l e . w r i t e ( s t e p + ” \n” )
e l i f hasattr ( s t e p , ’ v a l u e ’ ) :
f i l e . w r i t e ( s t r ( s t e p . v a l u e ) + ” \n” )
messagebox . s h o w i n f o ( ” Save ” , ” T r a v e r s a l s t e p s
saved s u c c e s s f u l l y ! ” )
except E x c e p t i o n a s e :
messagebox . s h o w e r r o r ( ” E r r o r ” , f ” F a i l e d t o s a v e
t h e f i l e : { e }” )
def r a n d o m i z e s t r u c t u r e ( s e l f ) :
i f s e l f . c u r r e n t s t r u c t u r e == ” Array ” :
17
count = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ” Enter
number o f e l e m e n t s t o randomize : ” , minvalue
=1, maxvalue =20)
i f count :
s e l f . data = [ random . r a n d i n t ( 1 , 1 0 0 ) f o r
in range ( count ) ]
s e l f . update visualization ()
e l i f s e l f . c u r r e n t s t r u c t u r e == ” L i s t ” :
count = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ” Enter
number o f e l e m e n t s t o randomize : ” , minvalue
=1, maxvalue =20)
i f count :
s e l f . data = [ random . r a n d i n t ( 1 , 1 0 0 ) f o r
in range ( count ) ]
s e l f . update visualization ()
e l i f s e l f . c u r r e n t s t r u c t u r e == ” Tree ” :
count = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ” Enter
number o f e l e m e n t s t o randomize : ” , minvalue
=1, maxvalue =20)
i f count :
s e l f . b i n a r y t r e e = BinaryTree ( )
s e l f . data = [ ]
for in range ( count ) :
v a l u e = random . r a n d i n t ( 1 , 1 0 0 )
s e l f . binary tree . i n s e r t ( value )
s e l f . data . append ( v a l u e )
s e l f . update visualization ()
e l i f s e l f . c u r r e n t s t r u c t u r e == ”Graph” :
num nodes = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ”
Enter number o f nodes : ” , minvalue =2,
maxvalue =20)
num edges = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ”
Enter number o f e d g e s : ” , minvalue =1,
maxvalue=num nodes ∗ ( num nodes − 1 ) // 2 )
i f num nodes and num edges :
s e l f . graph = Graph ( )
nodes = [ s t r ( i ) f o r i in range ( num nodes ) ]
18
f o r i in range ( num nodes ) :
s e l f . graph . a d j a c e n c y l i s t [ nodes [ i ] ] =
[]
s e l f . data = nodes
edge count = 0
while e d g e c o u n t < num edges :
s r c = random . c h o i c e ( nodes )
d e s t = random . c h o i c e ( nodes )
i f s r c != d e s t and d e s t not in s e l f .
graph . a d j a c e n c y l i s t [ s r c ] :
s e l f . graph . add edge ( s r c , d e s t )
e d g e c o u n t += 1
s e l f . update visualization ()
def g e n e r a t e r a n d o m e l e m e n t s ( s e l f ) :
import random
count = s i m p l e d i a l o g . a s k i n t e g e r ( ” Input ” , ” Enter
number o f e l e m e n t s t o g e n e r a t e : ” , minvalue =1,
maxvalue =20)
i f count :
s e l f . data = [ ]
for in range ( count ) :
v a l u e = random . r a n d i n t ( 1 , 1 0 0 )
s e l f . data . append ( v a l u e )
i f s e l f . c u r r e n t s t r u c t u r e == ” Tree ” :
s e l f . binary tree . i n s e r t ( value )
s e l f . update visualization ()
def u p d a t e b u t t o n s t a t e s ( s e l f ) :
i s t r e e = s e l f . c u r r e n t s t r u c t u r e == ” Tree ”
i s a r r a y = s e l f . c u r r e n t s t r u c t u r e == ” Array ”
i s g r a p h = s e l f . c u r r e n t s t r u c t u r e == ”Graph”
# Enable / d i s a b l e t r e e t r a v e r s a l b u t t o n s
f o r c h i l d in s e l f . t r e e b u t t o n s f r a m e . w i n f o c h i l d r e n
() :
c h i l d [ ” s t a t e ” ] = ” normal ” i f i s t r e e e l s e ”
disabled ”
# Enable / d i s a b l e s o r t i n g b u t t o n s
19
f o r c h i l d in s e l f . s o r t b u t t o n s f r a m e . w i n f o c h i l d r e n
() :
c h i l d [ ” s t a t e ” ] = ” normal ” i f i s a r r a y e l s e ”
disabled ”
# Enable / d i s a b l e graph b u t t o n s
f o r c h i l d in s e l f . g r a p h b u t t o n s f r a m e .
winfo children () :
c h i l d [ ” s t a t e ” ] = ” normal ” i f i s g r a p h e l s e ”
disabled ”
def a d d e l e m e n t ( s e l f ) :
e l e m e n t = s i m p l e d i a l o g . a s k s t r i n g ( ” Input ” , ” Enter
e l e m e n t t o add : ” )
i f e l e m e n t and e l e m e n t . i s d i g i t ( ) :
v a l u e = int ( e l e m e n t )
s e l f . data . append ( v a l u e )
i f s e l f . c u r r e n t s t r u c t u r e == ” Tree ” :
s e l f . binary tree . i n s e r t ( value )
s e l f . update visualization ()
e l i f element :
messagebox . s h o w e r r o r ( ” E r r o r ” , ” P l e a s e e n t e r a
v a l i d number . ” )
def d e l e t e e l e m e n t ( s e l f ) :
e l e m e n t = s i m p l e d i a l o g . a s k s t r i n g ( ” Input ” , ” Enter
element to d e l e t e : ” )
i f e l e m e n t and e l e m e n t . i s d i g i t ( ) :
v a l u e = int ( e l e m e n t )
i f v a l u e in s e l f . data :
s e l f . data . remove ( v a l u e )
i f s e l f . c u r r e n t s t r u c t u r e == ” Tree ” :
s e l f . b i n a r y t r e e = BinaryTree ( )
f o r v a l in s e l f . data :
s e l f . binary tree . i n s e r t ( val )
s e l f . update visualization ()
else :
messagebox . s h o w e r r o r ( ” E r r o r ” , ” Element not
found i n t h e data s t r u c t u r e . ” )
def s t a r t s o r t i n g ( s e l f , a l g o r i t h m ) :
20
i f not s e l f . data :
messagebox . s h o w i n f o ( ” S o r t ” , ”The data s t r u c t u r e
i s empty . ” )
return
if s e l f . is animating :
return
s e l f . i s a n i m a t i n g = True
s e l f . a n i m a t i o n s t e p s = g e t s o r t i n g s t e p s ( s e l f . data .
copy ( ) , a l g o r i t h m )
s e l f . current step = 0
s e l f . animate sort step ()
def a n i m a t e s o r t s t e p ( s e l f ) :
i f s e l f . c u r r e n t s t e p < len ( s e l f . a n i m a t i o n s t e p s ) :
step = s e l f . animation steps [ s e l f . current step ]
s e l f . data = s t e p . a r r a y . copy ( )
s e l f . update visualization ()
s e l f . v i s u a l i z e a r r a y ( s t e p . comparing , s t e p .
swapping )
s e l f . c u r r e n t s t e p += 1
d e l a y = int ( 1 0 0 0 / s e l f . a n i m a t i o n s p e e d . g e t ( ) )
s e l f . r o o t . a f t e r ( dela y , s e l f . a n i m a t e s o r t s t e p )
else :
s e l f . is animating = False
s e l f . update visualization ()
def t r a v e r s e t r e e ( s e l f , t r a v e r s a l t y p e ) :
i f not s e l f . b i n a r y t r e e . r o o t :
messagebox . s h o w i n f o ( ” T r a v e r s e ” , ”The t r e e i s
empty . ” )
return
if s e l f . is animating :
return
s e l f . i s a n i m a t i n g = True
21
s e l f . animation steps = s e l f . binary tree .
get traversal steps ( traversal type )
s e l f . current step = 0
s e l f . animate traversal step ()
def a n i m a t e t r a v e r s a l s t e p ( s e l f ) :
i f s e l f . c u r r e n t s t e p < len ( s e l f . a n i m a t i o n s t e p s ) :
# R e s e t a l l nodes t o o r i g i n a l c o l o r
f o r item in s e l f . v i s u a l c a n v a s . f i n d w i t h t a g ( ”
node ” ) :
s e l f . v i s u a l c a n v a s . i t e m c o n f i g ( item , f i l l =”
lightcoral ”)
# H i g h l i g h t c u r r e n t node
current node = s e l f . animation steps [ s e l f .
current step ]
node items = s e l f . visual canvas . find withtag ( f ”
node { c u r r e n t n o d e . v a l u e }” )
f o r item in n o d e i t e m s :
s e l f . v i s u a l c a n v a s . i t e m c o n f i g ( item , f i l l =”
yellow ”)
s e l f . c u r r e n t s t e p += 1
d e l a y = int ( 1 0 0 0 / s e l f . a n i m a t i o n s p e e d . g e t ( ) )
s e l f . r o o t . a f t e r ( dela y , s e l f .
animate traversal step )
else :
s e l f . is animating = False
s e l f . root . a f t e r (500 , s e l f . r e s e t n o d e c o l o r s )
def r e s e t n o d e c o l o r s ( s e l f ) :
f o r item in s e l f . v i s u a l c a n v a s . f i n d w i t h t a g ( ” node ” )
:
i f s e l f . c u r r e n t s t r u c t u r e == ” Tree ” :
s e l f . v i s u a l c a n v a s . i t e m c o n f i g ( item , f i l l =”
lightcoral ”)
e l i f s e l f . c u r r e n t s t r u c t u r e == ” Array ” :
s e l f . v i s u a l c a n v a s . i t e m c o n f i g ( item , f i l l =”
lightblue ”)
e l i f s e l f . c u r r e n t s t r u c t u r e == ” L i s t ” :
22
s e l f . v i s u a l c a n v a s . i t e m c o n f i g ( item , f i l l =”
lightgreen ”)
def u p d a t e v i s u a l i z a t i o n ( s e l f ) :
s e l f . visual canvas . delete (” a l l ”)
i f s e l f . c u r r e n t s t r u c t u r e == ” Array ” :
s e l f . visualize array ()
e l i f s e l f . c u r r e n t s t r u c t u r e == ” L i s t ” :
s e l f . v i s u a l i z e l i s t ()
e l i f s e l f . c u r r e n t s t r u c t u r e == ” Tree ” :
s e l f . visualize tree ()
e l i f s e l f . c u r r e n t s t r u c t u r e == ”Graph” :
s e l f . visualize graph ()
# Draw g r i d l i n e s
f o r i in range ( len ( s e l f . data ) + 1 ) :
x = x s t a r t + i ∗ box width
s e l f . v i s u a l c a n v a s . c r e a t e l i n e (x , y s t a r t − 10 ,
x , y start +
box height +
10 ,
f i l l =” l i g h t g r a y ” )
23
x s t a r t + len ( s e l f .
data ) ∗ box width ,
y start + box height +
1 0 , f i l l =”
lightgray ”)
# Determine box c o l o r b a s e d on o p e r a t i o n
i f i in swapping :
f i l l c o l o r = ”#FF6B6B”
o u t l i n e c o l o r = ”#FF0000”
outline width = 3
e l i f i in comparing :
f i l l c o l o r = ”#4ECDC4”
o u t l i n e c o l o r = ”#45B7AF”
outline width = 3
else :
f i l l c o l o r = ” lightblue ”
o u t l i n e c o l o r = ””
outline width = 1
# Draw shadow
shadow offset = 3
s e l f . v i s u a l c a n v a s . c r e a t e r e c t a n g l e ( x0 +
s h a d o w o f f s e t , y0 + s h a d o w o f f s e t ,
x1 +
shadow offset
, y1 +
shadow offset
,
f i l l =”#CCCCCC”
, o u t l i n e=”
”)
24
s e l f . v i s u a l c a n v a s . c r e a t e r e c t a n g l e ( x0 , y0 , x1 ,
y1 ,
f i l l=
fill color ,
o u t l i n e=
outline color
,
width=
outline width
, t a g s =(”
node ” , f ”
node {
element }” ) )
# Draw e l e m e n t v a l u e
s e l f . v i s u a l c a n v a s . c r e a t e t e x t ( ( x0 + x1 ) / 2 , (
y0 + y1 ) / 2 ,
t e x t=s t r ( e l e m e n t ) ,
f o n t =(” A r i a l ” , 1 2 ,
” bold ” ) )
# Draw i n d e x numbers
s e l f . v i s u a l c a n v a s . c r e a t e t e x t ( ( x0 + x1 ) / 2 ,
y0 − 2 0 ,
t e x t=s t r ( i ) ,
f o n t =(” A r i a l ” , 1 0 )
)
# Add o p e r a t i o n i n d i c a t o r s
i f i in comparing :
s e l f . v i s u a l c a n v a s . c r e a t e t e x t ( ( x0 + x1 ) /
2 , y1 + 2 0 ,
t e x t=”
comparing ” ,
f o n t =(” A r i a l ” ,
8) ,
f i l l =”#45B7AF”
)
e l i f i in swapping :
25
s e l f . v i s u a l c a n v a s . c r e a t e t e x t ( ( x0 + x1 ) /
2 , y1 + 2 0 ,
t e x t=” swapping
”,
f o n t =(” A r i a l ” ,
8) ,
f i l l =”#FF0000”
)
def v i s u a l i z e l i s t ( s e l f ) :
x s t a r t = 50
y s t a r t = 200
box width = 50
b o x h e i g h t = 50
a r r o w l e n g t h = 30
# Draw node
s e l f . v i s u a l c a n v a s . c r e a t e r e c t a n g l e ( x0 , y0 , x1 ,
y1 ,
f i l l =”
lightgreen ”
26
,
t a g s =(” node ” ,
f ” node {
element }” ) )
# Draw v a l u e
s e l f . v i s u a l c a n v a s . c r e a t e t e x t ( ( x0 + x1 ) / 2 , (
y0 + y1 ) / 2 ,
t e x t=s t r ( e l e m e n t ) ,
f o n t =(” A r i a l ” , 1 2 ,
” bold ” ) )
# Draw arrow l i n e
s e l f . v i s u a l c a n v a s . c r e a t e l i n e ( arrow x0 ,
arrow y ,
arrow x1 ,
arrow y ,
arrow=” l a s t ” ,
width =2)
def v i s u a l i z e t r e e ( s e l f ) :
i f not s e l f . data :
return
def c a l c u l a t e p o s i t i o n ( index , l e v e l , x o f f s e t ) :
””” C a l c u l a t e t h e x , y c o o r d i n a t e s f o r a node
b a s e d on i t s l e v e l and p o s i t i o n . ”””
y = 50 + l e v e l ∗ 80
x = 300 + x o f f s e t
return x , y
27
”””Draw a t r e e node and i t s c o n n e c t i o n t o
p a r e n t i f e x i s t s . ”””
r a d i u s = 20
# Draw c o n n e c t i o n t o p a r e n t
i f p a r e n t x i s not None and p a r e n t y i s not
None :
s e l f . v i s u a l c a n v a s . c r e a t e l i n e ( parent x ,
parent y + radius ,
x , y − radius ,
width =2)
# Draw node
s e l f . visual canvas . c r e a t e o v a l (x − radius , y −
radius ,
x + radius , y +
radius ,
f i l l =” l i g h t c o r a l ” ,
t a g s =(” node ” , f ”
node { v a l u e } ” ) )
# Draw v a l u e
s e l f . visual canvas . create text (x , y ,
t e x t=s t r ( v a l u e ) ,
f o n t =(” A r i a l ” , 1 2 ,
” bold ” ) )
28
def v i s u a l i z e l e v e l o r d e r ( ) :
””” V i s u a l i z e t h e t r e e u s i n g l e v e l −o r d e r
t r a v e r s a l . ”””
i f not s e l f . data :
return
# C a l c u l a t e t h e maximum l e v e l
level count = 0
nodes at current level = 1
t o t a l n o d e s = len ( s e l f . data )
while t o t a l n o d e s > 0 :
t o t a l n o d e s −= n o d e s a t c u r r e n t l e v e l
n o d e s a t c u r r e n t l e v e l ∗= 2
l e v e l c o u n t += 1
# Draw each l e v e l
node index = 0
f o r l e v e l in range ( l e v e l c o u n t ) :
n o d e s i n l e v e l = min( 2 ∗∗ l e v e l , len ( s e l f .
data ) − n o d e i n d e x )
l e v e l w i d t h = 2 ∗∗ ( l e v e l c o u n t − 1 ) ∗ 60
# Base s p a c i n g
f o r i in range ( n o d e s i n l e v e l ) :
i f n o d e i n d e x >= len ( s e l f . data ) :
break
# Calculate position
x o f f s e t = ( i − n o d e s i n l e v e l /2 + 0 . 5 )
∗ ( l e v e l w i d t h / ( 2 ∗∗ l e v e l ) )
x , y = calculate position ( i , level ,
x offset )
# C a l c u l a t e p a r e n t p o s i t i o n f o r drawing
connection
i f node index > 0:
p a r e n t i n d e x = ( n o d e i n d e x − 1 ) //
2
parent level = level − 1
29
p a r e n t i = p a r e n t i n d e x − ( 2 ∗∗
p a r e n t l e v e l − 1)
p a r e n t x o f f s e t = ( p a r e n t i − ( 2 ∗∗
p a r e n t l e v e l ) /2 + 0 . 5 ) ∗ (
l e v e l w i d t h / ( 2 ∗∗ p a r e n t l e v e l
))
parent x , parent y =
calculate position ( parent i ,
parent level , parent x offset )
else :
p a r e n t x , p a r e n t y = None , None
# Draw t h e node
draw node ( x , y , s e l f . data [ n o d e i n d e x ] ,
parent x , parent y )
n o d e i n d e x += 1
def t r a v e r s e g r a p h ( s e l f , t r a v e r s a l t y p e ) :
i f not s e l f . graph . a d j a c e n c y l i s t :
30
messagebox . s h o w i n f o ( ”Graph” , ”The graph i s
empty . ” )
return
if s e l f . is animating :
return
s t a r t n o d e = s i m p l e d i a l o g . a s k s t r i n g ( ” Input ” , ” Enter
s t a r t node : ” )
i f s t a r t n o d e not in s e l f . graph . a d j a c e n c y l i s t :
messagebox . s h o w e r r o r ( ” E r r o r ” , ” S t a r t node not
found i n t h e graph . ” )
return
s e l f . i s a n i m a t i n g = True
i f t r a v e r s a l t y p e == ” d f s ” :
s e l f . a n i m a t i o n s t e p s = s e l f . graph . g e t d f s s t e p s
( start node )
e l i f t r a v e r s a l t y p e == ” b f s ” :
s e l f . a n i m a t i o n s t e p s = s e l f . graph . g e t b f s s t e p s
( start node )
s e l f . current step = 0
s e l f . animate graph step ()
def a n i m a t e g r a p h s t e p ( s e l f ) :
i f s e l f . c u r r e n t s t e p < len ( s e l f . a n i m a t i o n s t e p s ) :
current node = s e l f . animation steps [ s e l f .
current step ]
# H i g h l i g h t c u r r e n t node
s e l f . visual canvas . delete (” highlight ”)
node items = s e l f . visual canvas . find withtag ( f ”
node { c u r r e n t n o d e }” )
f o r item in n o d e i t e m s :
s e l f . v i s u a l c a n v a s . i t e m c o n f i g ( item , f i l l =”
yellow ”)
s e l f . c u r r e n t s t e p += 1
d e l a y = int ( 1 0 0 0 / s e l f . a n i m a t i o n s p e e d . g e t ( ) )
31
s e l f . r o o t . a f t e r ( dela y , s e l f . a n i m a t e g r a p h s t e p )
else :
s e l f . is animating = False
s e l f . root . a f t e r (500 , s e l f . r e s e t n o d e c o l o r s )
def v i s u a l i z e g r a p h ( s e l f ) :
s e l f . visual canvas . delete (” a l l ”)
n o d e p o s i t i o n s = {}
r a d i u s = 20
c a n v a s w i d t h = 600
c a n v a s h e i g h t = 400
n o d e c o u n t = len ( s e l f . graph . a d j a c e n c y l i s t )
a n g l e s t e p = 2 ∗ math . p i / n o d e c o u n t i f n o d e c o u n t
e l s e 0 # Angle s t e p i n r a d i a n s
# C a l c u l a t e node p o s i t i o n s i n a c i r c u l a r l a y o u t
f o r i , node in enumerate ( s e l f . graph . a d j a c e n c y l i s t .
keys ( ) ) :
angle = angle step ∗ i
x = c a n v a s w i d t h // 2 + 150 ∗ math . c o s ( a n g l e )
y = c a n v a s h e i g h t // 2 + 150 ∗ math . s i n ( a n g l e )
n o d e p o s i t i o n s [ node ] = ( x , y )
# Draw node
s e l f . visual canvas . c r e a t e o v a l (x − radius , y −
radius , x + radius , y + radius ,
f i l l =” l i g h t b l u e ” ,
t a g s =(” node ” , f ”
node { node } ” ) )
s e l f . v i s u a l c a n v a s . c r e a t e t e x t ( x , y , t e x t=s t r (
node ) , f o n t =(” A r i a l ” , 1 2 , ” b o l d ” ) )
# Draw e d g e s
f o r s r c , n e i g h b o r s in s e l f . graph . a d j a c e n c y l i s t .
items () :
f o r d e s t in n e i g h b o r s :
x1 , y1 = n o d e p o s i t i o n s [ s r c ]
x2 , y2 = n o d e p o s i t i o n s [ d e s t ]
s e l f . v i s u a l c a n v a s . c r e a t e l i n e ( x1 , y1 , x2 ,
y2 , arrow=” l a s t ” )
32
if name == ” m a i n ” :
r o o t = tk . Tk ( )
app = D a t a S t r u c t u r e V i s u a l i z e r ( r o o t )
r o o t . mainloop ( )
33
Figure 2: The adding of elements
34
Figure 5: Random array
35
Figure 8: Binary tree
36
Figure 11: Graphs visualized
37