├── .gitignore ├── Chapter 1 - Basic Concepts.ipynb ├── Chapter 2 - Arrays.ipynb ├── Chapter 3 - Stacks and Queues.ipynb ├── Chapter 4 - Linked Lists.ipynb ├── Chapter 5 - Trees.ipynb ├── Chapter 6 - Graphs.ipynb ├── Chapter 7 - Sorting.ipynb ├── Chapter 8 - Hashing.ipynb └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *copy*.ipynb 3 | .ipynb_checkpoints 4 | -------------------------------------------------------------------------------- /Chapter 2 - Arrays.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:0cdf200479cb45c126f9773bd9d617dc0324ef8c22b43c0364a14404bd5eb8cb" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "code", 13 | "collapsed": false, 14 | "input": [ 15 | "# Imports\n", 16 | "import numpy\n", 17 | "# For random string generation\n", 18 | "from string import ascii_letters\n", 19 | "from random import choice\n", 20 | "from time import time # For analysis of the running time\n", 21 | "import matplotlib.pyplot as plt # to plot the run time analysis" 22 | ], 23 | "language": "python", 24 | "metadata": {}, 25 | "outputs": [], 26 | "prompt_number": 1 27 | }, 28 | { 29 | "cell_type": "heading", 30 | "level": 1, 31 | "metadata": {}, 32 | "source": [ 33 | "CHAPTER 2 - ARRAYS" 34 | ] 35 | }, 36 | { 37 | "cell_type": "heading", 38 | "level": 2, 39 | "metadata": {}, 40 | "source": [ 41 | "PROGRAM 2.1, PAGE 75" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "collapsed": false, 47 | "input": [ 48 | "# Definition of Class Rectangle\n", 49 | "\n", 50 | "class Rectangle:\n", 51 | " def __init__(self,x=None,y=None,h=None,w=None):\n", 52 | " '''Constructor of Rectangle'''\n", 53 | " pass\n", 54 | " def __del__(self):\n", 55 | " '''Destructor of Rectangle'''\n", 56 | " pass\n", 57 | " def get_height(self):\n", 58 | " '''returns Height of rectangle'''\n", 59 | " pass\n", 60 | " def get_width(self):\n", 61 | " '''Returns Width of rectangle'''\n", 62 | " pass\n", 63 | " _x_low = None\n", 64 | " _y_low = None\n", 65 | " _height = None\n", 66 | " _width = None\n", 67 | " # In python attributes starting with an underscore are conventionaly understood to be private attributes." 68 | ], 69 | "language": "python", 70 | "metadata": {}, 71 | "outputs": [], 72 | "prompt_number": 2 73 | }, 74 | { 75 | "cell_type": "heading", 76 | "level": 2, 77 | "metadata": {}, 78 | "source": [ 79 | "PROGRAM 2.2, PAGE 76" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "collapsed": false, 85 | "input": [ 86 | "# Implementations of Operations on Rectangle\n", 87 | "def get_height(self):\n", 88 | " return self._height\n", 89 | "def get_width(self):\n", 90 | " return self._width\n", 91 | "\n", 92 | "Rectangle.get_height = get_height\n", 93 | "Rectangle.get_width = get_width\n", 94 | "\n", 95 | "# This is the closest C++ equivalent to defining class methods outside the class. [ using class::member() {} ]\n", 96 | "\n", 97 | "# Though THIS IS NOT AN ACCEPTED PRACTICE IN PYTHON. This would be an workaround to define \n", 98 | "# the member functions outside of the class definition as and when the functionality of the method in defined\n", 99 | "# in the text" 100 | ], 101 | "language": "python", 102 | "metadata": {}, 103 | "outputs": [], 104 | "prompt_number": 3 105 | }, 106 | { 107 | "cell_type": "heading", 108 | "level": 2, 109 | "metadata": {}, 110 | "source": [ 111 | "PROGRAM 2.4, PAGE 78" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "collapsed": false, 117 | "input": [ 118 | "# Definition Of Constructor For Rectangle\n", 119 | "\n", 120 | "def constructor_for_Rectangle_class(self,x=None,y=None,h=None,w=None):\n", 121 | " '''Constructor for class Rectangle'''\n", 122 | " self._x_low = x\n", 123 | " self._y_low = x\n", 124 | " self._height = h\n", 125 | " self._width = w\n", 126 | "\n", 127 | "# __init__ method is invoked in python when a member of the class is instantiated\n", 128 | "Rectangle.__init__ = constructor_for_Rectangle_class" 129 | ], 130 | "language": "python", 131 | "metadata": {}, 132 | "outputs": [], 133 | "prompt_number": 4 134 | }, 135 | { 136 | "cell_type": "heading", 137 | "level": 2, 138 | "metadata": {}, 139 | "source": [ 140 | "PROGRAM 2.3, PAGE 77" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "collapsed": false, 146 | "input": [ 147 | "r = Rectangle(1,2,5,6)\n", 148 | "s = Rectangle(1,2,8,9)\n", 149 | "\n", 150 | "t = s\n", 151 | "\n", 152 | "if ( r.get_height() * r.get_width() ) > ( t.get_height() * t.get_width() ):\n", 153 | " print 'r',\n", 154 | "else:\n", 155 | " print 's',\n", 156 | "\n", 157 | "print 'has the greater area'" 158 | ], 159 | "language": "python", 160 | "metadata": {}, 161 | "outputs": [ 162 | { 163 | "output_type": "stream", 164 | "stream": "stdout", 165 | "text": [ 166 | "s has the greater area\n" 167 | ] 168 | } 169 | ], 170 | "prompt_number": 5 171 | }, 172 | { 173 | "cell_type": "heading", 174 | "level": 2, 175 | "metadata": {}, 176 | "source": [ 177 | "PROGRAM 2.6, PAGE 80" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "collapsed": false, 183 | "input": [ 184 | "s._x_low" 185 | ], 186 | "language": "python", 187 | "metadata": {}, 188 | "outputs": [ 189 | { 190 | "metadata": {}, 191 | "output_type": "pyout", 192 | "prompt_number": 6, 193 | "text": [ 194 | "1" 195 | ] 196 | } 197 | ], 198 | "prompt_number": 6 199 | }, 200 | { 201 | "cell_type": "code", 202 | "collapsed": false, 203 | "input": [ 204 | "# Overloading the equality check operator\n", 205 | "\n", 206 | "# Operator == is specified as a function __eq__(op1,op2)\n", 207 | "\n", 208 | "def __eq__(self,rhs):\n", 209 | " if (self._x_low == rhs._x_low) and (self._y_low == rhs._y_low) and ( self._height == rhs._height ) and ( self._width == rhs._width ) :\n", 210 | " return True\n", 211 | " else:\n", 212 | " return False\n", 213 | " \n", 214 | "# Overriding the default behaviour of == by defining a __eq__ memeber function\n", 215 | "Rectangle.__eq__ = __eq__\n", 216 | "\n", 217 | "# SAMPLE O/P\n", 218 | "print r == s" 219 | ], 220 | "language": "python", 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "output_type": "stream", 225 | "stream": "stdout", 226 | "text": [ 227 | "False\n" 228 | ] 229 | } 230 | ], 231 | "prompt_number": 7 232 | }, 233 | { 234 | "cell_type": "heading", 235 | "level": 2, 236 | "metadata": {}, 237 | "source": [ 238 | "PROGRAM 2.7, PAGE 80" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "collapsed": false, 244 | "input": [ 245 | "# Overloading the right shift operator <<\n", 246 | "import operator, sys, io, IPython\n", 247 | "\n", 248 | "\n", 249 | "class MyStdout(IPython.kernel.zmq.iostream.OutStream):\n", 250 | " \"\"\"\n", 251 | " MyStdout class inherits from the OutStream of IPython kernel.\n", 252 | " This is done to simulate the C++ OutStream \"cout\"\n", 253 | " \"\"\" \n", 254 | " def __init__(self):\n", 255 | " self.__dict__ = sys.stdout.__dict__.copy()\n", 256 | " # All elements of sys.stdout are copied to the MyStdout [inherited class]\n", 257 | "\n", 258 | " def __lshift__(self,rect_instance):\n", 259 | " # lshift ( << ) operator is overloaded to allow printing of Rectangle\n", 260 | " \n", 261 | " if isinstance(rect_instance, Rectangle): \n", 262 | " self.write('Position is:'+str(rect_instance._x_low)+' '+str(rect_instance._y_low))\n", 263 | " self.write('\\nHeight is: '+str(rect_instance._height))\n", 264 | " self.write('\\nWidth is: '+str(rect_instance._width))\n", 265 | " else:\n", 266 | " self.write(rect_instance)\n", 267 | " \n", 268 | "# A new MyStdout Class inheriting the elements of stdout [OutStream Object Class] is created with the \n", 269 | "# overloaded operator function __lshift__. \n", 270 | "\n", 271 | "sys.stdout = MyStdout()\n", 272 | "\n", 273 | "#an instance of MyStdout is then assigned to sys.stdout\n", 274 | "\n", 275 | "#Operator << is specified as a function __lshift__() [Equivalent to c++ style 'operator<<'" 276 | ], 277 | "language": "python", 278 | "metadata": {}, 279 | "outputs": [], 280 | "prompt_number": 8 281 | }, 282 | { 283 | "cell_type": "code", 284 | "collapsed": false, 285 | "input": [ 286 | "# C++ Style I/O using << operator overloading in python !\n", 287 | "\n", 288 | "cout = sys.stdout\n", 289 | "endl = '\\n'\n", 290 | "\n", 291 | "cout<= 0 else 0" 368 | ], 369 | "language": "python", 370 | "metadata": {}, 371 | "outputs": [], 372 | "prompt_number": 10 373 | }, 374 | { 375 | "cell_type": "heading", 376 | "level": 2, 377 | "metadata": {}, 378 | "source": [ 379 | "ADT 2.2, PAGE 85" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "collapsed": false, 385 | "input": [ 386 | "# Abstract Data Type GeneralArray\n", 387 | "default_value = 0\n", 388 | "\n", 389 | "class GeneralArray:\n", 390 | " def __init__(self, j, List, init_value = default_value):\n", 391 | " pass\n", 392 | " def retrieve(self,index):\n", 393 | " pass\n", 394 | " def store(self,index,x):\n", 395 | " x = float(x)\n", 396 | " pass " 397 | ], 398 | "language": "python", 399 | "metadata": {}, 400 | "outputs": [], 401 | "prompt_number": 11 402 | }, 403 | { 404 | "cell_type": "heading", 405 | "level": 2, 406 | "metadata": {}, 407 | "source": [ 408 | "ADT 2.3, PAGE 88   &   PROGRAM 2.8, PAGE 91   &   PROGRAM 2.9, PAGE 92" 409 | ] 410 | }, 411 | { 412 | "cell_type": "code", 413 | "collapsed": false, 414 | "input": [ 415 | "# Adding two Polynomials\n", 416 | "\n", 417 | "# Declaring and Defining Prerequisites Term and Polynomial\n", 418 | "\n", 419 | "# Class Terms to define a single term of a polynomial.\n", 420 | "\n", 421 | "# Refer Page 90\n", 422 | "\n", 423 | "# NOTE : This is just to illustrate how a Polynomial data type can be constructed in Python\n", 424 | "# For all practical purposes, use sympy, an efficient symbolic math and Computer Algebra System library in Python\n", 425 | "\n", 426 | "class Term:\n", 427 | " def __init__(self):\n", 428 | " self.coef = 0.0\n", 429 | " self.exp = 0\n", 430 | "\n", 431 | " \n", 432 | "# Abstract data type Polynomial - Representation 3 [ Refer Page 89 ]\n", 433 | "class Polynomial:\n", 434 | " def __init__(self,d=0):\n", 435 | " self.degree = d\n", 436 | " self.coeff = [0.0]\n", 437 | " self.term_array = []\n", 438 | " self.terms = 0\n", 439 | " pass\n", 440 | "\n", 441 | " # Method new_term to add a new term to the polynomial [ Refer Page 92 ]\n", 442 | "\n", 443 | " def new_term(self,coef,exp):\n", 444 | " NewTrm = Term()\n", 445 | " NewTrm.coef = coef\n", 446 | " NewTrm.exp = exp\n", 447 | " pos = 0\n", 448 | " # Compute the position of the new term ( sorted by exponents )\n", 449 | " while ( pos < self.terms ) and ( self.term_array[pos].exp < NewTrm.exp ):\n", 450 | " pos += 1\n", 451 | " \n", 452 | " # If there is already a term with the given exponent, add the coefficient\n", 453 | " if ( pos < self.terms ) and ( self.term_array[pos].exp == NewTrm.exp ):\n", 454 | " self.term_array[pos].coef += coef\n", 455 | " return\n", 456 | " \n", 457 | " self.term_array.insert(pos, NewTrm)\n", 458 | " self.terms += 1\n", 459 | " self.degree = max(self.degree, exp) \n", 460 | " \n", 461 | " # Method Add to add two polynomials\n", 462 | "\n", 463 | " def add(self,Polynomial_b):\n", 464 | " if isinstance(Polynomial_b, Polynomial):\n", 465 | " c = Polynomial()\n", 466 | " a_pos = 0\n", 467 | " b_pos = 0\n", 468 | " while ( a_pos < self.terms ) and ( b_pos < Polynomial_b.terms ) :\n", 469 | " # Similar Power terms\n", 470 | " if self.term_array[a_pos].exp == Polynomial_b.term_array[b_pos].exp :\n", 471 | " t = float(term_array[a_pos].coef) + float(Polynomial_b.term_array[b_pos].coef)\n", 472 | " if t != 0 :\n", 473 | " c.new_term(t, self.term_array[a_pos].exp)\n", 474 | " a_pos += 1\n", 475 | " b_pos += 1\n", 476 | " \n", 477 | " # Dissimilar Power terms\n", 478 | " elif self.term_array[a_pos].exp < Polynomial_b.term_array[b_pos].exp:\n", 479 | " c.new_term(Polynomial_b.term_array[b_pos].coef, Polynomial_b.term_array[b_pos].exp)\n", 480 | " b_pos += 1\n", 481 | " else:\n", 482 | " c.new_term(self.term_array[a_pos].coef, self.term_array[a_pos].exp)\n", 483 | " c.display()\n", 484 | " a_pos += 1\n", 485 | " \n", 486 | " # Leftover terms of a\n", 487 | " while a_pos < self.terms:\n", 488 | " c.new_term(self.term_array[a_pos].coef, self.term_array[a_pos].exp)\n", 489 | " a_pos += 1\n", 490 | " \n", 491 | " # Leftover terms of b\n", 492 | " while b_pos < Polynomial_b.terms:\n", 493 | " c.new_term(Polynomial_b.term_array[b_pos].coef, Polynomial_b.term_array[b_pos].exp)\n", 494 | " b_pos += 1\n", 495 | " \n", 496 | " # C contains the resulting polynomial\n", 497 | " return c\n", 498 | " else:\n", 499 | " raise(TypeError)\n", 500 | "\n", 501 | " # Overloading Operator + to do the same funcition as Polynomial_a.add(Polynomial_b)\n", 502 | "\n", 503 | " def __add__(self,Polynomial_b):\n", 504 | " return Polynomial.add(self,Polynomial_b)\n", 505 | " \n", 506 | " def display(self):\n", 507 | " \"\"\"Display the polynomial using the latex display in IPython notebook. \n", 508 | " Note that this works only inside IPython notebook\"\"\"\n", 509 | " \n", 510 | " from IPython.display import display, Math, Latex\n", 511 | " \n", 512 | " latex = \"{\"\n", 513 | " \n", 514 | " for t in reversed(self.term_array):\n", 515 | " if t.coef >= 0 and latex != \"{\" :\n", 516 | " latex += \" + \"\n", 517 | " \n", 518 | " if t.exp == 0:\n", 519 | " latex += \" {coef} \".format(coef=t.coef)\n", 520 | " elif t.exp == 1:\n", 521 | " latex += \" {coef}x \".format(coef=t.coef)\n", 522 | " else:\n", 523 | " latex += \" {coef}x^{exp} \".format(coef=t.coef, exp=t.exp)\n", 524 | " \n", 525 | " latex += \"}\"\n", 526 | " \n", 527 | " display(Math(latex))" 528 | ], 529 | "language": "python", 530 | "metadata": {}, 531 | "outputs": [], 532 | "prompt_number": 12 533 | }, 534 | { 535 | "cell_type": "markdown", 536 | "metadata": {}, 537 | "source": [ 538 | "### Example Usage\n", 539 | "$f = {2.5x^2 - 3x + 5}$
\n", 540 | "$g = {3.2x^3 - 4x}$

\n", 541 | "$h = f + g$

\n", 542 | "$h = {3.2x^3 + 2.5x^2 - 7x + 5}$
" 543 | ] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "collapsed": false, 548 | "input": [ 549 | "# Example Usage :\n", 550 | "\n", 551 | "f = Polynomial()\n", 552 | "f.new_term(2.5, 2); f.new_term(-3, 1); f.new_term(5,0)\n", 553 | "f .display()" 554 | ], 555 | "language": "python", 556 | "metadata": {}, 557 | "outputs": [ 558 | { 559 | "latex": [ 560 | "$${ 2.5x^2 -3x + 5 }$$" 561 | ], 562 | "metadata": {}, 563 | "output_type": "display_data", 564 | "text": [ 565 | "" 566 | ] 567 | } 568 | ], 569 | "prompt_number": 13 570 | }, 571 | { 572 | "cell_type": "code", 573 | "collapsed": false, 574 | "input": [ 575 | "g = Polynomial()\n", 576 | "g.new_term(3.2, 3); g.new_term(-4, 1);\n", 577 | "g.display()" 578 | ], 579 | "language": "python", 580 | "metadata": {}, 581 | "outputs": [ 582 | { 583 | "latex": [ 584 | "$${ 3.2x^3 -4x }$$" 585 | ], 586 | "metadata": {}, 587 | "output_type": "display_data", 588 | "text": [ 589 | "" 590 | ] 591 | } 592 | ], 593 | "prompt_number": 14 594 | }, 595 | { 596 | "cell_type": "code", 597 | "collapsed": false, 598 | "input": [ 599 | "h = f + g\n", 600 | "h.display()" 601 | ], 602 | "language": "python", 603 | "metadata": {}, 604 | "outputs": [ 605 | { 606 | "latex": [ 607 | "$${ 3.2x^3 + 2.5x^2 -7x + 5 }$$" 608 | ], 609 | "metadata": {}, 610 | "output_type": "display_data", 611 | "text": [ 612 | "" 613 | ] 614 | } 615 | ], 616 | "prompt_number": 15 617 | }, 618 | { 619 | "cell_type": "heading", 620 | "level": 2, 621 | "metadata": {}, 622 | "source": [ 623 | "ADT 2.4, PAGE 97 " 624 | ] 625 | }, 626 | { 627 | "cell_type": "code", 628 | "collapsed": false, 629 | "input": [ 630 | "# Abstract Data Type SparseMatrix\n", 631 | "\n", 632 | "class MatrixTerm(object):\n", 633 | " def __init__(self,row=None,col=None,value=None):\n", 634 | " self.row = row\n", 635 | " self.col = col\n", 636 | " self.value = value\n", 637 | " def set_value(self, row=None, col=None, value=None):\n", 638 | " if row is not None:\n", 639 | " self.row = row\n", 640 | " if col is not None:\n", 641 | " self.col = col\n", 642 | " if value is not None:\n", 643 | " self.value = value \n", 644 | "\n", 645 | "class SparseMatrix(object):\n", 646 | " '''A Set of triples , where row and column are non-negative integers\n", 647 | " and form a unique combination; value is also an integer '''\n", 648 | " def __init__(self, rows, cols, terms):\n", 649 | " '''The constructor function creates a SparseMatrix with\n", 650 | " r rows c columns and a capacity of t nonzero terms.'''\n", 651 | " self._rows = rows # No of rows\n", 652 | " self._cols = cols # No of cols\n", 653 | " self._terms = terms # No of terms\n", 654 | " # self._capacity = t # This term is not used since in python lists can be extended\n", 655 | " self._sm_array = [ MatrixTerm() for i in range(terms) ] # List which stores the triplet\n", 656 | " \n", 657 | " def Transpose(self):\n", 658 | " '''Returns the transpose of the SparseMatrix'''\n", 659 | " # self is comparable with *this in c++\n", 660 | " pass\n", 661 | " \n", 662 | " def add(self, b):\n", 663 | " '''Performs matrix addition of self with the b SpareMatrix'''\n", 664 | " pass\n", 665 | " \n", 666 | " def Multiply(self, b):\n", 667 | " '''\n", 668 | " If the number of columns in self equals the number of rows in b, then returns the\n", 669 | " multiplication matrix of self and b.\n", 670 | " If not an exception is thrown\n", 671 | " '''\n", 672 | " pass" 673 | ], 674 | "language": "python", 675 | "metadata": {}, 676 | "outputs": [], 677 | "prompt_number": 16 678 | }, 679 | { 680 | "cell_type": "heading", 681 | "level": 2, 682 | "metadata": {}, 683 | "source": [ 684 | "PROGRAM 2.10, PAGE 100" 685 | ] 686 | }, 687 | { 688 | "cell_type": "code", 689 | "collapsed": false, 690 | "input": [ 691 | "# Transposing a Matrix\n", 692 | "# Runs in O(terms*cols)\n", 693 | "# In comparison, the naive method runs in O(rows*cols)\n", 694 | "\n", 695 | "def transpose(self):\n", 696 | " '''Returns the transpose of self'''\n", 697 | " \n", 698 | " tran = SparseMatrix(self._cols, self._rows, self._terms)\n", 699 | " \n", 700 | " if(self._terms < 0):\n", 701 | " # If self is a zero matrix\n", 702 | " return tran\n", 703 | " \n", 704 | " # If self is a Non Zero matrix\n", 705 | " \n", 706 | " tran_term_index = 0\n", 707 | " \n", 708 | " for c in range(self._cols):\n", 709 | " for i in range(self._terms):\n", 710 | " # Find and move terms in column c\n", 711 | " if self._sm_array[i].col == c:\n", 712 | " # Add the i-th term with row number and col number interchanged to the tran matrix\n", 713 | " tran._sm_array[tran_term_index].set_value(row = c, \n", 714 | " col = self._sm_array[i].row,\n", 715 | " value = self._sm_array[i].value\n", 716 | " )\n", 717 | " tran_term_index += 1\n", 718 | " return tran\n", 719 | "\n", 720 | "SparseMatrix.transpose = transpose" 721 | ], 722 | "language": "python", 723 | "metadata": {}, 724 | "outputs": [], 725 | "prompt_number": 17 726 | }, 727 | { 728 | "cell_type": "heading", 729 | "level": 2, 730 | "metadata": {}, 731 | "source": [ 732 | "PROGRAM 2.11, PAGE 102" 733 | ] 734 | }, 735 | { 736 | "cell_type": "code", 737 | "collapsed": false, 738 | "input": [ 739 | "# A faster method for transposing of Sparse Matrices\n", 740 | "# Runs in O(terms + cols)\n", 741 | "\n", 742 | "def fast_transpose(self):\n", 743 | " \n", 744 | " tran = SparseMatrix(self._cols, self._rows, self._terms)\n", 745 | " \n", 746 | " if self._terms>0:\n", 747 | " cols = self._cols\n", 748 | " terms = self._terms\n", 749 | " sm_array = self._sm_array\n", 750 | " \n", 751 | " # No. of terms in the i-th column => row_size[i] => no of terms in the i-th row of transpose\n", 752 | " row_size = [0]*cols\n", 753 | " \n", 754 | " # Starting index of the sm_array for row i of tran array => row_start[i]\n", 755 | " row_start = [0]*cols\n", 756 | " \n", 757 | " for i in range(terms):\n", 758 | " row_size[sm_array[i].col] += 1\n", 759 | " \n", 760 | " # Based on the no. of terms in the previous row the row start index table can\n", 761 | " # be computed. This helps in speeding up the transpose method.\n", 762 | " for i in range(1,cols):\n", 763 | " row_start[i] = row_start[i-1] + row_size[i-1]\n", 764 | " \n", 765 | " for i in range(terms):\n", 766 | " j = row_start[sm_array[i].col]\n", 767 | " tran._sm_array[j].row = sm_array[i].col\n", 768 | " tran._sm_array[j].col = sm_array[i].row\n", 769 | " tran._sm_array[j].value = sm_array[i].value\n", 770 | " row_start[sm_array[i].col] += 1\n", 771 | " \n", 772 | " return tran\n", 773 | "\n", 774 | "SparseMatrix.fast_transpose = fast_transpose" 775 | ], 776 | "language": "python", 777 | "metadata": {}, 778 | "outputs": [], 779 | "prompt_number": 18 780 | }, 781 | { 782 | "cell_type": "code", 783 | "collapsed": false, 784 | "input": [ 785 | "def get_matrix(self,array):\n", 786 | " \"\"\"\n", 787 | " Stores the triplets in the array to self\n", 788 | " \"\"\"\n", 789 | " try:\n", 790 | " for i in range(len(array)):\n", 791 | " tupl = array[i]\n", 792 | " a._sm_array[i] = MatrixTerm(tupl[0],tupl[1],tupl[2])\n", 793 | " except Exception,e:\n", 794 | " pass\n", 795 | " \n", 796 | "def print_matrix(self):\n", 797 | " bmat = numpy.zeros((self._rows,self._cols))\n", 798 | " for term in self._sm_array:\n", 799 | " try:\n", 800 | " bmat[term.row][term.col] = term.value\n", 801 | " except Exception, e:\n", 802 | " pass\n", 803 | " print bmat\n", 804 | "\n", 805 | "# Helper methods to input an array of triplets and to print the sparse matrix\n", 806 | "SparseMatrix.get_matrix = get_matrix\n", 807 | "SparseMatrix.print_matrix = print_matrix\n", 808 | "\n", 809 | "a = SparseMatrix(6,6,8)\n", 810 | "get_matrix(a,[(0,0,-15),(0,3,12),(0,5,-5),(1,1,1),(1,2,13),(2,3,-16),(4,0,9),(5,2,12)])\n", 811 | "print 'Matrix a\\n'\n", 812 | "print_matrix(a)" 813 | ], 814 | "language": "python", 815 | "metadata": {}, 816 | "outputs": [ 817 | { 818 | "output_type": "stream", 819 | "stream": "stdout", 820 | "text": [ 821 | "Matrix a\n", 822 | "\n", 823 | "[[-15. 0. 0. 12. 0. -5.]\n", 824 | " [ 0. 1. 13. 0. 0. 0.]\n", 825 | " [ 0. 0. 0. -16. 0. 0.]\n", 826 | " [ 0. 0. 0. 0. 0. 0.]\n", 827 | " [ 9. 0. 0. 0. 0. 0.]\n", 828 | " [ 0. 0. 12. 0. 0. 0.]]\n" 829 | ] 830 | } 831 | ], 832 | "prompt_number": 19 833 | }, 834 | { 835 | "cell_type": "code", 836 | "collapsed": false, 837 | "input": [ 838 | "# Technically timeit should be run on different sized / valued inputs but here the same matrix a\n", 839 | "# is transposed repetitively instead to avoid complexity of generating a random sparse matrix\n", 840 | "\n", 841 | "%timeit a.transpose()\n", 842 | "tra = a.transpose()\n", 843 | "print '\\nTranspose of a\\n'\n", 844 | "print_matrix(tra)" 845 | ], 846 | "language": "python", 847 | "metadata": {}, 848 | "outputs": [ 849 | { 850 | "output_type": "stream", 851 | "stream": "stdout", 852 | "text": [ 853 | "100000 loops, best of 3: 17.8 \u00b5s per loop\n", 854 | "\n", 855 | "Transpose of a\n", 856 | "\n", 857 | "[[-15. 0. 0. 0. 9. 0.]\n", 858 | " [ 0. 1. 0. 0. 0. 0.]\n", 859 | " [ 0. 13. 0. 0. 0. 12.]\n", 860 | " [ 12. 0. -16. 0. 0. 0.]\n", 861 | " [ 0. 0. 0. 0. 0. 0.]\n", 862 | " [ -5. 0. 0. 0. 0. 0.]]\n" 863 | ] 864 | } 865 | ], 866 | "prompt_number": 20 867 | }, 868 | { 869 | "cell_type": "code", 870 | "collapsed": false, 871 | "input": [ 872 | "%timeit a.fast_transpose()\n", 873 | "tra = a.fast_transpose()\n", 874 | "print '\\nFast Transpose of a\\n'\n", 875 | "print_matrix(tra)" 876 | ], 877 | "language": "python", 878 | "metadata": {}, 879 | "outputs": [ 880 | { 881 | "output_type": "stream", 882 | "stream": "stdout", 883 | "text": [ 884 | "100000 loops, best of 3: 13.8 \u00b5s per loop\n", 885 | "\n", 886 | "Fast Transpose of a\n", 887 | "\n", 888 | "[[-15. 0. 0. 0. 9. 0.]\n", 889 | " [ 0. 1. 0. 0. 0. 0.]\n", 890 | " [ 0. 13. 0. 0. 0. 12.]\n", 891 | " [ 12. 0. -16. 0. 0. 0.]\n", 892 | " [ 0. 0. 0. 0. 0. 0.]\n", 893 | " [ -5. 0. 0. 0. 0. 0.]]\n" 894 | ] 895 | } 896 | ], 897 | "prompt_number": 21 898 | }, 899 | { 900 | "cell_type": "code", 901 | "collapsed": false, 902 | "input": [ 903 | "# Note that the sm_array has all the triplets ordered by row number.\n", 904 | "print \"Row\\tCol\\tValue\"\n", 905 | "print \"=======================\"\n", 906 | "for t in tra._sm_array:\n", 907 | " print \"%d\\t%d\\t%d\"%(t.row, t.col, t.value)" 908 | ], 909 | "language": "python", 910 | "metadata": {}, 911 | "outputs": [ 912 | { 913 | "output_type": "stream", 914 | "stream": "stdout", 915 | "text": [ 916 | "Row\tCol\tValue\n", 917 | "=======================\n", 918 | "0\t0\t-15\n", 919 | "0\t4\t9\n", 920 | "1\t1\t1\n", 921 | "2\t1\t13\n", 922 | "2\t5\t12\n", 923 | "3\t0\t12\n", 924 | "3\t2\t-16\n", 925 | "5\t0\t-5\n" 926 | ] 927 | } 928 | ], 929 | "prompt_number": 22 930 | }, 931 | { 932 | "cell_type": "heading", 933 | "level": 2, 934 | "metadata": {}, 935 | "source": [ 936 | "PROGRAM 2.12, PAGE 103" 937 | ] 938 | }, 939 | { 940 | "cell_type": "code", 941 | "collapsed": false, 942 | "input": [ 943 | "# Storing a Matrix Term\n", 944 | "\n", 945 | "def add_term(self,val,r,c):\n", 946 | " # If sum != 0, then it is stored along with r and c as last term in self\n", 947 | " if val != 0:\n", 948 | " # Compute the index where the new Term must be inserted into the \n", 949 | " # sm_array which is ordered by row no\n", 950 | " \n", 951 | " i = 0\n", 952 | " while i < self._terms:\n", 953 | " if self._sm_array[i].row > r:\n", 954 | " break\n", 955 | " i += 1\n", 956 | " \n", 957 | " self._sm_array.insert(i, MatrixTerm(row = r, col = c, value = val))\n", 958 | " self._terms += 1\n", 959 | " \n", 960 | "SparseMatrix.add_term = add_term" 961 | ], 962 | "language": "python", 963 | "metadata": {}, 964 | "outputs": [], 965 | "prompt_number": 23 966 | }, 967 | { 968 | "cell_type": "heading", 969 | "level": 2, 970 | "metadata": {}, 971 | "source": [ 972 | "PROGRAM 2.14, PAGE 104 - 106" 973 | ] 974 | }, 975 | { 976 | "cell_type": "code", 977 | "collapsed": false, 978 | "input": [ 979 | "# Multiply Sparse Matrices\n", 980 | "# Works in O(b.cols * a.terms + a.rows * b.terms)\n", 981 | "# This outperforms the standard O(a.rows * a.cols * b.cols) time if b.terms and a.terms are relatively low\n", 982 | "\n", 983 | "def multiply(self,b):\n", 984 | " '''Return the product of sparse matrices self and b'''\n", 985 | " \n", 986 | " if self._cols != b._rows:\n", 987 | " raise Exception('Incompatible Matrices.')\n", 988 | "\n", 989 | " # b transpose makes the sm_array contain terms ordered by columns of b ( rows of b\u1d40 )\n", 990 | " bXpose = b.fast_transpose()\n", 991 | " \n", 992 | " # The product matrix\n", 993 | " product = SparseMatrix(self._rows, b._cols, 0)\n", 994 | " \n", 995 | " curr_row_index = 0\n", 996 | " curr_row_begin = 0\n", 997 | " curr_row_a = self._sm_array[0].row # Current row of a that is being multiplied with the col of b\n", 998 | " \n", 999 | " # Introducing terms to help deal with the end condition\n", 1000 | " self._sm_array.append(MatrixTerm(row = self._rows, col = -1, value = None))\n", 1001 | " bXpose._sm_array.append(MatrixTerm(row = b._cols, col = -1, value = None))\n", 1002 | " \n", 1003 | " Sum = 0\n", 1004 | " \n", 1005 | " while curr_row_index < self._terms :\n", 1006 | " # Generate row current_row_a of d\n", 1007 | " curr_col_b = bXpose._sm_array[0].row\n", 1008 | " curr_col_index = 0\n", 1009 | " \n", 1010 | " while curr_col_index <= b._terms:\n", 1011 | " # Multiply row curr_row_a of self by column curr_col_b of b\n", 1012 | " \n", 1013 | " if self._sm_array[curr_row_index].row != curr_row_a:\n", 1014 | " # End of row curr_row_a\n", 1015 | " \n", 1016 | " # Add the sum to the product matrix at position { curr_row_a, curr_col_b }\n", 1017 | " product.add_term(Sum,curr_row_a,curr_col_b)\n", 1018 | " \n", 1019 | " Sum = 0 # Reset sum to 0\n", 1020 | " \n", 1021 | " # Reset to the beginning of current row ( of a ) for multiplication with next column ( of b )\n", 1022 | " curr_row_index = curr_row_begin\n", 1023 | " \n", 1024 | " # Advance to next column ( of b )\n", 1025 | " while bXpose._sm_array[curr_col_index].row == curr_col_b:\n", 1026 | " curr_col_index += 1\n", 1027 | " \n", 1028 | " # Note that in Sparse Matrix the terms are arranged in rows\n", 1029 | " # bXpose's terms are arranged in columns of b ( or rows of bXpose )\n", 1030 | " curr_col_b = bXpose._sm_array[curr_col_index].row\n", 1031 | " \n", 1032 | " elif bXpose._sm_array[curr_col_index].row != curr_col_b :\n", 1033 | " # End of column curr_col_b of b\n", 1034 | " \n", 1035 | " # Add the sum to the product matrix at position { curr_row_a, curr_col_b }\n", 1036 | " product.add_term(Sum,curr_row_a,curr_col_b)\n", 1037 | " \n", 1038 | " Sum = 0 # Reset sum to 0\n", 1039 | " \n", 1040 | " # Reset to the beginning of current row ( of a ) for multiplication with next column ( of b )\n", 1041 | " curr_row_index = curr_row_begin\n", 1042 | " \n", 1043 | " # Advance to the next column in b \n", 1044 | " # ( note that bXpose._sm_array[curr_col_index].row points to the next column already )\n", 1045 | " curr_col_b = bXpose._sm_array[curr_col_index].row\n", 1046 | " \n", 1047 | " elif self._sm_array[curr_row_index].col < bXpose._sm_array[curr_col_index].col :\n", 1048 | " curr_row_index += 1 # Advance to the next term in row\n", 1049 | " \n", 1050 | " # FOLLOWING EXPLANATION DIAGRAMS NOT IN TEXTBOOK\n", 1051 | " #\n", 1052 | " # ( If the following diagrams appear in two lines shrink your page size to below 100% )\n", 1053 | " #\n", 1054 | " # In the row curr_row_a, if the current column of the current term is \n", 1055 | " # same as the current row of b ( col of bXpose ) in the curr_col_b column\n", 1056 | " # multiply the terms and add to the Sum\n", 1057 | " #\n", 1058 | " #\n", 1059 | " # a b bXpose product\n", 1060 | " # \n", 1061 | " # . . 0 . . . . 0 . . 0 . . . . .\n", 1062 | " # 0 x . 0 \u25c0\u2015\u2015 curr_row_a . 0 0 . . 0 . 0 . . x . \u25c0\u2015\u2015 Result row\n", 1063 | " # . 0 . . 0 . . . . 0 . x \u25c0\u2500\u2510 . . . .\n", 1064 | " # 0 . 0 . . 0 x . 0 . . . \u2502 . . . . \n", 1065 | " # \u25b2 \u2502 \u25b2\n", 1066 | " # \u2502 curr_col_b \u2502 \n", 1067 | " # curr_col_b Result col\n", 1068 | " # \n", 1069 | " # in a : x = a._sm_matrix[curr_row_index]\n", 1070 | " # in b : x = b._sm_matrix[curr_col_index]\n", 1071 | " # in product : x is the new term to be added for which the Sum is being computed\n", 1072 | " #\n", 1073 | " \n", 1074 | " elif self._sm_array[curr_row_index].col == bXpose._sm_array[curr_col_index].col :\n", 1075 | " # Add to sum\n", 1076 | " Sum += self._sm_array[curr_row_index].value * bXpose._sm_array[curr_col_index].value\n", 1077 | " curr_row_index += 1\n", 1078 | " curr_col_index += 1\n", 1079 | " \n", 1080 | " else: \n", 1081 | " curr_col_index += 1\n", 1082 | " # Next term in curr_col_b\n", 1083 | " \n", 1084 | " while self._sm_array[curr_row_index].row == curr_row_a :\n", 1085 | " # Advance to next row ( of a )\n", 1086 | " curr_row_index += 1\n", 1087 | " \n", 1088 | " curr_row_begin = curr_row_index\n", 1089 | " curr_row_a = self._sm_array[curr_row_index].row\n", 1090 | " \n", 1091 | " # To remove the last terms in a and d since the terms are empty:\n", 1092 | " del product._sm_array[-1]\n", 1093 | " del self._sm_array[-1]\n", 1094 | " del b._sm_array [-1]\n", 1095 | " \n", 1096 | " return product\n", 1097 | "\n", 1098 | "SparseMatrix.multiply = multiply" 1099 | ], 1100 | "language": "python", 1101 | "metadata": {}, 1102 | "outputs": [], 1103 | "prompt_number": 24 1104 | }, 1105 | { 1106 | "cell_type": "code", 1107 | "collapsed": false, 1108 | "input": [ 1109 | "mult = a.multiply(tra)\n", 1110 | "print 'Matrix a is \\n'\n", 1111 | "print_matrix(a)\n", 1112 | "print \"\\nMatrix a . a' is :\\n\"\n", 1113 | "print_matrix(mult)" 1114 | ], 1115 | "language": "python", 1116 | "metadata": {}, 1117 | "outputs": [ 1118 | { 1119 | "output_type": "stream", 1120 | "stream": "stdout", 1121 | "text": [ 1122 | "Matrix a is \n", 1123 | "\n", 1124 | "[[-15. 0. 0. 12. 0. -5.]\n", 1125 | " [ 0. 1. 13. 0. 0. 0.]\n", 1126 | " [ 0. 0. 0. -16. 0. 0.]\n", 1127 | " [ 0. 0. 0. 0. 0. 0.]\n", 1128 | " [ 9. 0. 0. 0. 0. 0.]\n", 1129 | " [ 0. 0. 12. 0. 0. 0.]]\n", 1130 | "\n", 1131 | "Matrix a . a' is :\n", 1132 | "\n", 1133 | "[[ 394. 0. -192. 0. -135. 0.]\n", 1134 | " [ 0. 170. 0. 0. 0. 156.]\n", 1135 | " [-192. 0. 256. 0. 0. 0.]\n", 1136 | " [ 0. 0. 0. 0. 0. 0.]\n", 1137 | " [-135. 0. 0. 0. 81. 0.]\n", 1138 | " [ 0. 156. 0. 0. 0. 0.]]\n" 1139 | ] 1140 | } 1141 | ], 1142 | "prompt_number": 25 1143 | }, 1144 | { 1145 | "cell_type": "heading", 1146 | "level": 2, 1147 | "metadata": {}, 1148 | "source": [ 1149 | "ADT 2.5, PAGE 114" 1150 | ] 1151 | }, 1152 | { 1153 | "cell_type": "code", 1154 | "collapsed": false, 1155 | "input": [ 1156 | "# Abstract Datatype String\n", 1157 | "class String(object):\n", 1158 | " def __init__(self,init):\n", 1159 | " # Constructor that initializes self to string init of length of m\n", 1160 | " self._str = init\n", 1161 | " self._length = len(init)\n", 1162 | " self.failure_function()\n", 1163 | " \n", 1164 | " def __eq__(self,t):\n", 1165 | " # overloading == operators\n", 1166 | " return self._str == t._str\n", 1167 | " \n", 1168 | " def __not__(self):\n", 1169 | " if self._length <= 0:\n", 1170 | " print True\n", 1171 | " else:\n", 1172 | " print False\n", 1173 | " \n", 1174 | " def length(self):\n", 1175 | " return self._length\n", 1176 | " \n", 1177 | " def concat(self,left):\n", 1178 | " self._str += t\n", 1179 | " return self\n", 1180 | " \n", 1181 | " def substr(self,i,j):\n", 1182 | " \"\"\"\n", 1183 | " Return a substring whose starting index is i and length is j\n", 1184 | " \"\"\"\n", 1185 | " try:\n", 1186 | " substr = self._str[i:i+j]\n", 1187 | " return substr\n", 1188 | " \n", 1189 | " except IndexError:\n", 1190 | " print 'Invalid index / length to get Substring'\n", 1191 | " \n", 1192 | " def find(self, pat):\n", 1193 | " '''Returns an index i such that pat matches the substring of self that begins at position of i\n", 1194 | " Returns -1 if pat is either empty or not a substring'''\n", 1195 | " pass " 1196 | ], 1197 | "language": "python", 1198 | "metadata": {}, 1199 | "outputs": [], 1200 | "prompt_number": 26 1201 | }, 1202 | { 1203 | "cell_type": "heading", 1204 | "level": 2, 1205 | "metadata": {}, 1206 | "source": [ 1207 | "PROGRAM 2.15, PAGE 115" 1208 | ] 1209 | }, 1210 | { 1211 | "cell_type": "code", 1212 | "collapsed": false, 1213 | "input": [ 1214 | "# Exhaustive Pattern Matching\n", 1215 | "\n", 1216 | "def find(self,pat):\n", 1217 | " '''Return -1 if pat does not occur in self\n", 1218 | " otherwise return the first position in self, where pat begins'''\n", 1219 | " \n", 1220 | " for start in range(self.length()-pat.length()+1) :\n", 1221 | " # Check for match beginning at str[start]\n", 1222 | " for j in range(pat.length()) :\n", 1223 | " # Character by character checking\n", 1224 | " \n", 1225 | " if self._str[start + j] != pat._str[j]:\n", 1226 | " break\n", 1227 | " \n", 1228 | " if j == pat.length()-1:\n", 1229 | " # Match found\n", 1230 | " return start\n", 1231 | " \n", 1232 | " # Pat is empty or does not occur in string\n", 1233 | " return -1 \n", 1234 | "\n", 1235 | "# NOTE : The entire program can be implemented using python string function as follows: \n", 1236 | "# self._str.find(pat)\n", 1237 | "\n", 1238 | "String.find = find" 1239 | ], 1240 | "language": "python", 1241 | "metadata": {}, 1242 | "outputs": [], 1243 | "prompt_number": 27 1244 | }, 1245 | { 1246 | "cell_type": "heading", 1247 | "level": 2, 1248 | "metadata": {}, 1249 | "source": [ 1250 | "PROGRAM 2.16, PAGE 117" 1251 | ] 1252 | }, 1253 | { 1254 | "cell_type": "code", 1255 | "collapsed": false, 1256 | "input": [ 1257 | "# Faster implementation of the find method using the failure array and failure function to \n", 1258 | "# allow resuming search at partial matches. The failure vector is stored at String.f\n", 1259 | "\n", 1260 | "# Runs in O( LengthP + LengthS )\n", 1261 | "\n", 1262 | "def fast_find(self, pat):\n", 1263 | " posP = 0\n", 1264 | " posS = 0\n", 1265 | "\n", 1266 | " lengthP = pat.length()\n", 1267 | " lengthS = self.length()\n", 1268 | " \n", 1269 | " while ( posP < lengthP ) and ( posS < lengthS ):\n", 1270 | " if pat._str[posP] == self._str[posS] :\n", 1271 | " posP += 1\n", 1272 | " posS += 1\n", 1273 | " \n", 1274 | " elif posP == 0:\n", 1275 | " posS += 1\n", 1276 | " \n", 1277 | " else:\n", 1278 | " posP = pat.f[posP - 1] + 1\n", 1279 | " \n", 1280 | " if posP < lengthP :\n", 1281 | " return -1\n", 1282 | " else:\n", 1283 | " return posS-lengthP\n", 1284 | " \n", 1285 | "String.fast_find = fast_find" 1286 | ], 1287 | "language": "python", 1288 | "metadata": {}, 1289 | "outputs": [], 1290 | "prompt_number": 28 1291 | }, 1292 | { 1293 | "cell_type": "heading", 1294 | "level": 2, 1295 | "metadata": {}, 1296 | "source": [ 1297 | "PROGRAM 2.17, PAGE 118" 1298 | ] 1299 | }, 1300 | { 1301 | "cell_type": "code", 1302 | "collapsed": false, 1303 | "input": [ 1304 | "# Computing the failure function\n", 1305 | "\n", 1306 | "def failure_function(self):\n", 1307 | " lengthP = self.length()\n", 1308 | " self.f = [0]*lengthP\n", 1309 | " self.f[0] = -1\n", 1310 | " for j in range(1,lengthP):\n", 1311 | " i = self.f[j-1]\n", 1312 | " while ( self._str[j] != self._str[i+1] ) and ( i >= 0 ):\n", 1313 | " i = self.f[i]\n", 1314 | " if self._str[j] == self._str[i+1]:\n", 1315 | " self.f[j] = i + 1\n", 1316 | " else:\n", 1317 | " self.f[j-1] = -1\n", 1318 | " \n", 1319 | "String.failure_function = failure_function" 1320 | ], 1321 | "language": "python", 1322 | "metadata": {}, 1323 | "outputs": [], 1324 | "prompt_number": 29 1325 | }, 1326 | { 1327 | "cell_type": "code", 1328 | "collapsed": false, 1329 | "input": [ 1330 | "str1 = String('hello world')\n", 1331 | "str2 = String('sdf')\n", 1332 | "print str1.find(str2), str1.fast_find(str2)" 1333 | ], 1334 | "language": "python", 1335 | "metadata": {}, 1336 | "outputs": [ 1337 | { 1338 | "output_type": "stream", 1339 | "stream": "stdout", 1340 | "text": [ 1341 | "-1 -1\n" 1342 | ] 1343 | } 1344 | ], 1345 | "prompt_number": 30 1346 | }, 1347 | { 1348 | "cell_type": "code", 1349 | "collapsed": false, 1350 | "input": [ 1351 | "str2 = String('ell')\n", 1352 | "print str1.find(str2), str1.fast_find(str2)" 1353 | ], 1354 | "language": "python", 1355 | "metadata": {}, 1356 | "outputs": [ 1357 | { 1358 | "output_type": "stream", 1359 | "stream": "stdout", 1360 | "text": [ 1361 | "1 1\n" 1362 | ] 1363 | } 1364 | ], 1365 | "prompt_number": 31 1366 | }, 1367 | { 1368 | "cell_type": "code", 1369 | "collapsed": false, 1370 | "input": [ 1371 | "# Analysing the above two find methods\n", 1372 | "x_axis = range(10, 1000, 50)\n", 1373 | "find_run_time = []\n", 1374 | "fast_find_run_time = []\n", 1375 | "\n", 1376 | "\n", 1377 | "for i in x_axis:\n", 1378 | " string = String(''.join(choice(ascii_letters) for _ in range(i))) # Generates a random string of i chars\n", 1379 | " pattern = String(''.join(choice(ascii_letters) for _ in range(i/2))) # Generates a random pattern string of i chars\n", 1380 | " start = time()\n", 1381 | " for i in range(10):\n", 1382 | " string.find(pattern)\n", 1383 | " find_run_time.append((time() - start) / 10) # Takes average over 10 runs\n", 1384 | " start = time()\n", 1385 | " for i in range(10):\n", 1386 | " string.fast_find(pattern)\n", 1387 | " fast_find_run_time.append((time() - start) / 10)\n", 1388 | " \n", 1389 | "\n", 1390 | "# NOTE: All these are typically failure / worst case run times, \n", 1391 | "# since the probability of a random pattern matching with a random string is very low\n", 1392 | "\n", 1393 | "# Note the quadratic run time of find and linear run time of fast_find\n", 1394 | " \n", 1395 | "%matplotlib inline \n", 1396 | "plt.figure().set_size_inches(10,10)\n", 1397 | "plt.xlabel(\"Size of the input string : n \")\n", 1398 | "plt.ylabel(\"Time in ms for the find operation\")\n", 1399 | "\n", 1400 | "plt.plot(x_axis, find_run_time, marker = \"o\", linestyle = \"--\", c=\"b\", label=\"find\")\n", 1401 | "plt.plot(x_axis, fast_find_run_time, marker = \"o\", linestyle = \"--\", c=\"r\", label=\"fast_find\")\n", 1402 | "plt.legend()\n", 1403 | "plt.show()" 1404 | ], 1405 | "language": "python", 1406 | "metadata": {}, 1407 | "outputs": [ 1408 | { 1409 | "metadata": {}, 1410 | "output_type": "display_data", 1411 | "png": "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\nPfRQBg4cSGVlJR9++GHof1apZuCTJEndKmlpSdpePHMmFBUFr6lTk588dSoUFVHS0JD8Gs3NoWp4\n9NFHGTVqFNdeey1LlixhxIgR/O53v+Pjjz8mFotx/fXXc//99wNw22238cknn/D222/z0UcfMW3a\nNDbeeGNqa2s7XaOurm6D94vH4wwZMoTp06fzySef0L9/f4qKijr1ED755JPsvvvuLFq0iB//+Med\nhom//e1v88UvfpFFixYxZcoUbrvttsiGdQ18kiSpW62lpUnb28aOhfb24NVV4Gtvp7WyMvk1ysp6\nVEt7ezsAhx56KHvuuScAe++9N9/85jeZPXs2AP3792fRokW88sorFBUVMXLkSAYMGLDeNfpqp512\n4rTTTqOoqIiTTz6Zd999lw8++IA333yTp556issuu4x+/foxatQojj766JTdt6cMfJIkqVuV1dXU\nlJd3aptcXs6YxGSGTF0D1j6DN3fuXA477DAGDx7MZpttxrRp01i0aBEAEyZMYOzYsXzzm99k++23\n54ILLqC1tXW9a/TVNttss+b9JptsAsDSpUtZuHAhgwYNYuONN17z/Z122ikl9+wNJ21IkqRurZ5U\nMaW+nuLmZtrKyhhXVdWjGbapuEZH3/72t6murmbmzJn079+fH/zgB2uekyspKeGiiy7ioosu4o03\n3uCoo47ic5/7HKeeempGhlW33XZbFi9ezLJly9YEwTfeeIPi4uK03zsZA58kSQpl9PjxvQ5nqbzG\nakuXLmXQoEH079+fJ598kjvuuIOxY8cC0NjYyBZbbMHw4cMZMGAA/fr1WxO2tt56a+LrTB5JtZ12\n2on99tuPiy++mCuuuIK5c+cyffr0Pi3r0hcO6UqSpJx03XXXcdFFFzFw4EAuu+wyvvGNb6z53nvv\nvccJJ5zApptuyvDhw9esvQcwadIk/vjHP7L55ptz7rnn9vr+607gWN222h133MHcuXPZfPPNufTS\nSznllFN6fa++im4FwOi0R/XApCRJ2a6oqCiyiQWFbEP/3BMBss95zR4+SZKkPGfgkyRJBWvOnDkM\nGDBgvdfAgQOjLi2lHNKVJElrOKQbDYd0JUmS1CcGPkmSpDznOnySJGmNQYMGRbbfayEbNGhQWq9f\niL9Rn+GTJEk5wWf4JEmSFIqBT5IkKc8Z+CRJkvKcgU+SJCnPGfgkSZLynIFPkiQpzxn4JEmS8pyB\n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\n", 1412 | "text": [ 1413 | "" 1414 | ] 1415 | } 1416 | ], 1417 | "prompt_number": 32 1418 | } 1419 | ], 1420 | "metadata": {} 1421 | } 1422 | ] 1423 | } -------------------------------------------------------------------------------- /Chapter 3 - Stacks and Queues.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:44b54fb1fd14d6735dba1b11d6e67b5bb26265f7c730c29e178c4939bd141d0d" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "heading", 13 | "level": 1, 14 | "metadata": {}, 15 | "source": [ 16 | "CHAPTER 3 - STACKS AND QUEUES" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "collapsed": false, 22 | "input": [ 23 | "# Imports:\n", 24 | "import numpy as np # Array manipulations\n", 25 | "import Queue as qu # Queue implementation\n", 26 | "import matplotlib.pyplot as plt # To plot the maze" 27 | ], 28 | "language": "python", 29 | "metadata": {}, 30 | "outputs": [], 31 | "prompt_number": 1 32 | }, 33 | { 34 | "cell_type": "heading", 35 | "level": 2, 36 | "metadata": {}, 37 | "source": [ 38 | "PROGRAM 3.1, PAGE 129" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "collapsed": false, 44 | "input": [ 45 | "# Selection sort\n", 46 | "\n", 47 | "def selection_sort(a,n):\n", 48 | " # Sort a[0] to a[n-1]\n", 49 | " for i in range(n):\n", 50 | " j = i\n", 51 | " # Find smallest integer in a[i] to a[n-1]\n", 52 | " for k in range(i+1,n):\n", 53 | " if a[k] < a[j]:\n", 54 | " j = k\n", 55 | " \n", 56 | " a[i], a[j] = a[j], a[i]" 57 | ], 58 | "language": "python", 59 | "metadata": {}, 60 | "outputs": [], 61 | "prompt_number": 2 62 | }, 63 | { 64 | "cell_type": "heading", 65 | "level": 2, 66 | "metadata": {}, 67 | "source": [ 68 | "PROGRAM 3.2, PAGE 129" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "collapsed": false, 74 | "input": [ 75 | "# Code Fragment to illustrate template instantiation\n", 76 | "farray = [ float(j)/2 for j in range(10,0,-1) ]\n", 77 | "intarray = [ j for j in range(25,0,-1) ]\n", 78 | "print \"Before sorting : \"\n", 79 | "print farray\n", 80 | "print intarray\n", 81 | "\n", 82 | "selection_sort(farray,len(farray))\n", 83 | "selection_sort(intarray,len(intarray))\n", 84 | "\n", 85 | "print \"After sorting : \"\n", 86 | "print farray\n", 87 | "print intarray" 88 | ], 89 | "language": "python", 90 | "metadata": {}, 91 | "outputs": [ 92 | { 93 | "output_type": "stream", 94 | "stream": "stdout", 95 | "text": [ 96 | "Before sorting : \n", 97 | "[5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5]\n", 98 | "[25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]\n", 99 | "After sorting : \n", 100 | "[0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]\n", 101 | "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]\n" 102 | ] 103 | } 104 | ], 105 | "prompt_number": 3 106 | }, 107 | { 108 | "cell_type": "heading", 109 | "level": 2, 110 | "metadata": {}, 111 | "source": [ 112 | "PROGRAM 3.4, PAGE 131   &   PROGRAM 3.5, PAGE 132" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "collapsed": false, 118 | "input": [ 119 | "# Definition of the class Bag containing integers\n", 120 | "\n", 121 | "# The concept of capacity is not necessary in python since\n", 122 | "# list size and memory management is done automatically by python\n", 123 | "\n", 124 | "class Bag(object):\n", 125 | " def __init__(self):\n", 126 | " \n", 127 | " self._array = []\n", 128 | " self._top = -1\n", 129 | " \n", 130 | " def size(self):\n", 131 | " '''returns the number of elements in the bag'''\n", 132 | " return self._top + 1\n", 133 | " \n", 134 | " def is_empty(self):\n", 135 | " '''return true if the bag is empty; false otherwise'''\n", 136 | " return size == 0\n", 137 | " \n", 138 | " def element(self):\n", 139 | " '''Return an element that is in the bag'''\n", 140 | " if self.is_empty():\n", 141 | " raise Exception('Bag is empty')\n", 142 | " else:\n", 143 | " return self._array[0]\n", 144 | " \n", 145 | " def push(self,elt):\n", 146 | " '''Add an integer to the end of the bag'''\n", 147 | " self._array.append(elt)\n", 148 | " self._top += 1\n", 149 | " \n", 150 | " def pop(self):\n", 151 | " '''Delete an integer from the bag'''\n", 152 | " self._top -= 1 \n", 153 | " return self._array.pop()" 154 | ], 155 | "language": "python", 156 | "metadata": {}, 157 | "outputs": [], 158 | "prompt_number": 4 159 | }, 160 | { 161 | "cell_type": "code", 162 | "collapsed": false, 163 | "input": [ 164 | "bg = Bag()\n", 165 | "bg.push(5)\n", 166 | "bg.push(6)\n", 167 | "bg.push(7)\n", 168 | "bg.push(8)\n", 169 | "print \"Popped Item : \", bg.pop()\n", 170 | "print \"The contents of the bag : \", bg._array" 171 | ], 172 | "language": "python", 173 | "metadata": {}, 174 | "outputs": [ 175 | { 176 | "output_type": "stream", 177 | "stream": "stdout", 178 | "text": [ 179 | "Popped Item : 8\n", 180 | "The contents of the bag : [5, 6, 7]\n" 181 | ] 182 | } 183 | ], 184 | "prompt_number": 5 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "
\n", 191 | "PROGRAM 3.6, PAGE 133   &   PROGRAM 3.7, PAGE 134\n", 192 | "\n", 193 | "Python uses [duck typing](http://en.wikipedia.org/wiki/Duck_typing), so it doesn't need special syntax to handle multiple types.\n", 194 | "Hence template class for Bag is not required. The above defined class Bag will suffice.\n", 195 | "
" 196 | ] 197 | }, 198 | { 199 | "cell_type": "heading", 200 | "level": 2, 201 | "metadata": {}, 202 | "source": [ 203 | "ADT 3.1, PAGE 137   &   PROGRAM 3.8, PAGE 138   &   PROGRAM 3.9, PAGE 138" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "collapsed": false, 209 | "input": [ 210 | "# Abstract data type Stack\n", 211 | "\n", 212 | "# NOTE: This is done just to understand the working of various methods\n", 213 | "# Python list is very much versatile and can be readily used as a sophisticated stack\n", 214 | "# for all practical purposes\n", 215 | "\n", 216 | "class Stack:\n", 217 | " def __init__(self):\n", 218 | " self._stack = []\n", 219 | " self._top = -1\n", 220 | " \n", 221 | " def is_empty(self):\n", 222 | " '''If number of elements in the stack is 0, return True\n", 223 | " else return False'''\n", 224 | " return self._top == -1\n", 225 | " \n", 226 | " def top(self):\n", 227 | " return self._top\n", 228 | " \n", 229 | " def push(self, item):\n", 230 | " '''Insert item into the top of the stack'''\n", 231 | " \n", 232 | " self._stack.append(item)\n", 233 | " self._top += 1\n", 234 | " \n", 235 | " def pop(self):\n", 236 | " '''Delete the top element of the stack'''\n", 237 | " \n", 238 | " if self.is_empty():\n", 239 | " raise Exception('Stack is empty. Cannot delete.')\n", 240 | " \n", 241 | " self._stack.pop()\n", 242 | " self._top -= 1" 243 | ], 244 | "language": "python", 245 | "metadata": {}, 246 | "outputs": [], 247 | "prompt_number": 6 248 | }, 249 | { 250 | "cell_type": "heading", 251 | "level": 2, 252 | "metadata": {}, 253 | "source": [ 254 | "ADT 3.2, PAGE 140     -     Program 3.2, PAGE 144     -     Program 3.11 & 3.12 PAGE 146 & 147" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "collapsed": false, 260 | "input": [ 261 | "# Abstract data type Queue\n", 262 | "\n", 263 | "# NOTE: Inbuilt library Queue can be used for all practical purposes.\n", 264 | "# Again the concept of capacity is unnecessary in python, since the \n", 265 | "# queue containers lists are automatically managed\n", 266 | "\n", 267 | "class Queue:\n", 268 | " '''Abstract Data type Queue'''\n", 269 | " def __init__(self):\n", 270 | " self._queue = []\n", 271 | " \n", 272 | " def is_empty(self):\n", 273 | " return len(self._queue) == 0\n", 274 | " \n", 275 | " def front(self):\n", 276 | " '''Return the element at the rear of the queue'''\n", 277 | " try:\n", 278 | " return self._queue[0]\n", 279 | " except:\n", 280 | " return None\n", 281 | " \n", 282 | " def rear(self):\n", 283 | " '''Return the element at the rear of the queue'''\n", 284 | " try:\n", 285 | " return self._queue[-1]\n", 286 | " except:\n", 287 | " return None\n", 288 | " \n", 289 | " def push(self, item):\n", 290 | " '''Add item to the rear of queue'''\n", 291 | " self._queue.append(item)\n", 292 | " \n", 293 | " def pop(self):\n", 294 | " '''Delete the front element of the queue'''\n", 295 | " if self.is_empty():\n", 296 | " raise Exception('Queue is empty. Cannot delete')\n", 297 | " else:\n", 298 | " self._queue.pop()" 299 | ], 300 | "language": "python", 301 | "metadata": {}, 302 | "outputs": [], 303 | "prompt_number": 7 304 | }, 305 | { 306 | "cell_type": "code", 307 | "collapsed": false, 308 | "input": [ 309 | "# Sample I/O\n", 310 | "\n", 311 | "a = Queue()\n", 312 | "a.push(5)\n", 313 | "a.push(6)\n", 314 | "a.push(9)\n", 315 | "a.push(8)\n", 316 | "a.pop()\n", 317 | "print \"The contents of the queue : \", a._queue\n", 318 | "print \"The front of the queue : \", a.front()\n", 319 | "print \"The rear of the queue : \", a.rear()" 320 | ], 321 | "language": "python", 322 | "metadata": {}, 323 | "outputs": [ 324 | { 325 | "output_type": "stream", 326 | "stream": "stdout", 327 | "text": [ 328 | "The contents of the queue : [5, 6, 9]\n", 329 | "The front of the queue : 5\n", 330 | "The rear of the queue : 9\n" 331 | ] 332 | } 333 | ], 334 | "prompt_number": 8 335 | }, 336 | { 337 | "cell_type": "heading", 338 | "level": 2, 339 | "metadata": {}, 340 | "source": [ 341 | "PROGRAM 3.13, PAGE 149 - PROGRAM 3.14, PAGE 150" 342 | ] 343 | }, 344 | { 345 | "cell_type": "code", 346 | "collapsed": false, 347 | "input": [ 348 | "# Implementataion of stack operations.\n", 349 | "# Here the concept of capacity is not neglected\n", 350 | "# This allows fixed stack sizes which have many practical applications\n", 351 | "# Again, lists can be used as stacks for all practical purposes\n", 352 | "\n", 353 | "# Stack class inherits from class Bag\n", 354 | "\n", 355 | "class Stack(Bag):\n", 356 | "\n", 357 | " def __init__(self, stack_capacity = 10):\n", 358 | " '''Create an empty stack whose initial capacity is stackCapacity'''\n", 359 | " self._stack_capacity = stack_capacity\n", 360 | " self._stack = []\n", 361 | " self._top = -1\n", 362 | " \n", 363 | " def is_empty(self):\n", 364 | " '''If number of elements in the stack is 0, return True\n", 365 | " else return False'''\n", 366 | " return len(self._stack)==0\n", 367 | "\n", 368 | " def top(self):\n", 369 | " if self._top != -1:\n", 370 | " return self._stack[self._top]\n", 371 | " else:\n", 372 | " return None\n", 373 | "\n", 374 | " def push(self, item):\n", 375 | " '''Insert item into the top of the stack'''\n", 376 | " # Adding to a stack, Page 138\n", 377 | " if self._stack_capacity == self._top + 1:\n", 378 | " self._stack_capacity *= 2\n", 379 | " self._stack.append(item)\n", 380 | " self._top += 1\n", 381 | "\n", 382 | " def pop(self):\n", 383 | " '''Delete the top element of the stack'''\n", 384 | " # Deleting from a stack, Page 138\n", 385 | " self._top -= 1\n", 386 | " if self.is_empty():\n", 387 | " raise Exception('Stack is empty. Cannot delete.')\n", 388 | " return self._stack.pop()\n", 389 | " \n", 390 | " def __str__(self):\n", 391 | " '''Print contents of stack'''\n", 392 | " \n", 393 | " # Based on PROGRAM 3.17, PAGE 159\n", 394 | " \n", 395 | " strval = ''\n", 396 | " for elt in self._stack:\n", 397 | " strval += str(elt)+' , '\n", 398 | " return strval.strip(' , ')\n", 399 | " \n", 400 | " # This is similar to overloading operator << in C++ for printing the contents of the stack\n", 401 | " # In python __str__ provides a method for returning the data elements as a string.\n", 402 | "\n", 403 | " # To iterate through the stack elements\n", 404 | " def __iter__(self):\n", 405 | " return iter(self._stack)" 406 | ], 407 | "language": "python", 408 | "metadata": {}, 409 | "outputs": [], 410 | "prompt_number": 9 411 | }, 412 | { 413 | "cell_type": "heading", 414 | "level": 2, 415 | "metadata": {}, 416 | "source": [ 417 | "PROGRAM 3.15 [ Algorithm ], PAGE 156   &   PROGRAM 3.16, PAGE 158" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "collapsed": false, 423 | "input": [ 424 | "# A Simple application of Stack\n", 425 | "# Finding a Path through a Maze. Storing the path in a stack. \n", 426 | "# Path is found through brute force search with backtracking\n", 427 | "\n", 428 | "def Path(maze, mark, path_stack, m, p, startij = (0,0) ):\n", 429 | " '''Output a path, if any, in the maze'''\n", 430 | " \n", 431 | " # direction array [Increment required to move from current cell ]\n", 432 | " d_array = [(0,1), (0,-1), (-1,0), (1,0), (-1,1), (1,1), (-1,-1), (1,-1)]\n", 433 | " # E, W, N, S, NE, SE, NW, SW \n", 434 | "\n", 435 | " si, sj = startij\n", 436 | " \n", 437 | " for di in d_array: \n", 438 | " try:\n", 439 | " # Navigate to new cell\n", 440 | " i = si + di[0]\n", 441 | " j = sj + di[1]\n", 442 | " \n", 443 | " if (i<0) or (j<0):\n", 444 | " raise IndexError\n", 445 | " \n", 446 | " if (i,j) == (m,p):\n", 447 | " path_stack.push((i,j))\n", 448 | " return path_stack \n", 449 | " \n", 450 | " if (maze[i][j] == 0) and (mark[i][j] == 0):\n", 451 | " mark[i][j] = 1\n", 452 | " path_stack.push((i,j))\n", 453 | " return Path(maze, mark, path_stack, m, p, (i,j) )\n", 454 | " \n", 455 | " if (maze[i][j] == 1) and (mark[i][j] == 0):\n", 456 | " mark[i][j] = 1\n", 457 | " # revert to prev valid cell if new cell address is not a part of the path\n", 458 | " \n", 459 | " except IndexError:\n", 460 | " continue\n", 461 | " try:\n", 462 | " return Path(maze, mark, path_stack, m, p, path_stack.pop())\n", 463 | " \n", 464 | " except Exception, e:\n", 465 | " print 'No Path in Maze'\n", 466 | " return None" 467 | ], 468 | "language": "python", 469 | "metadata": {}, 470 | "outputs": [], 471 | "prompt_number": 10 472 | }, 473 | { 474 | "cell_type": "code", 475 | "collapsed": false, 476 | "input": [ 477 | "maze = np.array([ [ 0, 0, 0, 0, 0, 0, 0, 0, 1 ],\n", 478 | " [ 1, 0, 1, 1, 1, 1 ,1, 1, 0 ],\n", 479 | " [ 1, 0, 0, 0, 1, 1 ,0, 1, 0 ],\n", 480 | " [ 1, 0, 1, 0, 1, 1 ,0, 0, 0 ],\n", 481 | " [ 0, 0, 1, 0, 0, 0 ,1, 0, 1 ],\n", 482 | " [ 0, 1, 1, 1, 1, 1 ,1, 0, 1 ],\n", 483 | " [ 0, 0, 0, 0, 0, 1 ,1, 1, 1 ],\n", 484 | " [ 1, 1, 1, 1, 1, 0 ,1, 1, 0 ],\n", 485 | " [ 1, 1, 1, 1, 1, 1 ,0, 0, 0 ] ])\n", 486 | "\n", 487 | "mark = np.zeros(maze.shape,int)\n", 488 | "\n", 489 | "path_stack = Stack(maze.size)\n", 490 | "\n", 491 | "path_stack.push((0,0))\n", 492 | "\n", 493 | "print Path(maze, mark, path_stack, 8, 8)" 494 | ], 495 | "language": "python", 496 | "metadata": {}, 497 | "outputs": [ 498 | { 499 | "output_type": "stream", 500 | "stream": "stdout", 501 | "text": [ 502 | "(0, 0) , (0, 1) , (1, 1) , (2, 1) , (3, 1) , (4, 1) , (4, 0) , (5, 0) , (6, 0) , (6, 1) , (6, 2) , (6, 3) , (6, 4) , (7, 5) , (8, 6) , (8, 7) , (8, 8)\n" 503 | ] 504 | } 505 | ], 506 | "prompt_number": 11 507 | }, 508 | { 509 | "cell_type": "code", 510 | "collapsed": false, 511 | "input": [ 512 | "%matplotlib inline\n", 513 | "plt.figure().set_size_inches(10, 10); plt.axis('off'); plt.axis('equal')\n", 514 | "\n", 515 | "plt.scatter(*np.where(maze == 1), s = 3000, marker = \"s\", c = \"black\", edgecolors = \"w\")\n", 516 | "plt.plot(*(zip(*path_stack)), marker = \"o\", linestyle = \"--\", c = \"r\")\n", 517 | "\n", 518 | "plt.show()" 519 | ], 520 | "language": "python", 521 | "metadata": {}, 522 | "outputs": [ 523 | { 524 | "metadata": {}, 525 | "output_type": "display_data", 526 | "png": "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\nnwEAJBQBAFRC0fuy9hkAXB5CEbBUpsMAdkooAhbH2mfrZu0z1mozdwFLdaMOfrh++sn6kf9U//ZO\n3XytXt7Fd0/TNG024+2aaZrabDabkfurGrG3em//XfT33KiDx+qF/bp6WO/s8tjbhcvQ36fqZz5W\n3/1L9YvOnR+dcwuzulEHz9a3pppOP8/Wt27UwS6+fzo5Aob7vNvX0P2N2tvZ/XeR5j72Lpr+Ltao\nx59zy+5IZud4pl75en323u0HJ9s/d9HfP/JfO64Urdcu/pq737H3V+r1n61/dmbTL2/qa99WY/1Q\n9cVz/tOL+PmfrJ/4J/XkvT93em5Zev0f9PM/Xq/+fH3m3u3OnR+Nc8vueKboHPt19bzt1+varmuB\ny+R+x96V2tt1LRfhO+4zYe4o55bvrCvnbR+lP7iUnqlXzl7+Pf18rr6+i+8f9TKp22fr/uziEvfc\nx95F09/FGvX4c27ZHVeKznGnbj5Xr5/d9my9cbtuzVUTXAajH3v6g2VbxD28JbpRB4/X89fr2lv1\n9u265Q2Kj8YzReu2y7fP5jr2dkF/F8e5ZZ2W9EzRIorgbiMf2ELRei3pxAXncW5ZpyWdW9w+AwBI\nKAIAqIQiAIBKKAIAqIQiAIBKKAIAqIQiAIBKKAIAqIQiAIBKKAIAqIQiAIBKKAIAqIQiAIBKKAIA\nqIQiAIBKKAIAqIQiAIBKKAIAqIQiAIBKKAIAqIQiAIBKKAIAqOqRuQvg2x0fHx9O07Q/dx3bdnx8\nfHj678j9jdhbvdcfLJVzyzo5twAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAA8L7+P+8RnUBDbw/7AAAAAElFTkSuQmCC\n", 527 | "text": [ 528 | "" 529 | ] 530 | } 531 | ], 532 | "prompt_number": 12 533 | }, 534 | { 535 | "cell_type": "heading", 536 | "level": 2, 537 | "metadata": {}, 538 | "source": [ 539 | "PROGRAM 3.18, PAGE 162" 540 | ] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "collapsed": false, 545 | "input": [ 546 | "# Evaluating Postfix Expressions\n", 547 | "def postfixvalue(a,b,expr):\n", 548 | " if expr == '+':\n", 549 | " return a + b \n", 550 | " elif expr == '-':\n", 551 | " return a - b\n", 552 | " elif expr == '/':\n", 553 | " return a / b\n", 554 | " elif expr == '*':\n", 555 | " return a * b\n", 556 | "\n", 557 | "def Eval(stack_e):\n", 558 | " '''Evaluate a Postfix expression e. It is assumed that the last token is either an operator, operand or #'''\n", 559 | " stack_operations = Stack() \n", 560 | " while not stack_e.is_empty():\n", 561 | " a = stack_e.pop()\n", 562 | " if str(a).isdigit() != True:\n", 563 | " stack_operations.push(a)\n", 564 | " else:\n", 565 | " b = stack_e.pop() \n", 566 | " val = postfixvalue(a,b,stack_operations.pop())\n", 567 | " if stack_e.is_empty():\n", 568 | " return val\n", 569 | " else:\n", 570 | " stack_e.push(val)\n", 571 | " \n", 572 | " \n", 573 | " if stack_e.is_empty() == False:\n", 574 | " stack_e.pop() \n", 575 | " else:\n", 576 | " None " 577 | ], 578 | "language": "python", 579 | "metadata": {}, 580 | "outputs": [], 581 | "prompt_number": 13 582 | }, 583 | { 584 | "cell_type": "code", 585 | "collapsed": false, 586 | "input": [ 587 | "#Sample I/O - Not in textbook\n", 588 | "exp = Stack()\n", 589 | "exp.push(3)\n", 590 | "exp.push(4)\n", 591 | "exp.push(5)\n", 592 | "exp.push('+')\n", 593 | "exp.push('-')\n", 594 | "print Eval(exp)" 595 | ], 596 | "language": "python", 597 | "metadata": {}, 598 | "outputs": [ 599 | { 600 | "output_type": "stream", 601 | "stream": "stdout", 602 | "text": [ 603 | "6\n" 604 | ] 605 | } 606 | ], 607 | "prompt_number": 14 608 | }, 609 | { 610 | "cell_type": "heading", 611 | "level": 2, 612 | "metadata": {}, 613 | "source": [ 614 | "PROGRAM 3.19, PAGE 165" 615 | ] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "collapsed": false, 620 | "input": [ 621 | "# Converting from Infix to postfix form\n", 622 | "\n", 623 | "def isp(op):\n", 624 | " '''Returns the In-Stack Priority of the operator'''\n", 625 | " # Refer Page 160\n", 626 | " # Note - Unary operators are not considered they cannot be parsed by our function.\n", 627 | " if op in ['!']:\n", 628 | " return 1\n", 629 | " elif op in ['*','/','%']:\n", 630 | " return 2\n", 631 | " elif op in ['+','-']:\n", 632 | " return 3\n", 633 | " elif op in ['<','<=','>=','>']:\n", 634 | " return 4\n", 635 | " elif op in ['==','!=']:\n", 636 | " return 5\n", 637 | " elif op in ['&&']:\n", 638 | " return 6\n", 639 | " elif op in ['||']:\n", 640 | " return 7\n", 641 | " elif (op == '#') or (op == '('):\n", 642 | " return 8\n", 643 | "\n", 644 | "def icp(op):\n", 645 | " '''Incoming priority of the operator'''\n", 646 | " if (op == '('):\n", 647 | " return 0\n", 648 | " else:\n", 649 | " return isp(op)\n", 650 | " \n", 651 | "def Postfix(e):\n", 652 | " '''Output the postfix form of the infix expression '''\n", 653 | " stack = Stack()\n", 654 | " stack.push('#')\n", 655 | " for x in e._stack:\n", 656 | " if x in ['+','-','/','*']:\n", 657 | " # If x is an operator\n", 658 | " while isp(stack.top()) <= icp(x):\n", 659 | " print stack.pop(),\n", 660 | " stack.push(x)\n", 661 | " elif x == ')':\n", 662 | " # unstack untill '('\n", 663 | " while stack.top() != '(':\n", 664 | " print stack.pop(), \n", 665 | " # Unstack and print it\n", 666 | " else:\n", 667 | " # If x is an operand\n", 668 | " print x,\n", 669 | " # End of expression, empty the stack\n", 670 | " while not stack.is_empty():\n", 671 | " print stack.pop()," 672 | ], 673 | "language": "python", 674 | "metadata": {}, 675 | "outputs": [], 676 | "prompt_number": 15 677 | }, 678 | { 679 | "cell_type": "code", 680 | "collapsed": false, 681 | "input": [ 682 | "e = Stack()\n", 683 | "map(e.push, \"A/B*C+D*E\") # Push the infix expression characters one by one ( left to right ) into the e stack\n", 684 | "Postfix(e)" 685 | ], 686 | "language": "python", 687 | "metadata": {}, 688 | "outputs": [ 689 | { 690 | "output_type": "stream", 691 | "stream": "stdout", 692 | "text": [ 693 | "A B / C * D E * + #\n" 694 | ] 695 | } 696 | ], 697 | "prompt_number": 16 698 | } 699 | ], 700 | "metadata": {} 701 | } 702 | ] 703 | } -------------------------------------------------------------------------------- /Chapter 4 - Linked Lists.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:24a398f5079d2b5ec4ad1b77b913b9629ff6aa4bdfa838b4364f2c52dc809f1a" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "heading", 13 | "level": 2, 14 | "metadata": {}, 15 | "source": [ 16 | "PROGRAM 4.1, PAGE 179" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "collapsed": false, 22 | "input": [ 23 | "#Composite Classes\n", 24 | "\n", 25 | "#Python does not support friend funcitons hence 2 classes one for the node and one for the class are declared.\n", 26 | "\n", 27 | "class ThreeLetterNode:\n", 28 | " data = None\n", 29 | " link = None\n", 30 | "class ThreeLetterChain:\n", 31 | " '''A linked list of 3 letter strings'''\n", 32 | " first = None" 33 | ], 34 | "language": "python", 35 | "metadata": {}, 36 | "outputs": [], 37 | "prompt_number": 1 38 | }, 39 | { 40 | "cell_type": "heading", 41 | "level": 2, 42 | "metadata": {}, 43 | "source": [ 44 | "PROGRAM 4.2, PAGE 180" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "collapsed": false, 50 | "input": [ 51 | "#Nested Classes\n", 52 | "class ThreeLetterChain:\n", 53 | " class ThreeLetterNode:\n", 54 | " data = None\n", 55 | " link = None\n", 56 | " first = None" 57 | ], 58 | "language": "python", 59 | "metadata": {}, 60 | "outputs": [], 61 | "prompt_number": 2 62 | }, 63 | { 64 | "cell_type": "heading", 65 | "level": 2, 66 | "metadata": {}, 67 | "source": [ 68 | "PROGRAM 4.3, PAGE 182" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "collapsed": false, 74 | "input": [ 75 | "#Creating a two-node list\n", 76 | "class ChainNode:\n", 77 | " def __init__(self, data, link = None):\n", 78 | " self.data = data\n", 79 | " self.link = link\n", 80 | "class Chain:\n", 81 | " def __init__(self, first):\n", 82 | " self.first = first\n", 83 | "def Create2(self):\n", 84 | " #Create and set fields of second node\n", 85 | " self.second = ChainNode(20,None)\n", 86 | " \n", 87 | " #Create and set fields of first node\n", 88 | " self.first = ChainNode(10,second)\n", 89 | "Chain.Create2 = Create2" 90 | ], 91 | "language": "python", 92 | "metadata": {}, 93 | "outputs": [], 94 | "prompt_number": 3 95 | }, 96 | { 97 | "cell_type": "heading", 98 | "level": 2, 99 | "metadata": {}, 100 | "source": [ 101 | "PROGRAM 4.4, PAGE 182" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "collapsed": false, 107 | "input": [ 108 | "#Inserting a Node\n", 109 | "def Insert50(self,x):\n", 110 | " if self.first is not None:\n", 111 | " #Insert after x\n", 112 | " x.link = ChainNode(50,x.link)\n", 113 | " else:\n", 114 | " #Insert into empty list\n", 115 | " first = ChainNode(50)\n", 116 | "Chain.Insert50 = Insert50" 117 | ], 118 | "language": "python", 119 | "metadata": {}, 120 | "outputs": [], 121 | "prompt_number": 4 122 | }, 123 | { 124 | "cell_type": "heading", 125 | "level": 2, 126 | "metadata": {}, 127 | "source": [ 128 | "PROGRAM 4.5, PAGE 183" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "collapsed": false, 134 | "input": [ 135 | "#Deleting a node\n", 136 | "def Delete(self,x,y):\n", 137 | " if x == self.first:\n", 138 | " self.first = self.first.link\n", 139 | " else:\n", 140 | " y.link = x.link\n", 141 | "Chain.Delete = Delete" 142 | ], 143 | "language": "python", 144 | "metadata": {}, 145 | "outputs": [], 146 | "prompt_number": 5 147 | }, 148 | { 149 | "cell_type": "heading", 150 | "level": 2, 151 | "metadata": {}, 152 | "source": [ 153 | "PROGRAM 4.6, PAGE 186" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "Python uses [duck typing](http://en.wikipedia.org/wiki/Duck_typing), so it doesn't need special syntax to handle multiple types.\n", 161 | "Hence template class for Chains is not possible in Python." 162 | ] 163 | }, 164 | { 165 | "cell_type": "heading", 166 | "level": 2, 167 | "metadata": {}, 168 | "source": [ 169 | "PROGRAM 4.7, PAGE 187" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "collapsed": false, 175 | "input": [ 176 | "#Pseudo code for computing maximum element\n", 177 | "\n", 178 | "def Max(C):\n", 179 | " return max(C)" 180 | ], 181 | "language": "python", 182 | "metadata": {}, 183 | "outputs": [], 184 | "prompt_number": 6 185 | }, 186 | { 187 | "cell_type": "heading", 188 | "level": 2, 189 | "metadata": {}, 190 | "source": [ 191 | "PROGRAM 4.8, PAGE 189" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "collapsed": false, 197 | "input": [ 198 | "#Using an array iterator\n", 199 | "def main():\n", 200 | " x = [0,1,2]\n", 201 | " for y in x:\n", 202 | " print y,\n", 203 | "if __name__ == \"__main__\":\n", 204 | " main()" 205 | ], 206 | "language": "python", 207 | "metadata": {}, 208 | "outputs": [ 209 | { 210 | "output_type": "stream", 211 | "stream": "stdout", 212 | "text": [ 213 | "0 1 2\n" 214 | ] 215 | } 216 | ], 217 | "prompt_number": 7 218 | }, 219 | { 220 | "cell_type": "heading", 221 | "level": 2, 222 | "metadata": {}, 223 | "source": [ 224 | "PROGRAM 4.9, PAGE 190" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "collapsed": false, 230 | "input": [ 231 | "#Code to simulate C++:STL copy function\n", 232 | "\n", 233 | "def copy(src, target, start, end, to):\n", 234 | " '''Copy form src[start:end] to target[to:(to+end-start)]'''\n", 235 | " while start <= end:\n", 236 | " target.__setitem__(to,src[start])\n", 237 | " #Set item is used for inplace assignment\n", 238 | " to += 1\n", 239 | " start += 1\n", 240 | " \n", 241 | "#Sample I/O - Not in textbook\n", 242 | "a = [1,2,3,4,5,6]\n", 243 | "b = [6,4,0,1,2,3]\n", 244 | "copy(a,b,2,5,2)\n", 245 | "#copies a[2:5] to b[2:5]\n", 246 | "print b" 247 | ], 248 | "language": "python", 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "output_type": "stream", 253 | "stream": "stdout", 254 | "text": [ 255 | "[6, 4, 3, 4, 5, 6]\n" 256 | ] 257 | } 258 | ], 259 | "prompt_number": 8 260 | }, 261 | { 262 | "cell_type": "heading", 263 | "level": 2, 264 | "metadata": {}, 265 | "source": [ 266 | "PROGRAM 4.10, PAGE 191" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "collapsed": false, 272 | "input": [ 273 | "#Forward chain iterator for Chain class\n", 274 | "class ChainIterator:\n", 275 | " def __init__(self, startNode = None):\n", 276 | " self.current = startNode\n", 277 | " #Python does not support ++ operator hence add method is overloaded.\n", 278 | " def __add__(self,value):\n", 279 | " if value is int:\n", 280 | " for i in range(value):\n", 281 | " if self.current == None:\n", 282 | " break\n", 283 | " self.current = self.current.link\n", 284 | " return self\n", 285 | " else:\n", 286 | " raise TypeError\n", 287 | " def __ne__(self, right):\n", 288 | " return self.current != right.current\n", 289 | " def __eq__(self, right):\n", 290 | " return self.current == right.current\n", 291 | " \n", 292 | " # This is vaguely equivalent to overloading the . operator\n", 293 | " # This basically allows accessing the members / attributes of the self.current from the interator instance itself.\n", 294 | " __getattr__ = lambda self : self.current.__getattribute__(key)\n", 295 | " \n", 296 | " def __getattr__(self, key):\n", 297 | " return self.current.__getattr__(key)\n", 298 | "\n", 299 | "# Defining ChainIterator as a member object of Chain class\n", 300 | "Chain.ChainIterator = ChainIterator\n", 301 | "\n", 302 | "# Refer Page No 190\n", 303 | "\n", 304 | "# Defining begin and end methods of Chain\n", 305 | " \n", 306 | "Chain.begin = lambda self : self.ChainIterator(self.first)\n", 307 | "Chain.end = lambda self : self.ChainIterator(None)" 308 | ], 309 | "language": "python", 310 | "metadata": {}, 311 | "outputs": [], 312 | "prompt_number": 9 313 | }, 314 | { 315 | "cell_type": "heading", 316 | "level": 2, 317 | "metadata": {}, 318 | "source": [ 319 | "PROGRAM 4.11, PAGE 192" 320 | ] 321 | }, 322 | { 323 | "cell_type": "code", 324 | "collapsed": false, 325 | "input": [ 326 | "#Inserting at the back of a list\n", 327 | "\n", 328 | "def InsertBack(self, e):\n", 329 | " if self.first == None :\n", 330 | " #If chain is empty\n", 331 | " self.first = ChainNode(e)\n", 332 | " self.last = self.first\n", 333 | " else:\n", 334 | " #On non empty chains\n", 335 | " self.last.link = ChainNode(e)\n", 336 | " self.last = self.last.link\n", 337 | " \n", 338 | "Chain.InsertBack = InsertBack" 339 | ], 340 | "language": "python", 341 | "metadata": {}, 342 | "outputs": [], 343 | "prompt_number": 10 344 | }, 345 | { 346 | "cell_type": "heading", 347 | "level": 2, 348 | "metadata": {}, 349 | "source": [ 350 | "PROGRAM 4.12, PAGE 192" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "collapsed": false, 356 | "input": [ 357 | "#Concatenating two chains\n", 358 | "def Concatenate(b):\n", 359 | " '''b is concatenated to the end of self'''\n", 360 | " if first != None :\n", 361 | " self.last.link = b.first\n", 362 | " self.last = b.last\n", 363 | " else:\n", 364 | " self.first = b.first\n", 365 | " self.last = b.last\n", 366 | " b.first = None\n", 367 | " b.last = None \n", 368 | "Chain.Concatenate = Concatenate" 369 | ], 370 | "language": "python", 371 | "metadata": {}, 372 | "outputs": [], 373 | "prompt_number": 11 374 | }, 375 | { 376 | "cell_type": "heading", 377 | "level": 2, 378 | "metadata": {}, 379 | "source": [ 380 | "PROGRAM 4.13, PAGE 193" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "collapsed": false, 386 | "input": [ 387 | "#Reversing a list\n", 388 | "def Reverse(self):\n", 389 | " ''' A chain is reversed so that [ a[0] , ... , a[n] ] becomes [ a[n] , ... , a[0] ]'''\n", 390 | " previous = None\n", 391 | " current = self.first\n", 392 | " while current is not None:\n", 393 | " r = previous\n", 394 | " #r is a temp variable which trails the previous\n", 395 | " previous = current\n", 396 | " current = current.link\n", 397 | " previous.link = r\n", 398 | " self.first = previous\n", 399 | "Chain.Reverse = Reverse" 400 | ], 401 | "language": "python", 402 | "metadata": {}, 403 | "outputs": [], 404 | "prompt_number": 12 405 | }, 406 | { 407 | "cell_type": "heading", 408 | "level": 2, 409 | "metadata": {}, 410 | "source": [ 411 | "PROGRAM 4.14, PAGE 196" 412 | ] 413 | }, 414 | { 415 | "cell_type": "code", 416 | "collapsed": false, 417 | "input": [ 418 | "class CircularList:\n", 419 | " def __init__(self):\n", 420 | " self.first = None\n", 421 | " self.last = None\n", 422 | " self.av = None\n", 423 | " #av is the list of deleted Nodes\n", 424 | " def InsertFront(self,e):\n", 425 | " '''Inserts the element e at the front of the circular list self, where last points to the last node in the list'''\n", 426 | " newNode = ChainNode(e)\n", 427 | " if last is not None:\n", 428 | " newNode.link = self.last.link\n", 429 | " self.last.link = newNode\n", 430 | " else:\n", 431 | " #empty list\n", 432 | " self.last = newNode\n", 433 | " self.last.link = self.last\n", 434 | " #circular referencing" 435 | ], 436 | "language": "python", 437 | "metadata": {}, 438 | "outputs": [], 439 | "prompt_number": 13 440 | }, 441 | { 442 | "cell_type": "heading", 443 | "level": 2, 444 | "metadata": {}, 445 | "source": [ 446 | "PROGRAM 4.15, PAGE 198" 447 | ] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "collapsed": false, 452 | "input": [ 453 | "#Getting a Node\n", 454 | "def GetNode(self):\n", 455 | " '''Provide a node for use'''\n", 456 | " if self.av is not None:\n", 457 | " x = self.av\n", 458 | " self.av = self.av.link\n", 459 | " else:\n", 460 | " #if there is no deleted node to x is assigned a new Node\n", 461 | " x = ChainNode()\n", 462 | " return x\n", 463 | "CircularList.GetNode = GetNode" 464 | ], 465 | "language": "python", 466 | "metadata": {}, 467 | "outputs": [], 468 | "prompt_number": 14 469 | }, 470 | { 471 | "cell_type": "heading", 472 | "level": 2, 473 | "metadata": {}, 474 | "source": [ 475 | "PROGRAM 4.16, PAGE 198" 476 | ] 477 | }, 478 | { 479 | "cell_type": "code", 480 | "collapsed": false, 481 | "input": [ 482 | "#Returning a node\n", 483 | "def RetNode(self,x):\n", 484 | " '''Free the node pointed by x'''\n", 485 | " x.link = self.av\n", 486 | " self.av = x\n", 487 | " x = None\n", 488 | " #inserts (at the front) the x to the list av, which contains deleted list" 489 | ], 490 | "language": "python", 491 | "metadata": {}, 492 | "outputs": [], 493 | "prompt_number": 15 494 | }, 495 | { 496 | "cell_type": "heading", 497 | "level": 2, 498 | "metadata": {}, 499 | "source": [ 500 | "PROGRAM 4.17, PAGE 198" 501 | ] 502 | }, 503 | { 504 | "cell_type": "code", 505 | "collapsed": false, 506 | "input": [ 507 | "#Deleting a Circular list\n", 508 | "#Python manages out of scope variable by efficient garbage collection methods hence destructors need not be defined in python\n", 509 | "#Instead a method __del__() is created to simulate the same effect.\n", 510 | "def __del__(self):\n", 511 | " '''Delete the circular list'''\n", 512 | " if self.last is not None:\n", 513 | " self.first = self.last.link\n", 514 | " self.last.link = self.av\n", 515 | " self.av = self.first\n", 516 | " self.last = None\n", 517 | "CircularList.__del__ = __del__" 518 | ], 519 | "language": "python", 520 | "metadata": {}, 521 | "outputs": [], 522 | "prompt_number": 16 523 | }, 524 | { 525 | "cell_type": "heading", 526 | "level": 2, 527 | "metadata": {}, 528 | "source": [ 529 | "PROGRAM 4.19, PAGE 200" 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "collapsed": false, 535 | "input": [ 536 | "#Adding a linked stack\n", 537 | "class LinkedStack:\n", 538 | " def __init__(self):\n", 539 | " self.top = None\n", 540 | " def Push(self,e):\n", 541 | " self.top = ChainNode(e,top)\n", 542 | " def IsEmpty(self):\n", 543 | " return self.top is None " 544 | ], 545 | "language": "python", 546 | "metadata": {}, 547 | "outputs": [], 548 | "prompt_number": 17 549 | }, 550 | { 551 | "cell_type": "heading", 552 | "level": 2, 553 | "metadata": {}, 554 | "source": [ 555 | "PROGRAM 4.20, PAGE 201" 556 | ] 557 | }, 558 | { 559 | "cell_type": "code", 560 | "collapsed": false, 561 | "input": [ 562 | "#Deleting from a Linked Stack\n", 563 | "def Pop(self):\n", 564 | " '''Deleting top node from the stack'''\n", 565 | " if (self.IsEmpty()):\n", 566 | " raise Exception('Stack is empty. Cannot delete')\n", 567 | " delNode = self.top\n", 568 | " sel.top = self.top.link\n", 569 | " #In python the del operator deletes the name from the name space only\n", 570 | " #Automatic garbage collection in python frees the allocated space by itself hence the use of del is not required\n", 571 | "LinkedStack.Pop = Pop" 572 | ], 573 | "language": "python", 574 | "metadata": {}, 575 | "outputs": [], 576 | "prompt_number": 18 577 | }, 578 | { 579 | "cell_type": "heading", 580 | "level": 2, 581 | "metadata": {}, 582 | "source": [ 583 | "PROGRAM 4.21, PAGE 201" 584 | ] 585 | }, 586 | { 587 | "cell_type": "code", 588 | "collapsed": false, 589 | "input": [ 590 | "#Adding to a linked queue\n", 591 | "class LinkedQueue:\n", 592 | " def __init__(self):\n", 593 | " self.front = None\n", 594 | " self.rear = None\n", 595 | " def Push(self,e):\n", 596 | " if(self.IsEmpty()):\n", 597 | " self.rear = self.front = ChainNode(e,None)\n", 598 | " else:\n", 599 | " self.rear.link = ChainNode(e,None)\n", 600 | " def IsEmpty(self):\n", 601 | " if(self.front is None):\n", 602 | " return True\n", 603 | " else:\n", 604 | " return False" 605 | ], 606 | "language": "python", 607 | "metadata": {}, 608 | "outputs": [], 609 | "prompt_number": 19 610 | }, 611 | { 612 | "cell_type": "heading", 613 | "level": 2, 614 | "metadata": {}, 615 | "source": [ 616 | "PROGRAM 4.22, PAGE 201" 617 | ] 618 | }, 619 | { 620 | "cell_type": "code", 621 | "collapsed": false, 622 | "input": [ 623 | "# Deleting from a linked queue\n", 624 | "def _pop(self):\n", 625 | " if(self.IsEmpty()):\n", 626 | " raise Exception(\"Queue is empty. Cannot delete\")\n", 627 | " self.front = self.front.link\n", 628 | "LinkedQueue.pop = _pop" 629 | ], 630 | "language": "python", 631 | "metadata": {}, 632 | "outputs": [], 633 | "prompt_number": 20 634 | }, 635 | { 636 | "cell_type": "heading", 637 | "level": 2, 638 | "metadata": {}, 639 | "source": [ 640 | "PROGRAM 4.23, PAGE 203" 641 | ] 642 | }, 643 | { 644 | "cell_type": "code", 645 | "collapsed": false, 646 | "input": [ 647 | "# Polynomial class definition\n", 648 | "class Term:\n", 649 | " def __init__(self, c = None, e = None):\n", 650 | " self.coef = c\n", 651 | " self.exp = e\n", 652 | " lambda Set : self(c,e)\n", 653 | " self.Set = Set\n", 654 | "\n", 655 | "class Polynomial:\n", 656 | " def __init__(self):\n", 657 | " poly = Chain() # Instantiating a Chain object with an instance of Term as its attribute first." 658 | ], 659 | "language": "python", 660 | "metadata": {}, 661 | "outputs": [], 662 | "prompt_number": 21 663 | }, 664 | { 665 | "cell_type": "heading", 666 | "level": 2, 667 | "metadata": {}, 668 | "source": [ 669 | "PROGRAM 4.24, PAGE 206" 670 | ] 671 | }, 672 | { 673 | "cell_type": "code", 674 | "collapsed": false, 675 | "input": [ 676 | "# Adding two polynomials\n", 677 | "def _add(self, b):\n", 678 | " \"\"\"\n", 679 | " Polynomials self (a) and b are added and the sum is returned\n", 680 | " \"\"\"\n", 681 | " temp = Term()\n", 682 | " ai = poly.begin()\n", 683 | " bi = b.poly.begin()\n", 684 | " c = Polynomial\n", 685 | " \n", 686 | " while ai is not None and bi is not None:\n", 687 | " if ai.exp == bi.exp:\n", 688 | " sum_ = ai.coef + bi.coef\n", 689 | " if sum_ != 0:\n", 690 | " c.poly.InsertBack(temp.Set(sum_,ai.exp))\n", 691 | " ai += 1\n", 692 | " bi += 1\n", 693 | " elif ai.exp < bi.exp:\n", 694 | " c.poly.InsertBack(temp.Set(bi.coef, bi.exp))\n", 695 | " else:\n", 696 | " c.poly.InsertBack(temp.Set(ai.coef, ai.exp))\n", 697 | " \n", 698 | " while ai != 0:\n", 699 | " # Copy rest of a\n", 700 | " c.poly.InsertBack(temp.Set(ai.coef, ai.exp))\n", 701 | " ai += 1\n", 702 | " \n", 703 | " while bi != 0:\n", 704 | " # Copy rest of b\n", 705 | " c.poly.InsertBack(temp.Set(bi.coef, bi.exp))\n", 706 | " bi += 1\n", 707 | " \n", 708 | " return c\n", 709 | "\n", 710 | "# Overloading the Polynomial's __add__ method ( overloading the + operator for Polynomial class)\n", 711 | "Polynomial.__add__ = _add" 712 | ], 713 | "language": "python", 714 | "metadata": {}, 715 | "outputs": [], 716 | "prompt_number": 22 717 | }, 718 | { 719 | "cell_type": "heading", 720 | "level": 2, 721 | "metadata": {}, 722 | "source": [ 723 | "PROGRAM 4.26, PAGE 212   &   PROGRAM 4.27, PAGE 213   &   PROGRAM 4.28, PAGE 214" 724 | ] 725 | }, 726 | { 727 | "cell_type": "code", 728 | "collapsed": false, 729 | "input": [ 730 | "# Function to find equivalence classes\n", 731 | "class ENode:\n", 732 | " def __init__(self, d = 0, link = None):\n", 733 | " self.data = d\n", 734 | " self.link = link\n", 735 | "\n", 736 | "def Equivalence():\n", 737 | " \"\"\"\n", 738 | " Input equivalence pairs and output the equivalence classes.\n", 739 | " \"\"\"\n", 740 | " inFileContent = None\n", 741 | " try:\n", 742 | " with open(\"equiv.in\", \"r\") as inFile:\n", 743 | " inFileContent = [ int(i) for i in inFile.read().replace(',',' ').split() ]\n", 744 | " # Stores the file contents as an array of type int.\n", 745 | " except Exception, e:\n", 746 | " print \"Cannot open input file\"\n", 747 | " return\n", 748 | " \n", 749 | " n = inFileContent[0]\n", 750 | " first = [ ENode(0) for i in range(n) ]\n", 751 | " out = [False]*n\n", 752 | "\n", 753 | " # p is a variable to iterate through the length of the inFileContent\n", 754 | " p = 1\n", 755 | " \n", 756 | " # Phase 1 : Input equivalence pairs\n", 757 | " while p < len(inFileContent):\n", 758 | " i = inFileContent[p]; j = inFileContent[p+1]\n", 759 | " first[i] = ENode(j, first[i])\n", 760 | " first[j] = ENode(i, first[j])\n", 761 | " p += 2\n", 762 | " \n", 763 | " #Phase 2 : Output Equivalence classes\n", 764 | " for i in range(n):\n", 765 | " if not out[i]:\n", 766 | " print \"\\nA new class\", i,\n", 767 | " out[i] = True\n", 768 | " x = first[i]\n", 769 | " top = None\n", 770 | " while True: # Find the rest of the class\n", 771 | " while x is not None: # Process the list\n", 772 | " j = x.data\n", 773 | " if not out[j]:\n", 774 | " print \",\", j, \n", 775 | " out[j] = True\n", 776 | " y = x.link\n", 777 | " x.link = top\n", 778 | " top = x\n", 779 | " x = y\n", 780 | " else:\n", 781 | " x = x.link\n", 782 | " # End of while loop\n", 783 | "\n", 784 | " if not top:\n", 785 | " break\n", 786 | "\n", 787 | " x = first[top.data]\n", 788 | " top = top.link # Unstack\n", 789 | "\n", 790 | " # End of while True\n", 791 | "\n", 792 | " # End of if not out[i]\n", 793 | "\n", 794 | " # In python Garbage Collection is automatic\n", 795 | " \n", 796 | "# Sample Example - Refer Page 211\n", 797 | "with open('equiv.in','w') as f:\n", 798 | " f.write('12 0 4 3 1 6 10 8 9 7 4 6 8 3 5 2 11 11 0')\n", 799 | " \n", 800 | "Equivalence()" 801 | ], 802 | "language": "python", 803 | "metadata": {}, 804 | "outputs": [ 805 | { 806 | "output_type": "stream", 807 | "stream": "stdout", 808 | "text": [ 809 | "\n", 810 | "A new class 0 , 11 , 4 , 7 , 2 \n", 811 | "A new class 1 , 3 , 5 \n", 812 | "A new class 6 , 8 , 10 , 9\n" 813 | ] 814 | } 815 | ], 816 | "prompt_number": 23 817 | }, 818 | { 819 | "cell_type": "heading", 820 | "level": 2, 821 | "metadata": {}, 822 | "source": [ 823 | "PROGRAM 4.29, PAGE 219" 824 | ] 825 | }, 826 | { 827 | "cell_type": "code", 828 | "collapsed": false, 829 | "input": [ 830 | "# Class Definitions for sparse matrix\n", 831 | "class Triple:\n", 832 | " def __init__(self):\n", 833 | " self.row = None\n", 834 | " self.col = None\n", 835 | " self.value = None\n", 836 | "\n", 837 | "class MatrixNode:\n", 838 | " def __init__(self, b, t):\n", 839 | " if ( type(b) != bool ):\n", 840 | " raise TypeError\n", 841 | " return\n", 842 | " \n", 843 | " self.head = b\n", 844 | " \n", 845 | " if b:\n", 846 | " self.right = self.down = self\n", 847 | " self.next_ = None\n", 848 | " else:\n", 849 | " self.triple = t\n", 850 | " \n", 851 | " \n", 852 | "\n", 853 | "class Matrix:\n", 854 | " def __init__(self):\n", 855 | " self.headnode = None\n", 856 | " self.av = None" 857 | ], 858 | "language": "python", 859 | "metadata": {}, 860 | "outputs": [], 861 | "prompt_number": 24 862 | }, 863 | { 864 | "cell_type": "heading", 865 | "level": 2, 866 | "metadata": {}, 867 | "source": [ 868 | "PROGRAM 4.30, PAGE 221" 869 | ] 870 | }, 871 | { 872 | "cell_type": "code", 873 | "collapsed": false, 874 | "input": [ 875 | "# Reading in the Sparse Matrix\n", 876 | "\n", 877 | "#Overloading Operator >> for Class Matrix\n", 878 | "import operator, sys, io, IPython\n", 879 | "\n", 880 | "class MyStdIn(object):\n", 881 | " def __init__(self):\n", 882 | " pass\n", 883 | " \n", 884 | " def __rshift__(self, matrix):\n", 885 | " if isinstance(matrix, Matrix): \n", 886 | " s = Triple()\n", 887 | " \n", 888 | " # Accept inputs as triplets\n", 889 | " # >>> 5 6 7\n", 890 | " # >>> 1 2 3 etc ...\n", 891 | " \n", 892 | " triplet = raw_input().strip().split()\n", 893 | " \n", 894 | " s.row, s.col, s.value = [ int(i) for i in triplet ]\n", 895 | " \n", 896 | " p = max(s.row, s.col)\n", 897 | " \n", 898 | " # Set up header node for list of header Nodes\n", 899 | " matrix.headnode = MatrixNode(False, s)\n", 900 | " \n", 901 | " # If there is no row or column to input\n", 902 | " if p == 0:\n", 903 | " matrix.headnode.right = matrix.headnode\n", 904 | " return\n", 905 | " \n", 906 | " # If there is atleast one row or column\n", 907 | " head = [ MatrixNode(True, None) for i in range(p)]\n", 908 | " \n", 909 | " currentRow = 0\n", 910 | " last = head[0] # Last node in current row\n", 911 | " \n", 912 | " for i in range(s.value):\n", 913 | " t = Triple()\n", 914 | " triplet = raw_input().strip().split()\n", 915 | " \n", 916 | " t.row, t.col, t.value = [ int(i) for i in triplet ]\n", 917 | " if t.row > currentRow:\n", 918 | " # Close current Row\n", 919 | " last.right = head[currentRow]\n", 920 | " currentRow = t.row\n", 921 | " last = head[currentRow]\n", 922 | " \n", 923 | " # End of if\n", 924 | " last = last.right = MatrixNode(False, t) # Link new node into row list\n", 925 | " head[t.col].next_ = head[t.col].down = last # Link into column list\n", 926 | " \n", 927 | " # End of for\n", 928 | " last.right = head[currentRow] # Close last row\n", 929 | " \n", 930 | " for i in range(s.col):\n", 931 | " head[i].next_.down = head[i] # Close all column lists\n", 932 | " \n", 933 | " # Link the header nodes together\n", 934 | " for i in range(p-1):\n", 935 | " head[i].next_ = head[i+1]\n", 936 | " \n", 937 | " head[p-1].next = matrix.headnode\n", 938 | " matrix.headnode.right = head[0]\n", 939 | " \n", 940 | " return\n", 941 | " \n", 942 | " else:\n", 943 | " for k, v in list(globals().iteritems()):\n", 944 | " if (id(v) == id(matrix)) and (k != \"matrix\"):\n", 945 | " globals()[k] = raw_input()\n", 946 | " return\n", 947 | " \n", 948 | "#A new MyStdIn Class inheriting the elements of stdin [InStream Object Class] is created with the \n", 949 | "#overloaded operator function __rshift__. \n", 950 | "\n", 951 | "#Operator >> is specified as a function __rshift__() [Equivalent to c++ style 'operator>>']" 952 | ], 953 | "language": "python", 954 | "metadata": {}, 955 | "outputs": [], 956 | "prompt_number": 25 957 | }, 958 | { 959 | "cell_type": "code", 960 | "collapsed": false, 961 | "input": [ 962 | "# So to emulate a C++ style cin we can have :\n", 963 | "\n", 964 | "print \"Standard input\"\n", 965 | "cin = MyStdIn()\n", 966 | "a = 'Text Before' # Otherwise NameError is raised; This is similar to declarations in C++\n", 967 | "cin>>a\n", 968 | "print type(a), a" 969 | ], 970 | "language": "python", 971 | "metadata": {}, 972 | "outputs": [ 973 | { 974 | "output_type": "stream", 975 | "stream": "stdout", 976 | "text": [ 977 | "Standard input\n" 978 | ] 979 | }, 980 | { 981 | "name": "stdout", 982 | "output_type": "stream", 983 | "stream": "stdout", 984 | "text": [ 985 | "New Text\n" 986 | ] 987 | }, 988 | { 989 | "output_type": "stream", 990 | "stream": "stdout", 991 | "text": [ 992 | " New Text\n" 993 | ] 994 | } 995 | ], 996 | "prompt_number": 26 997 | }, 998 | { 999 | "cell_type": "code", 1000 | "collapsed": false, 1001 | "input": [ 1002 | "print \"\\nMatrix Input\"\n", 1003 | "# For a Matrix we have:\n", 1004 | "m = Matrix()\n", 1005 | "# Matrix input is Given as :\n", 1006 | "# NUM_ROW NUM_COL NUM_NON_ZERO_ELEMENTS\n", 1007 | "# ROW COL VALUE\n", 1008 | "# ROW COL VALUE\n", 1009 | "# .\n", 1010 | "# .\n", 1011 | "# .\n", 1012 | "# .\n", 1013 | "\n", 1014 | "cin>>m # Refer Page 220 for Input format\n", 1015 | "\n", 1016 | "# Matrix Input\n", 1017 | "# 2 2 2\n", 1018 | "# 1 1 2\n", 1019 | "# 1 0 4\n", 1020 | "\n", 1021 | "print \"\\nFirst Element of the Matrix: \",\n", 1022 | "first_cell = m.headnode.right.down.triple\n", 1023 | "print (first_cell.row, first_cell.col, first_cell.value)" 1024 | ], 1025 | "language": "python", 1026 | "metadata": {}, 1027 | "outputs": [ 1028 | { 1029 | "output_type": "stream", 1030 | "stream": "stdout", 1031 | "text": [ 1032 | "\n", 1033 | "Matrix Input\n" 1034 | ] 1035 | }, 1036 | { 1037 | "name": "stdout", 1038 | "output_type": "stream", 1039 | "stream": "stdout", 1040 | "text": [ 1041 | "2 2 2\n" 1042 | ] 1043 | }, 1044 | { 1045 | "name": "stdout", 1046 | "output_type": "stream", 1047 | "stream": "stdout", 1048 | "text": [ 1049 | "1 1 2\n" 1050 | ] 1051 | }, 1052 | { 1053 | "name": "stdout", 1054 | "output_type": "stream", 1055 | "stream": "stdout", 1056 | "text": [ 1057 | "1 0 4\n" 1058 | ] 1059 | }, 1060 | { 1061 | "output_type": "stream", 1062 | "stream": "stdout", 1063 | "text": [ 1064 | "\n", 1065 | "First Element of the Matrix: (1, 0, 4)\n" 1066 | ] 1067 | } 1068 | ], 1069 | "prompt_number": 27 1070 | }, 1071 | { 1072 | "cell_type": "heading", 1073 | "level": 2, 1074 | "metadata": {}, 1075 | "source": [ 1076 | "PROGRAM 4.31, PAGE 222" 1077 | ] 1078 | }, 1079 | { 1080 | "cell_type": "code", 1081 | "collapsed": false, 1082 | "input": [ 1083 | "def _del(self):\n", 1084 | " # Return all nodes to the av list. This list is a chain linked via the right field.\n", 1085 | " # av is a static variable that points to the first node of the av list.\n", 1086 | " if self.headnode is None:\n", 1087 | " return # No nodes to delete\n", 1088 | " \n", 1089 | " x = self.headnode.right\n", 1090 | " self.headnode.right = self.av\n", 1091 | " self.av = self.headnode # Return headnode\n", 1092 | " \n", 1093 | " while x!=self.headnode:\n", 1094 | " # Erase by rows\n", 1095 | " y = x.right\n", 1096 | " x.right = self.av\n", 1097 | " self.av = y\n", 1098 | " x = x.next_ # Next row\n", 1099 | " \n", 1100 | " self.headnode = None\n", 1101 | "\n", 1102 | "Matrix.__del__ = _del" 1103 | ], 1104 | "language": "python", 1105 | "metadata": {}, 1106 | "outputs": [], 1107 | "prompt_number": 28 1108 | }, 1109 | { 1110 | "cell_type": "heading", 1111 | "level": 2, 1112 | "metadata": {}, 1113 | "source": [ 1114 | "PROGRAM 4.32, PAGE 226" 1115 | ] 1116 | }, 1117 | { 1118 | "cell_type": "code", 1119 | "collapsed": false, 1120 | "input": [ 1121 | "# Class definition of a doubly linked list\n", 1122 | "\n", 1123 | "class DblListNode:\n", 1124 | " def __init__(self):\n", 1125 | " self.data = None\n", 1126 | " self.left = self.right = None\n", 1127 | " \n", 1128 | "class DblList:\n", 1129 | " def __init__(self):\n", 1130 | " self.first = DblListNode()" 1131 | ], 1132 | "language": "python", 1133 | "metadata": {}, 1134 | "outputs": [], 1135 | "prompt_number": 29 1136 | }, 1137 | { 1138 | "cell_type": "heading", 1139 | "level": 2, 1140 | "metadata": {}, 1141 | "source": [ 1142 | "PROGRAM 4.33, PAGE 227" 1143 | ] 1144 | }, 1145 | { 1146 | "cell_type": "code", 1147 | "collapsed": false, 1148 | "input": [ 1149 | "# Deleting from a doubly linked circular list\n", 1150 | "def _delete(self, x):\n", 1151 | " if x == self.first:\n", 1152 | " raise(Exception(\"Deletion of header node is not permitted\"))\n", 1153 | " else:\n", 1154 | " x.left.right = x.right\n", 1155 | " x.right.left = x.left\n", 1156 | " \n", 1157 | "DblList.Delete = _delete" 1158 | ], 1159 | "language": "python", 1160 | "metadata": {}, 1161 | "outputs": [], 1162 | "prompt_number": 30 1163 | }, 1164 | { 1165 | "cell_type": "heading", 1166 | "level": 2, 1167 | "metadata": {}, 1168 | "source": [ 1169 | "PROGRAM 4.34, PAGE 227" 1170 | ] 1171 | }, 1172 | { 1173 | "cell_type": "code", 1174 | "collapsed": false, 1175 | "input": [ 1176 | "# Insertion into a doubly linked circular list\n", 1177 | "def _insert(self, p, x):\n", 1178 | " \"\"\" Insert into node p to the right of node x \"\"\"\n", 1179 | " p.left = x; p.right = x.right\n", 1180 | " x.right.left = p; x.right = p" 1181 | ], 1182 | "language": "python", 1183 | "metadata": {}, 1184 | "outputs": [], 1185 | "prompt_number": 31 1186 | }, 1187 | { 1188 | "cell_type": "heading", 1189 | "level": 2, 1190 | "metadata": {}, 1191 | "source": [ 1192 | "PROGRAM 4.35, PAGE 233" 1193 | ] 1194 | }, 1195 | { 1196 | "cell_type": "code", 1197 | "collapsed": false, 1198 | "input": [ 1199 | "# Copying a list\n", 1200 | "# Driver\n", 1201 | "\n", 1202 | "# Class Definition for GenList - Refer Page 231\n", 1203 | "class GenList:\n", 1204 | " def __init__(self):\n", 1205 | " self.first = GenListNode()\n", 1206 | "\n", 1207 | "class GenListNode:\n", 1208 | " def __init__(self):\n", 1209 | " self.tag = False\n", 1210 | " self.data = None\n", 1211 | " self.down = None\n", 1212 | " \n", 1213 | " self.ref = 0 # Refer Page 238\n", 1214 | " self.next_ = None\n", 1215 | "\n", 1216 | "def _copy(self, l):\n", 1217 | " \"\"\"Make a copy of l\"\"\"\n", 1218 | " if isinstance(l, GenList):\n", 1219 | " self.first = self.Copy(l.first)\n", 1220 | " return None\n", 1221 | " else:\n", 1222 | " q = None\n", 1223 | " if l is not None:\n", 1224 | " q = GenListNode()\n", 1225 | " q.tag = p.tag\n", 1226 | " if p.tag:\n", 1227 | " q.down = Copy(p.down)\n", 1228 | " else:\n", 1229 | " q.data = p.data\n", 1230 | " \n", 1231 | " q.next_ = self.Copy(p.next_)\n", 1232 | " return q\n", 1233 | " \n", 1234 | "GenList.Copy = _copy" 1235 | ], 1236 | "language": "python", 1237 | "metadata": {}, 1238 | "outputs": [], 1239 | "prompt_number": 32 1240 | }, 1241 | { 1242 | "cell_type": "heading", 1243 | "level": 2, 1244 | "metadata": {}, 1245 | "source": [ 1246 | "PROGRAM 4.36, PAGE 235" 1247 | ] 1248 | }, 1249 | { 1250 | "cell_type": "code", 1251 | "collapsed": false, 1252 | "input": [ 1253 | "# Determining if two lists are identical\n", 1254 | "\n", 1255 | "def _eq(self, l):\n", 1256 | " return self.Equal(self, l)\n", 1257 | "\n", 1258 | "def _equal(self, s, l):\n", 1259 | " if ( s is None ) and ( t is None ):\n", 1260 | " return True\n", 1261 | " if ( s and t and ( s.tag == t.tag )):\n", 1262 | " if s.tag:\n", 1263 | " return self.Equal(s.down, t.down) and self.Equal(s.next_ and t.next_)\n", 1264 | " else:\n", 1265 | " return ( s.data == t.data ) and self.Equal(s.next_, t.next_)\n", 1266 | " return False\n", 1267 | "\n", 1268 | "GenList.__eq__ = _eq # Overloading the equality operator.\n", 1269 | "GenList.Equal = _equal" 1270 | ], 1271 | "language": "python", 1272 | "metadata": {}, 1273 | "outputs": [], 1274 | "prompt_number": 33 1275 | }, 1276 | { 1277 | "cell_type": "heading", 1278 | "level": 2, 1279 | "metadata": {}, 1280 | "source": [ 1281 | "PROGRAM 4.37, PAGE 236" 1282 | ] 1283 | }, 1284 | { 1285 | "cell_type": "code", 1286 | "collapsed": false, 1287 | "input": [ 1288 | "# Driver\n", 1289 | "def _depth(self, s = -1):\n", 1290 | " if s == -1: # Pseudo - Function overloading\n", 1291 | " return Depth(first)\n", 1292 | " else:\n", 1293 | " # Workhorse\n", 1294 | " if s is None:\n", 1295 | " return None\n", 1296 | " \n", 1297 | " current = s\n", 1298 | " m = 0\n", 1299 | " \n", 1300 | " while current is not None:\n", 1301 | " if current.tag:\n", 1302 | " m = max(m, Depth(current.down))\n", 1303 | " current = current.next_\n", 1304 | " \n", 1305 | " return m+1\n", 1306 | "GenList.Depth = _depth" 1307 | ], 1308 | "language": "python", 1309 | "metadata": {}, 1310 | "outputs": [], 1311 | "prompt_number": 35 1312 | }, 1313 | { 1314 | "cell_type": "heading", 1315 | "level": 2, 1316 | "metadata": {}, 1317 | "source": [ 1318 | "PROGRAM 4.38, PAGE 239" 1319 | ] 1320 | }, 1321 | { 1322 | "cell_type": "code", 1323 | "collapsed": false, 1324 | "input": [ 1325 | "# Deleting a list recursively\n", 1326 | "# Driver\n", 1327 | "\n", 1328 | "def _del(self, *inputs):\n", 1329 | " \n", 1330 | " if len(inputs == 0):\n", 1331 | " if first is None:\n", 1332 | " self.Delete(first)\n", 1333 | " first = None\n", 1334 | " return\n", 1335 | " \n", 1336 | " x = inputs[0] # Pseudo Function Overloading\n", 1337 | " \n", 1338 | " x.ref -= x.ref\n", 1339 | " if x.ref != 0:\n", 1340 | " y = x\n", 1341 | " while y.next_ is not None:\n", 1342 | " y = y.next_\n", 1343 | " if y.tag == 1:\n", 1344 | " self.Delete(y.down)\n", 1345 | " y.next_ = self.av # Attach top level node to av list\n", 1346 | " self.av = x" 1347 | ], 1348 | "language": "python", 1349 | "metadata": {}, 1350 | "outputs": [], 1351 | "prompt_number": 36 1352 | } 1353 | ], 1354 | "metadata": {} 1355 | } 1356 | ] 1357 | } -------------------------------------------------------------------------------- /Chapter 5 - Trees.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:5cc4b5e6a2febd3f429cdf773534797f97f475f334b5aa008a5d343d7754ac24" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "heading", 13 | "level": 2, 14 | "metadata": {}, 15 | "source": [ 16 | "Class Definition for Tree and TreeNode - Page 252, Page 257" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "collapsed": false, 22 | "input": [ 23 | "# Binary Tree Class\n", 24 | "\n", 25 | "class TreeNode(object):\n", 26 | " def __init__(self, left = None, data = None, right = None):\n", 27 | " \"\"\" Create a new TreeNode \"\"\"\n", 28 | " self.data = data\n", 29 | " self.rightChild = right\n", 30 | " self.leftChild = left \n", 31 | "\n", 32 | " \n", 33 | "class Tree(object):\n", 34 | " def __init__(self, root = None ):\n", 35 | " # This implementation differs from the Textbook definition\n", 36 | " # Here Tree is an encapsulation of the root\n", 37 | " # root is a Binary Tree formed by the Linking together TreeNodes\n", 38 | " # This will avoid confusion between Tree and TreeNode\n", 39 | " \n", 40 | " \"\"\" Create a new Binary Tree \"\"\"\n", 41 | " self.root = root\n", 42 | " \n", 43 | " def LeftSubtree(self):\n", 44 | " \"\"\" Return Left Sub Tree \"\"\"\n", 45 | " return self.root.rightChild\n", 46 | " \n", 47 | " def RightSubtree(self):\n", 48 | " \"\"\" Return Right Sub Tree \"\"\"\n", 49 | " return self.root.leftChild\n", 50 | " \n", 51 | " def RootData(self):\n", 52 | " \"\"\" Return the root data \"\"\"\n", 53 | " return self.root.data\n", 54 | " \n", 55 | " def IsEmpty(self):\n", 56 | " \"\"\" Returns True if Tree Node is empty \"\"\"\n", 57 | " return self.root is None" 58 | ], 59 | "language": "python", 60 | "metadata": {}, 61 | "outputs": [], 62 | "prompt_number": 1 63 | }, 64 | { 65 | "cell_type": "heading", 66 | "level": 2, 67 | "metadata": {}, 68 | "source": [ 69 | "PROGRAM 5.1, PAGE 261" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "collapsed": false, 75 | "input": [ 76 | "# Inorder Traversal of a binary Tree\n", 77 | "\n", 78 | "def _inorder(self, currentNode = -1):\n", 79 | " if currentNode != -1:\n", 80 | " if currentNode is not None:\n", 81 | " self.Inorder(currentNode.leftChild)\n", 82 | " self.Visit(currentNode)\n", 83 | " self.Inorder(currentNode.rightChild)\n", 84 | " \n", 85 | " elif self.root is None:\n", 86 | " return None\n", 87 | " \n", 88 | " else:\n", 89 | " self.Inorder(self.root)\n", 90 | " \n", 91 | "def _visit(self, Node):\n", 92 | " print \"\" if Node is None else Node.data,\n", 93 | "\n", 94 | "Tree.Inorder = _inorder\n", 95 | "Tree.Visit = _visit" 96 | ], 97 | "language": "python", 98 | "metadata": {}, 99 | "outputs": [], 100 | "prompt_number": 2 101 | }, 102 | { 103 | "cell_type": "heading", 104 | "level": 2, 105 | "metadata": {}, 106 | "source": [ 107 | "PROGRAM 5.2, PAGE 263" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "collapsed": false, 113 | "input": [ 114 | "# Preorder traversal of a binary tree\n", 115 | "\n", 116 | "def _preorder(self, currentNode = -1):\n", 117 | " if currentNode != -1:\n", 118 | " if currentNode is not None:\n", 119 | " self.Visit(currentNode)\n", 120 | " self.Preorder(currentNode.leftChild) \n", 121 | " self.Preorder(currentNode.rightChild)\n", 122 | " \n", 123 | " elif self.root is None:\n", 124 | " return None\n", 125 | " \n", 126 | " else:\n", 127 | " self.Preorder(self.root)\n", 128 | " \n", 129 | "Tree.Preorder = _preorder" 130 | ], 131 | "language": "python", 132 | "metadata": {}, 133 | "outputs": [], 134 | "prompt_number": 3 135 | }, 136 | { 137 | "cell_type": "heading", 138 | "level": 2, 139 | "metadata": {}, 140 | "source": [ 141 | "PROGRAM 5.3, PAGE 263" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "collapsed": false, 147 | "input": [ 148 | "# Postorder traversal of a binary tree\n", 149 | "\n", 150 | "def _postorder(self, currentNode = -1):\n", 151 | " if currentNode != -1:\n", 152 | " if currentNode is not None:\n", 153 | " self.Postorder(currentNode.leftChild) \n", 154 | " self.Postorder(currentNode.rightChild)\n", 155 | " self.Visit(currentNode) \n", 156 | "\n", 157 | " elif self.root is None:\n", 158 | " return None\n", 159 | " \n", 160 | " else:\n", 161 | " return self.Postorder(self.root)\n", 162 | "\n", 163 | "Tree.Postorder = _postorder" 164 | ], 165 | "language": "python", 166 | "metadata": {}, 167 | "outputs": [], 168 | "prompt_number": 4 169 | }, 170 | { 171 | "cell_type": "heading", 172 | "level": 2, 173 | "metadata": {}, 174 | "source": [ 175 | "PROGRAM 5.4, PAGE 264" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "collapsed": false, 181 | "input": [ 182 | "# Non recursive inorder traversal\n", 183 | "\n", 184 | "def _nonrecInorder(self):\n", 185 | " \"\"\" Non Recursive inorder traversal using a stack \"\"\"\n", 186 | " s = [] # Using Python List as a stack\n", 187 | " currentNode = self.root\n", 188 | " while True:\n", 189 | " while currentNode is not None: # move down leftChild field\n", 190 | " s.append(currentNode) # add to stack\n", 191 | " currentNode = currentNode.leftChild\n", 192 | " if len(s) == 0:\n", 193 | " return\n", 194 | " \n", 195 | " currentNode = s[-1]\n", 196 | " s.pop() # delete from the stack\n", 197 | " self.Visit(currentNode)\n", 198 | " currentNode = currentNode.rightChild\n", 199 | " \n", 200 | "Tree.NonrecInorder = _nonrecInorder" 201 | ], 202 | "language": "python", 203 | "metadata": {}, 204 | "outputs": [], 205 | "prompt_number": 5 206 | }, 207 | { 208 | "cell_type": "heading", 209 | "level": 2, 210 | "metadata": {}, 211 | "source": [ 212 | "PROGRAM 5.5, PAGE 265" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "collapsed": false, 218 | "input": [ 219 | "# Definition of a simple inorder iterator\n", 220 | "\n", 221 | "# In Python it is possible to return an iterable of the object using the iter() method\n", 222 | "# The __iter__() is overloaded to provide custom definition\n", 223 | "\n", 224 | "def _iter(self):\n", 225 | " return self\n", 226 | "\n", 227 | "Tree.__iter__ = _iter\n", 228 | "\n", 229 | "# iter(Tree) will return an iterable whose definition is defined in PROGRAM 5.6 \n", 230 | "# This also works using for\n", 231 | "# for inorder_node in tree1:\n", 232 | "# " 233 | ], 234 | "language": "python", 235 | "metadata": {}, 236 | "outputs": [], 237 | "prompt_number": 6 238 | }, 239 | { 240 | "cell_type": "heading", 241 | "level": 2, 242 | "metadata": {}, 243 | "source": [ 244 | "PROGRAM 5.6, PAGE 265" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "collapsed": false, 250 | "input": [ 251 | "# Code for obtaining the next inorder element\n", 252 | "def _next(self):\n", 253 | " if \"s\" not in self.next.__dict__:\n", 254 | " # During every 1st iteration :\n", 255 | " \n", 256 | " self.next.__dict__[\"s\"] = list() # Define an empty list\n", 257 | " # Python equivalent of a C++ static list variable s\n", 258 | " \n", 259 | " if \"currentNode\" not in self.next.__dict__:\n", 260 | " self.next.__dict__[\"currentNode\"] = self.root\n", 261 | " \n", 262 | " while self.next.currentNode is not None:\n", 263 | " self.next.s.append(self.next.currentNode)\n", 264 | " self.next.__dict__[\"currentNode\"] = self.next.currentNode.leftChild\n", 265 | " \n", 266 | " if len(self.next.s) == 0:\n", 267 | " self.next.__dict__.pop(\"s\")\n", 268 | " self.next.__dict__.pop(\"currentNode\")\n", 269 | " raise StopIteration\n", 270 | " \n", 271 | " self.next.__dict__[\"currentNode\"] = self.next.s.pop()\n", 272 | " \n", 273 | " temp = self.next.currentNode.data\n", 274 | " \n", 275 | " self.next.__dict__[\"currentNode\"] = self.next.currentNode.rightChild\n", 276 | " \n", 277 | " return temp\n", 278 | "\n", 279 | "Tree.next = _next\n", 280 | "\n", 281 | "# A more simpler Python way to iterate over the tree elements in inorder traversal is by using the generator\n", 282 | "# Not given in Text Book\n", 283 | "\n", 284 | "def _InorderIterator(self, tree = -1):\n", 285 | " if tree == -1:\n", 286 | " tree = self.root\n", 287 | " \n", 288 | " if tree is not None:\n", 289 | " for node in self.InorderIterator(tree.leftChild):\n", 290 | " yield node\n", 291 | " \n", 292 | " yield tree.data\n", 293 | " \n", 294 | " for node in self.InorderIterator(tree.rightChild):\n", 295 | " yield node\n", 296 | " \n", 297 | "Tree.InorderIterator = _InorderIterator" 298 | ], 299 | "language": "python", 300 | "metadata": {}, 301 | "outputs": [], 302 | "prompt_number": 7 303 | }, 304 | { 305 | "cell_type": "heading", 306 | "level": 2, 307 | "metadata": {}, 308 | "source": [ 309 | "PROGRAM 5.7, PAGE 266" 310 | ] 311 | }, 312 | { 313 | "cell_type": "code", 314 | "collapsed": false, 315 | "input": [ 316 | "# Level order traversal of Binary tree\n", 317 | "\n", 318 | "def _LevelOrder(self):\n", 319 | " \n", 320 | " q = list() # Using a list as a queue\n", 321 | " currentNode = self.root\n", 322 | " \n", 323 | " while currentNode is not None:\n", 324 | " self.Visit(currentNode)\n", 325 | "\n", 326 | " if currentNode.leftChild:\n", 327 | " q.append(currentNode.leftChild)\n", 328 | " if currentNode.rightChild:\n", 329 | " q.append(currentNode.rightChild)\n", 330 | " if len(q) == 0:\n", 331 | " return\n", 332 | " \n", 333 | " currentNode = q.pop()\n", 334 | " \n", 335 | "Tree.LevelOrder = _LevelOrder" 336 | ], 337 | "language": "python", 338 | "metadata": {}, 339 | "outputs": [], 340 | "prompt_number": 8 341 | }, 342 | { 343 | "cell_type": "code", 344 | "collapsed": false, 345 | "input": [ 346 | "# Sample Example to Showcase Working of Tree and its functions defined so far\n", 347 | "# ( NOT IN TEXTBOOK )\n", 348 | "# Tree Example Diagram @ http://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Binary_tree.svg/300px-Binary_tree.svg.png\n", 349 | "\n", 350 | "# Defining Height = 0 Nodes ( Leafs ):\n", 351 | "\n", 352 | "h0_1 = TreeNode(None, 5, None)\n", 353 | "h0_2 = TreeNode(None, 11, None)\n", 354 | "h0_3 = TreeNode(None, 4, None)\n", 355 | "\n", 356 | "# Defining Height = 1 Nodes ( Subtrees and one leaf - h1_1):\n", 357 | "\n", 358 | "h1_1 = TreeNode(None, 2, None)\n", 359 | "h1_2 = TreeNode(h0_1, 6, h0_2)\n", 360 | "h1_3 = TreeNode(h0_3, 9, None)\n", 361 | "\n", 362 | "# Defining Height = 2 Nodes ( Subtrees ):\n", 363 | "\n", 364 | "h2_1 = TreeNode(h1_1, 7, h1_2)\n", 365 | "h2_2 = TreeNode(None, 5, h1_3)\n", 366 | "\n", 367 | "# Defining Height = 3 Node ( root ):\n", 368 | "\n", 369 | "h3_1 = TreeNode(h2_1, 2, h2_2)\n", 370 | "\n", 371 | "tree1 = Tree(h3_1)\n", 372 | "\n", 373 | "print \"inorder iteration using next() definition ( as provided in the TextBook )\\n\"\n", 374 | "\n", 375 | "for i in tree1:\n", 376 | " print i,\n", 377 | " \n", 378 | "print \"\\n\\nInorderIterator using Generator function\\n\"\n", 379 | "\n", 380 | "for i in tree1.InorderIterator():\n", 381 | " print i, \n", 382 | " \n", 383 | "print \"\\n\\nPost order traversal using function Postorder()\\n\"\n", 384 | "\n", 385 | "tree1.Postorder()\n", 386 | "\n", 387 | "print \"\\n\\nPre order traversal using function Preorder()\\n\"\n", 388 | "\n", 389 | "tree1.Preorder()\n", 390 | "\n", 391 | "print \"\\n\\nIn order traversal using function Inorder()\\n\"\n", 392 | "\n", 393 | "tree1.Inorder()\n", 394 | "\n", 395 | "print \"\\n\\nIn order traversal using function NonrecInorder()\\n\"\n", 396 | "\n", 397 | "tree1.NonrecInorder()\n", 398 | "\n", 399 | "print \"\\n\\nLevel order traversal using function LevelOrder()\\n\"\n", 400 | "\n", 401 | "tree1.LevelOrder()" 402 | ], 403 | "language": "python", 404 | "metadata": {}, 405 | "outputs": [ 406 | { 407 | "output_type": "stream", 408 | "stream": "stdout", 409 | "text": [ 410 | "inorder iteration using next() definition ( as provided in the TextBook )\n", 411 | "\n", 412 | "2 7 5 6 11 2 5 4 9 \n", 413 | "\n", 414 | "InorderIterator using Generator function\n", 415 | "\n", 416 | "2 7 5 6 11 2 5 4 9 \n", 417 | "\n", 418 | "Post order traversal using function Postorder()\n", 419 | "\n", 420 | "2 5 11 6 7 4 9 5 2 \n", 421 | "\n", 422 | "Pre order traversal using function Preorder()\n", 423 | "\n", 424 | "2 7 2 6 5 11 5 9 4 \n", 425 | "\n", 426 | "In order traversal using function Inorder()\n", 427 | "\n", 428 | "2 7 5 6 11 2 5 4 9 \n", 429 | "\n", 430 | "In order traversal using function NonrecInorder()\n", 431 | "\n", 432 | "2 7 5 6 11 2 5 4 9 \n", 433 | "\n", 434 | "Level order traversal using function LevelOrder()\n", 435 | "\n", 436 | "2 5 9 4 7 6 11 5 2\n" 437 | ] 438 | } 439 | ], 440 | "prompt_number": 9 441 | }, 442 | { 443 | "cell_type": "heading", 444 | "level": 2, 445 | "metadata": {}, 446 | "source": [ 447 | "PROGRAM 5.8, PAGE 269" 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "collapsed": false, 453 | "input": [ 454 | "# O(1) space inorder traversal\n", 455 | "\n", 456 | "def _NoStackInorder(self):\n", 457 | " # Inorder traversal of Binary Tree using a fixed amount of additional storage\n", 458 | " if self.root is None:\n", 459 | " return\n", 460 | "\n", 461 | " top = lastRight = p = q = r = r1 = None\n", 462 | " p = q = self.root\n", 463 | " while True:\n", 464 | " while True:\n", 465 | " if ( p.leftChild is None ) and ( p.rightChild is None ):\n", 466 | " # Leaf Node\n", 467 | " self.Visit(p)\n", 468 | " break\n", 469 | "\n", 470 | " elif p.leftChild is None:\n", 471 | " # Visit p and move to p.rightChild\n", 472 | " self.Visit(p)\n", 473 | " r = p.rightChild\n", 474 | " p.rightChild = q\n", 475 | " q = p\n", 476 | " p = r\n", 477 | " \n", 478 | " else:\n", 479 | " # move to p.leftChild\n", 480 | " r = p.leftChild\n", 481 | " p.leftChild = q\n", 482 | " q = p\n", 483 | " p = r\n", 484 | "\n", 485 | " # p is a leaf node move upward to a node whose right subtree has not yet been examined\n", 486 | " av = p\n", 487 | " while True:\n", 488 | " if p == self.root:\n", 489 | " return None\n", 490 | "\n", 491 | " if q.leftChild is None:\n", 492 | " # q is linked via rightChild\n", 493 | " r = q.rightChild\n", 494 | " q.rightChild = p\n", 495 | " p = q\n", 496 | " q = r\n", 497 | "\n", 498 | " elif q.rightChild is None:\n", 499 | " # q is linked via leftChild\n", 500 | " r = q.leftChild\n", 501 | " q.leftChild = p\n", 502 | " p = q\n", 503 | " q = r\n", 504 | "\n", 505 | " self.Visit(p)\n", 506 | "\n", 507 | " else:\n", 508 | " # Check if p is a rightChild of q\n", 509 | " if q == lastRight:\n", 510 | " r = top\n", 511 | " lastRight = r.leftChild\n", 512 | " top = r.rightChild # unstack\n", 513 | " r.leftChild = r.rightChild = None\n", 514 | " r = q.rightChild\n", 515 | " q.rightChild = p\n", 516 | " p = q\n", 517 | " q = r\n", 518 | "\n", 519 | " else:\n", 520 | " # p is leftChild of q\n", 521 | " self.Visit(q)\n", 522 | " av.leftChild = lastRight\n", 523 | " av.rightChild = top\n", 524 | " top = av\n", 525 | " lastRight = q\n", 526 | " r = q.leftChild\n", 527 | " q.leftChild = p # Restore link to p\n", 528 | " \n", 529 | " r1 = q.rightChild\n", 530 | " q.rightChild = r\n", 531 | " p = r1\n", 532 | "\n", 533 | " break\n", 534 | "\n", 535 | "Tree.NoStackInorder = _NoStackInorder" 536 | ], 537 | "language": "python", 538 | "metadata": {}, 539 | "outputs": [], 540 | "prompt_number": 10 541 | }, 542 | { 543 | "cell_type": "code", 544 | "collapsed": false, 545 | "input": [ 546 | "# Sample Output ( NOT IN TEXTBOOK )\n", 547 | "tree1.NoStackInorder()" 548 | ], 549 | "language": "python", 550 | "metadata": {}, 551 | "outputs": [ 552 | { 553 | "output_type": "stream", 554 | "stream": "stdout", 555 | "text": [ 556 | "2 7 5 6 11 2 5 4 9\n" 557 | ] 558 | } 559 | ], 560 | "prompt_number": 11 561 | }, 562 | { 563 | "cell_type": "heading", 564 | "level": 2, 565 | "metadata": {}, 566 | "source": [ 567 | "PROGRAM 5.9, PAGE 270" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "collapsed": false, 573 | "input": [ 574 | "# Copying a binary tree.\n", 575 | "\n", 576 | "# Overloading __init__ to provide copy constructor like functionality\n", 577 | "\n", 578 | "def _init(self, copy_from = None):\n", 579 | " # This implementation differs from the Textbook definition\n", 580 | " # Here Tree is an encapsulation of the root\n", 581 | " # root is a Binary Tree formed by the Linking together TreeNodes\n", 582 | " # This will avoid confusion between Tree and TreeNode\n", 583 | " \"\"\" Create a new Binary Tree \"\"\"\n", 584 | " \n", 585 | " # if the copy_from is a Tree Class object\n", 586 | " if isinstance(copy_from, Tree):\n", 587 | " self.root = self.Copy(copy_from.root)\n", 588 | " \n", 589 | " # if the copy_from is a root ( TreeNode object )\n", 590 | " else:\n", 591 | " self.root = copy_from\n", 592 | " # This also copies None to root if passed\n", 593 | " \n", 594 | "Tree.__init__ = _init\n", 595 | "\n", 596 | "def _Copy(self, origNode):\n", 597 | " # Workhorse which recursively copies the whole binary tree.\n", 598 | " \n", 599 | " # Return a pointer to an exact copy of the binary tree rooted at origNode\n", 600 | " \n", 601 | " if origNode is None:\n", 602 | " return None\n", 603 | " \n", 604 | " return TreeNode(self.Copy(origNode.leftChild), origNode.data, self.Copy(origNode.rightChild))\n", 605 | "\n", 606 | "Tree.Copy = _Copy" 607 | ], 608 | "language": "python", 609 | "metadata": {}, 610 | "outputs": [], 611 | "prompt_number": 12 612 | }, 613 | { 614 | "cell_type": "heading", 615 | "level": 2, 616 | "metadata": {}, 617 | "source": [ 618 | "PROGRAM 5.10, PAGE 270" 619 | ] 620 | }, 621 | { 622 | "cell_type": "code", 623 | "collapsed": false, 624 | "input": [ 625 | "# Binary tree equivalence\n", 626 | "\n", 627 | "def _eq(self, t):\n", 628 | " if isinstance(t, Tree):\n", 629 | " return self.Equal(self.root, t.root)\n", 630 | "\n", 631 | "Tree.__eq__ = _eq\n", 632 | " \n", 633 | "def _Equal(self, a, b):\n", 634 | " # Workhorse which recursively checks for equivalence\n", 635 | " if (a is None) and (b is None):\n", 636 | " return True\n", 637 | " \n", 638 | " # Return True if :\n", 639 | " # Both a and b are not None\n", 640 | " # Data is same\n", 641 | " # left subtrees are equal\n", 642 | " # right subtrees are equal\n", 643 | " \n", 644 | " return ( a is not None ) and (b is not None ) and (a.data == b.data) and self.Equal(a.leftChild, b.leftChild) and self.Equal(a.rightChild, b.rightChild) \n", 645 | " \n", 646 | "Tree.Equal = _Equal\n" 647 | ], 648 | "language": "python", 649 | "metadata": {}, 650 | "outputs": [], 651 | "prompt_number": 13 652 | }, 653 | { 654 | "cell_type": "code", 655 | "collapsed": false, 656 | "input": [ 657 | "# Sample Output ( NOT IN TEXT BOOK )\n", 658 | "\n", 659 | "tree2 = Tree(tree1) # Copy from tree1 to tree2\n", 660 | "tree2.NoStackInorder()\n", 661 | "\n", 662 | "print \"\\n\\nBinary Tree Equivalence: \", tree2 == tree1\n", 663 | "\n", 664 | "tree3 = Tree(None) # Empty tree\n", 665 | "print \"\\n\\nBinary Tree Equivalence 2: \", tree1 == tree3" 666 | ], 667 | "language": "python", 668 | "metadata": {}, 669 | "outputs": [ 670 | { 671 | "output_type": "stream", 672 | "stream": "stdout", 673 | "text": [ 674 | "2 7 5 6 11 2 5 4 9 \n", 675 | "\n", 676 | "Binary Tree Equivalence: True\n", 677 | "\n", 678 | "\n", 679 | "Binary Tree Equivalence 2: False\n" 680 | ] 681 | } 682 | ], 683 | "prompt_number": 14 684 | }, 685 | { 686 | "cell_type": "heading", 687 | "level": 2, 688 | "metadata": {}, 689 | "source": [ 690 | "PROGRAM 5.12, PAGE 273" 691 | ] 692 | }, 693 | { 694 | "cell_type": "code", 695 | "collapsed": false, 696 | "input": [ 697 | "# Expression Tree definition ( NOT GIVEN IN THE TEXT BOOK )\n", 698 | "# This definition is not given in the text book but is assumed for the algorithm to work\n", 699 | "\n", 700 | "# Here the structure of TreeNode have been kept the same for ease of presentability of sample output\n", 701 | "# In the Text Book a different structure is presented with Nodes having twin data field\n", 702 | "\n", 703 | "class ExprTree(Tree):\n", 704 | " \n", 705 | " def evaluate(self, node = -1, variable_values = None):\n", 706 | " \"\"\" \n", 707 | " Evaluates the Tree for the given list of variable values \n", 708 | " \n", 709 | " USAGE:\n", 710 | " >>> t = ExprTree(root)\n", 711 | " >>> t.evaluate([1, 0, 0])\n", 712 | " 1\n", 713 | " \n", 714 | " \"\"\"\n", 715 | " # Exception handling\n", 716 | " if (node == -1) and (variable_values is None):\n", 717 | " raise Exception(\"Variable Value vector is not passed\")\n", 718 | " \n", 719 | " # Initializing\n", 720 | " elif node == -1:\n", 721 | " node = self.root\n", 722 | " \n", 723 | " \n", 724 | " # PROGRAM 5.12, PAGE 273\n", 725 | " # Visiting a Node in an Expression Tree\n", 726 | " \n", 727 | " var_list = self.getVariables()\n", 728 | " \n", 729 | " # If the node contains boolean data\n", 730 | " if node.data in [1, 0]:\n", 731 | " return bool(node)\n", 732 | " \n", 733 | " # If the node contains a variable\n", 734 | " if node.data in var_list:\n", 735 | " var_index = var_list.index(node.data)\n", 736 | " var_value = variable_values[var_index]\n", 737 | " \n", 738 | " return bool(var_value)\n", 739 | " \n", 740 | " # If the node is an operator\n", 741 | " elif node.data in [ '^', 'v', '~' ]:\n", 742 | " \n", 743 | " if node.data == '^':\n", 744 | " # And operator\n", 745 | " return self.evaluate(node.rightChild, variable_values) and self.evaluate(node.leftChild, variable_values)\n", 746 | " elif node.data == 'v':\n", 747 | " # Or operator\n", 748 | " return self.evaluate(node.rightChild, variable_values) or self.evaluate(node.leftChild, variable_values)\n", 749 | " elif node.data == '~':\n", 750 | " # Not operator\n", 751 | " return not self.evaluate(node.rightChild, variable_values)\n", 752 | " \n", 753 | " def getVariables(self, node = -1):\n", 754 | " # Defining a static var_list for storage of variables while recursing throught the tree\n", 755 | " \n", 756 | " if node is -1:\n", 757 | " node = self.root\n", 758 | " \n", 759 | " if node == self.root:\n", 760 | " self.getVariables.__dict__[\"var_list\"] = []\n", 761 | " \n", 762 | " if node is None:\n", 763 | " return\n", 764 | "\n", 765 | " # If the node contains a variable string and the variable is not already in the static var_list\n", 766 | " if ( node.data not in ['^', 'v', '~', 1, 0, True, False, None] ) and ( node.data not in self.getVariables.__dict__[\"var_list\"] ):\n", 767 | " self.getVariables.__dict__[\"var_list\"].append(node.data)\n", 768 | "\n", 769 | " self.getVariables(node.rightChild) # Parse the right subtree\n", 770 | " self.getVariables(node.leftChild) # Parse the left subtree\n", 771 | "\n", 772 | " var_list = sorted(self.getVariables.__dict__[\"var_list\"])\n", 773 | " \n", 774 | " if node == self.root:\n", 775 | " # Cleaning up the function namespace if the function returns back to the root node\n", 776 | " self.getVariables.__dict__.pop('var_list')\n", 777 | " \n", 778 | " # Return the list of variables\n", 779 | " return var_list\n", 780 | "\n", 781 | "# SAMPLE OUTPUT - Refer Tree Diagram - Figure 5.18, Page 272\n", 782 | "\n", 783 | "# Constructing the Expression Tree\n", 784 | "\n", 785 | "# Defining leaf Nodes:\n", 786 | "\n", 787 | "l1 = TreeNode(None, 'x1', None)\n", 788 | "l2 = TreeNode(None, 'x2', None)\n", 789 | "l3 = TreeNode(None, 'x3', None)\n", 790 | "\n", 791 | "o1 = TreeNode(None, '~', l2)\n", 792 | "o2 = TreeNode(l1, '^', o1)\n", 793 | "o3 = TreeNode(None, '~', l1)\n", 794 | "o4 = TreeNode(o3, '^', l3)\n", 795 | "\n", 796 | "o5 = TreeNode(o2, 'v', o4)\n", 797 | "o6 = TreeNode(None, '~', l3)\n", 798 | "\n", 799 | "o7 = TreeNode(o5, 'v', o6)\n", 800 | "\n", 801 | "exp = ExprTree(o7)\n", 802 | "\n", 803 | "print \"Inorder traversal : \"\n", 804 | "exp.Inorder()\n", 805 | "\n", 806 | "print \"\\n\\nThe variable list is : \"\n", 807 | "print exp.getVariables()\n", 808 | "\n", 809 | "print \"\\nEvaluating the expression for (1,1,1) : \",\n", 810 | "print exp.evaluate(variable_values = [1, 1, 1])\n", 811 | "\n", 812 | "print \"\\nEvaluating the expression for (1,0,1) : \",\n", 813 | "print exp.evaluate(variable_values = [1, 0, 1])\n" 814 | ], 815 | "language": "python", 816 | "metadata": {}, 817 | "outputs": [ 818 | { 819 | "output_type": "stream", 820 | "stream": "stdout", 821 | "text": [ 822 | "Inorder traversal : \n", 823 | "x1 ^ ~ x2 v ~ x1 ^ x3 v ~ x3 \n", 824 | "\n", 825 | "The variable list is : \n", 826 | "['x1', 'x2', 'x3']\n", 827 | "\n", 828 | "Evaluating the expression for (1,1,1) : False\n", 829 | "\n", 830 | "Evaluating the expression for (1,0,1) : True\n" 831 | ] 832 | } 833 | ], 834 | "prompt_number": 15 835 | }, 836 | { 837 | "cell_type": "heading", 838 | "level": 2, 839 | "metadata": {}, 840 | "source": [ 841 | "PROGRAM 5.11, PAGE 273" 842 | ] 843 | }, 844 | { 845 | "cell_type": "code", 846 | "collapsed": false, 847 | "input": [ 848 | "# First version of satisfiability algorithm\n", 849 | "\n", 850 | "def _Satisfiability(self):\n", 851 | " var_list = self.getVariables()\n", 852 | " \n", 853 | " no_of_vars = len(var_list)\n", 854 | " \n", 855 | " for i in range(no_of_vars):\n", 856 | " \n", 857 | " # Convert an integer to a binary string\n", 858 | " # 5 --> '0b101' --> '101' --> '0101'\n", 859 | " binary_i = (bin(i)[2:]).zfill(no_of_vars)\n", 860 | " \n", 861 | " # Convert a binary string to a vector of binary data\n", 862 | " # \"1111\" --> ['1', '1', '1', '1'] --> [1, 1, 1, 1]\n", 863 | " input_vector = map(int, list(binary_i))\n", 864 | " \n", 865 | " if self.evaluate(variable_values = input_vector):\n", 866 | " print input_vector\n", 867 | " return True\n", 868 | " \n", 869 | " print \"No satisfiable combination\"\n", 870 | " return False\n", 871 | "\n", 872 | "ExprTree.Satisfiability = _Satisfiability\n", 873 | "\n", 874 | "# Sample Output\n", 875 | "exp.Satisfiability()" 876 | ], 877 | "language": "python", 878 | "metadata": {}, 879 | "outputs": [ 880 | { 881 | "output_type": "stream", 882 | "stream": "stdout", 883 | "text": [ 884 | "[0, 0, 0]\n" 885 | ] 886 | }, 887 | { 888 | "metadata": {}, 889 | "output_type": "pyout", 890 | "prompt_number": 16, 891 | "text": [ 892 | "True" 893 | ] 894 | } 895 | ], 896 | "prompt_number": 16 897 | }, 898 | { 899 | "cell_type": "code", 900 | "collapsed": false, 901 | "input": [ 902 | "# Class Definition for ThreadedNode\n", 903 | "class ThreadedNode(TreeNode):\n", 904 | " def __init__(self):\n", 905 | " super(ThreadedNode, self).__init__()\n", 906 | " # Defining 2 new fields rightThread and leftThread\n", 907 | " self.rightThread = self.leftThread = None\n", 908 | " \n", 909 | "# Class Definition for ThreadedTree\n", 910 | "class ThreadedTree(ThreadedNode):\n", 911 | " def __init__(self):\n", 912 | " super(ThreadedTree, self).__init__()" 913 | ], 914 | "language": "python", 915 | "metadata": {}, 916 | "outputs": [], 917 | "prompt_number": 17 918 | }, 919 | { 920 | "cell_type": "heading", 921 | "level": 2, 922 | "metadata": {}, 923 | "source": [ 924 | "PROGRAM 5.13, PAGE 277" 925 | ] 926 | }, 927 | { 928 | "cell_type": "code", 929 | "collapsed": false, 930 | "input": [ 931 | "# Finding the inorder successor in a threaded binary tree\n", 932 | "def _ThreadedInorderIterator(self):\n", 933 | " \"\"\" Return the inorder successor of currentNode in a threaded binary tree \"\"\"\n", 934 | " temp = currentnode.rightChild\n", 935 | " \n", 936 | " if currentNode.rightThread is None:\n", 937 | " while temp.leftThread is None:\n", 938 | " temp = temp.leftChild\n", 939 | " \n", 940 | " currentNode = temp\n", 941 | " \n", 942 | " if currentNode == root:\n", 943 | " return None\n", 944 | " else:\n", 945 | " return currentNode.data\n", 946 | " \n", 947 | "ThreadedTree.ThreadedInorderIterator = _ThreadedInorderIterator" 948 | ], 949 | "language": "python", 950 | "metadata": {}, 951 | "outputs": [], 952 | "prompt_number": 18 953 | }, 954 | { 955 | "cell_type": "heading", 956 | "level": 2, 957 | "metadata": {}, 958 | "source": [ 959 | "PROGRAM 5.14, PAGE 279" 960 | ] 961 | }, 962 | { 963 | "cell_type": "code", 964 | "collapsed": false, 965 | "input": [ 966 | "# Inserting r as the right child of s\n", 967 | "\n", 968 | "def _InsertRight(s, r):\n", 969 | " \"\"\" Insert r as the right child of s \"\"\"\n", 970 | " r.rightChild = s.rightChild\n", 971 | " r.rightThread = s.rightThread\n", 972 | " r.leftChild = s\n", 973 | " r.leftThread = True # Left child is a thread\n", 974 | " s.rightChild = r\n", 975 | " s.rightThread = False\n", 976 | " if r.rightThread is None:\n", 977 | " temp = self.InorderSucc(r)\n", 978 | " # Returns the inorder successor of r\n", 979 | " temp.leftChild = r " 980 | ], 981 | "language": "python", 982 | "metadata": {}, 983 | "outputs": [], 984 | "prompt_number": 19 985 | }, 986 | { 987 | "cell_type": "heading", 988 | "level": 2, 989 | "metadata": {}, 990 | "source": [ 991 | "ADT 5.2, PAGE 280" 992 | ] 993 | }, 994 | { 995 | "cell_type": "code", 996 | "collapsed": false, 997 | "input": [ 998 | "# A max priority queue\n", 999 | "\n", 1000 | "# This defines the skeletal structure of a Max Priority Queue Class\n", 1001 | "\n", 1002 | "class MaxPQ(object):\n", 1003 | " def __init__(self):\n", 1004 | " pass\n", 1005 | " def IsEmpty(self):\n", 1006 | " # Returns true if the PQ is empty\n", 1007 | " pass\n", 1008 | " def Top(self):\n", 1009 | " # Returns the reference to the max element ( Max priority queue top element )\n", 1010 | " pass\n", 1011 | " def Push(self):\n", 1012 | " # Add an element to the priority queue\n", 1013 | " pass\n", 1014 | " def Pop(self):\n", 1015 | " # delete element with max priority\n", 1016 | " pass\n", 1017 | " def __del__(self):\n", 1018 | " # Distructor to delete reference to names that are no longer required\n", 1019 | " pass" 1020 | ], 1021 | "language": "python", 1022 | "metadata": {}, 1023 | "outputs": [], 1024 | "prompt_number": 20 1025 | }, 1026 | { 1027 | "cell_type": "heading", 1028 | "level": 2, 1029 | "metadata": {}, 1030 | "source": [ 1031 | "PROGRAM 5.15, PAGE 282" 1032 | ] 1033 | }, 1034 | { 1035 | "cell_type": "code", 1036 | "collapsed": false, 1037 | "input": [ 1038 | "# Max heap constructor\n", 1039 | "class MaxHeap(object):\n", 1040 | " def __init__(self, theCapacity = 10):\n", 1041 | " if theCapacity < 1:\n", 1042 | " raise Exception(\"Capacity must be >= 1\")\n", 1043 | "\n", 1044 | " self.capacity = theCapacity\n", 1045 | " self.heapSize = 0\n", 1046 | " self.heap = dict()\n", 1047 | " \n", 1048 | " def IsEmpty(self):\n", 1049 | " return ( self.heapSize == 0 ) or ( len(self.heap) == 0 )" 1050 | ], 1051 | "language": "python", 1052 | "metadata": {}, 1053 | "outputs": [], 1054 | "prompt_number": 21 1055 | }, 1056 | { 1057 | "cell_type": "heading", 1058 | "level": 1, 1059 | "metadata": {}, 1060 | "source": [ 1061 | "PROGRAM 5.16, PAGE 285" 1062 | ] 1063 | }, 1064 | { 1065 | "cell_type": "code", 1066 | "collapsed": false, 1067 | "input": [ 1068 | "# Insertion into a max heap\n", 1069 | "\n", 1070 | "def _Push(self, e):\n", 1071 | " \"\"\" Insert e into max heap \"\"\"\n", 1072 | " \n", 1073 | " if self.heapSize == self.capacity:\n", 1074 | " # Double the capacity\n", 1075 | " self.capacity *= 2\n", 1076 | " \n", 1077 | " self.heapSize += 1\n", 1078 | " currentNode = self.heapSize\n", 1079 | " \n", 1080 | " while ( currentNode != 1 ) and ( self.heap[currentNode/2] < e) :\n", 1081 | " # Bubble up\n", 1082 | " self.heap[currentNode] = self.heap[currentNode / 2] # Move parent down\n", 1083 | " currentNode /= 2\n", 1084 | " \n", 1085 | " self.heap[currentNode] = e\n", 1086 | " \n", 1087 | "MaxHeap.Push = _Push" 1088 | ], 1089 | "language": "python", 1090 | "metadata": {}, 1091 | "outputs": [], 1092 | "prompt_number": 22 1093 | }, 1094 | { 1095 | "cell_type": "heading", 1096 | "level": 2, 1097 | "metadata": {}, 1098 | "source": [ 1099 | "PROGRAM 5.17, PAGE 286" 1100 | ] 1101 | }, 1102 | { 1103 | "cell_type": "code", 1104 | "collapsed": false, 1105 | "input": [ 1106 | "# Deletion from a Max heap\n", 1107 | "\n", 1108 | "def _Pop(self):\n", 1109 | " # Delete max element\n", 1110 | " if self.IsEmpty():\n", 1111 | " raise Exception(\"Heap is empty. Cannot delete\")\n", 1112 | " \n", 1113 | " # Remove last element from heap\n", 1114 | " lastE = self.heap[self.heapSize]\n", 1115 | " self.heapSize -= 1\n", 1116 | " \n", 1117 | " # Tricle down\n", 1118 | " currentNode = 1 # Root\n", 1119 | " child = 2 # A child of the CurrentNode\n", 1120 | " while child <= self.heapSize:\n", 1121 | " # set child to larger child of currentNode\n", 1122 | " if child < self.heapSize and self.heap[child] < self.heap[child+1]:\n", 1123 | " child += 1\n", 1124 | " \n", 1125 | " if lastE >= self.heap[child]:\n", 1126 | " # If lastE can be put in the currentNode, break out of the loop\n", 1127 | " break\n", 1128 | " \n", 1129 | " # If not\n", 1130 | " \n", 1131 | " self.heap[currentNode] = self.heap[child]\n", 1132 | " currentNode = child # move child up\n", 1133 | " child *= 2 # Move down a level\n", 1134 | " \n", 1135 | " self.heap[currentNode] = lastE\n", 1136 | " \n", 1137 | "MaxHeap.Pop = _Pop" 1138 | ], 1139 | "language": "python", 1140 | "metadata": {}, 1141 | "outputs": [], 1142 | "prompt_number": 23 1143 | }, 1144 | { 1145 | "cell_type": "code", 1146 | "collapsed": false, 1147 | "input": [ 1148 | "# Sample Output - NOT IN TEXTBOOK\n", 1149 | "# Refer Figure 5.26, Page 284\n", 1150 | "\n", 1151 | "a = MaxHeap()\n", 1152 | "\n", 1153 | "a.Push(20)\n", 1154 | "a.Push(15)\n", 1155 | "a.Push(10)\n", 1156 | "a.Push(14)\n", 1157 | "a.Push(2)\n", 1158 | "a.Push(5)\n", 1159 | "a.Pop() # 20 will be removed.\n", 1160 | "\n", 1161 | "print a.heap" 1162 | ], 1163 | "language": "python", 1164 | "metadata": {}, 1165 | "outputs": [ 1166 | { 1167 | "output_type": "stream", 1168 | "stream": "stdout", 1169 | "text": [ 1170 | "{1: 15, 2: 14, 3: 10, 4: 2, 5: 2, 6: 5}\n" 1171 | ] 1172 | } 1173 | ], 1174 | "prompt_number": 24 1175 | }, 1176 | { 1177 | "cell_type": "heading", 1178 | "level": 2, 1179 | "metadata": {}, 1180 | "source": [ 1181 | "ADT 5.3, PAGE 287" 1182 | ] 1183 | }, 1184 | { 1185 | "cell_type": "code", 1186 | "collapsed": false, 1187 | "input": [ 1188 | "# A dictionary\n", 1189 | "\n", 1190 | "class Dictionary:\n", 1191 | " def __init__(self):\n", 1192 | " pass\n", 1193 | " \n", 1194 | " def IsEmpty(self):\n", 1195 | " pass\n", 1196 | " \n", 1197 | " def Insert(self, pair):\n", 1198 | " pass\n", 1199 | " \n", 1200 | " def Delete(self, pair):\n", 1201 | " pass" 1202 | ], 1203 | "language": "python", 1204 | "metadata": {}, 1205 | "outputs": [], 1206 | "prompt_number": 25 1207 | }, 1208 | { 1209 | "cell_type": "heading", 1210 | "level": 2, 1211 | "metadata": {}, 1212 | "source": [ 1213 | "PAIR / BST CLASS DECLARATIONS" 1214 | ] 1215 | }, 1216 | { 1217 | "cell_type": "code", 1218 | "collapsed": false, 1219 | "input": [ 1220 | "# Pair Class - Key / Value pair ( data ) of a bst node\n", 1221 | "class Pair(object):\n", 1222 | " def __init__(self, key = None, value = None):\n", 1223 | " self.first = key # key\n", 1224 | " self.second = value # value\n", 1225 | " # To print the key value pairs when Pair is \"print\"-ed\n", 1226 | " def __repr__(self):\n", 1227 | " return \"( \" + str(self.first) + \" , \" + str(self.second) + \" )\"\n", 1228 | " __str__ = __repr__\n", 1229 | " \n", 1230 | "# Abstract Class for the Binary Search Tree deriving from the Tree Class\n", 1231 | "class BST(Tree):\n", 1232 | " def __init__(self, *inputs):\n", 1233 | " Tree.__init__(self, *inputs)" 1234 | ], 1235 | "language": "python", 1236 | "metadata": {}, 1237 | "outputs": [], 1238 | "prompt_number": 26 1239 | }, 1240 | { 1241 | "cell_type": "heading", 1242 | "level": 2, 1243 | "metadata": {}, 1244 | "source": [ 1245 | "PROGRAM 5.18, PAGE 289" 1246 | ] 1247 | }, 1248 | { 1249 | "cell_type": "code", 1250 | "collapsed": false, 1251 | "input": [ 1252 | "# Recursive search of a binary search tree\n", 1253 | "def _Get(self, frm, k):\n", 1254 | " # Search binary search tree for a pair with key k\n", 1255 | " # If such a pair is found, return a pointer to this pair, other wise return None\n", 1256 | " \n", 1257 | " # Driver\n", 1258 | " if ( k is None ):\n", 1259 | " k = frm\n", 1260 | " return self.Get(self.root, k)\n", 1261 | " \n", 1262 | " # Workhorse\n", 1263 | " if ( frm is None ):\n", 1264 | " return None\n", 1265 | " \n", 1266 | " \n", 1267 | " if ( k < frm.data.first ): # TreeNode will have Pair object as its data attribute\n", 1268 | " return self.Get(frm.leftChild, k)\n", 1269 | " \n", 1270 | " elif ( k > frm.data.first ):\n", 1271 | " return self.Get(frm.rightChild, k)\n", 1272 | " \n", 1273 | " else:\n", 1274 | " return frm.data # Returns the pair object which is the frm - TreeNode's data attribute.\n", 1275 | " \n", 1276 | "BST.Get = _Get" 1277 | ], 1278 | "language": "python", 1279 | "metadata": {}, 1280 | "outputs": [], 1281 | "prompt_number": 27 1282 | }, 1283 | { 1284 | "cell_type": "heading", 1285 | "level": 2, 1286 | "metadata": {}, 1287 | "source": [ 1288 | "PROGRAM 5.19, PAGE 290" 1289 | ] 1290 | }, 1291 | { 1292 | "cell_type": "code", 1293 | "collapsed": false, 1294 | "input": [ 1295 | "# Iterative search of a binary search tree.\n", 1296 | "\n", 1297 | "def _Get_Iterative(self, k):\n", 1298 | " while ( currentNode is not None ):\n", 1299 | " if ( k < currentNode.data.first ): \n", 1300 | " #NOTE: currentNode is a TreeNode object, data is a Pair object and first is the key of that Pair object.\n", 1301 | " currentNode = currentNode.leftChild\n", 1302 | " elif ( k > currentNode.data.first ):\n", 1303 | " currentNode = currentNode.rightChild\n", 1304 | " else:\n", 1305 | " return currentNode.data\n", 1306 | " \n", 1307 | " # If there is no matching pair ( while loop terminates without returning )\n", 1308 | " return None " 1309 | ], 1310 | "language": "python", 1311 | "metadata": {}, 1312 | "outputs": [], 1313 | "prompt_number": 28 1314 | }, 1315 | { 1316 | "cell_type": "heading", 1317 | "level": 2, 1318 | "metadata": {}, 1319 | "source": [ 1320 | "PROGRAM 5.20, PAGE 290" 1321 | ] 1322 | }, 1323 | { 1324 | "cell_type": "code", 1325 | "collapsed": false, 1326 | "input": [ 1327 | "# Searching the Binary Search Tree by rank\n", 1328 | "def _RankGet(self, r):\n", 1329 | " # Search the binary search tree for the rth smallest pair\n", 1330 | " while ( currentNode is not None ):\n", 1331 | " if ( r < currentNode.leftSize ):\n", 1332 | " currentNode = currentNode.leftChild\n", 1333 | " \n", 1334 | " elif ( r > currentNode.leftSize ):\n", 1335 | " r -= currentNode.leftSize\n", 1336 | " currentNode = currentNode.rightChild\n", 1337 | " \n", 1338 | " else:\n", 1339 | " return currentNode.data\n", 1340 | " \n", 1341 | "BST.RankGet = _RankGet" 1342 | ], 1343 | "language": "python", 1344 | "metadata": {}, 1345 | "outputs": [], 1346 | "prompt_number": 29 1347 | }, 1348 | { 1349 | "cell_type": "heading", 1350 | "level": 2, 1351 | "metadata": {}, 1352 | "source": [ 1353 | "PROGRAM 5.21, PAGE 292" 1354 | ] 1355 | }, 1356 | { 1357 | "cell_type": "code", 1358 | "collapsed": false, 1359 | "input": [ 1360 | "# Insertion into a binary search tree\n", 1361 | "def _Insert(self, thePair):\n", 1362 | " # Insert thePair\n", 1363 | " # Search for thePair.first, pp is the parent of p\n", 1364 | " p = self.root\n", 1365 | " pp = None\n", 1366 | " \n", 1367 | " while (p is not None):\n", 1368 | " pp = p\n", 1369 | " if ( thePair.first < p.data.first ):\n", 1370 | " p = p.leftChild\n", 1371 | " elif ( thePair.first > p.data.first ):\n", 1372 | " p = p.rightChild\n", 1373 | " else:\n", 1374 | " # Duplicate, Update associated element\n", 1375 | " p.data.second = thePair.second\n", 1376 | " return None\n", 1377 | " \n", 1378 | " # Perform the insertion\n", 1379 | " p = TreeNode(data = thePair)\n", 1380 | " if ( self.root is not None ):\n", 1381 | " if ( thePair.first < pp.data.first ):\n", 1382 | " pp.leftChild = p\n", 1383 | " else:\n", 1384 | " pp.rightChild = p\n", 1385 | " else:\n", 1386 | " root = p\n", 1387 | " \n", 1388 | "BST.Insert = _Insert" 1389 | ], 1390 | "language": "python", 1391 | "metadata": {}, 1392 | "outputs": [], 1393 | "prompt_number": 30 1394 | }, 1395 | { 1396 | "cell_type": "heading", 1397 | "level": 2, 1398 | "metadata": {}, 1399 | "source": [ 1400 | "PROGRAM 5.22, PAGE 295" 1401 | ] 1402 | }, 1403 | { 1404 | "cell_type": "code", 1405 | "collapsed": false, 1406 | "input": [ 1407 | "# Splitting a Binary Search Tree\n", 1408 | "def _Split(self, k, small, mid, big):\n", 1409 | " \"\"\"\n", 1410 | " The Binary Search Tree is split into 3 subtrees - small, mid and big\n", 1411 | " small is the BST with all the keys less than k\n", 1412 | " big is the BST with all the keys greater than k\n", 1413 | " mid is the Pair object with key equal to k ( if any such pair exists in BST )\n", 1414 | " \"\"\"\n", 1415 | " # Split the Binary Search Tree with respect to the key k\n", 1416 | " \n", 1417 | " # Empty tree :\n", 1418 | " if ( self.root is None ):\n", 1419 | " small.root = big.root = None\n", 1420 | " return\n", 1421 | " \n", 1422 | " sHead = TreeNode()\n", 1423 | " s = sHead\n", 1424 | " bHead = TreeNode()\n", 1425 | " b = bHead\n", 1426 | " currentNode = self.root\n", 1427 | " \n", 1428 | " while ( currentNode is not None ):\n", 1429 | " if ( k < currentNode.data.first ):\n", 1430 | " # Add it to the big\n", 1431 | " b.leftChild = currentNode\n", 1432 | " b = currentNode\n", 1433 | " currentNode = currentNode.leftChild\n", 1434 | " elif ( k > currentNode.data.first ):\n", 1435 | " # Add it to the small\n", 1436 | " s.rightChild = currentNode\n", 1437 | " s = currentNode\n", 1438 | " currentNode = currentNode.rightChild\n", 1439 | " else:\n", 1440 | " # Split at the currentNode\n", 1441 | " s.rightChild = currentNode.leftChild\n", 1442 | " b.leftChild = currentNode.rightChild\n", 1443 | " small.root = sHead.rightChild\n", 1444 | " del sHead\n", 1445 | " big.root = bHead.leftChild\n", 1446 | " del bHead\n", 1447 | " mid.first = currentNode.data.first; mid.second = currentNode.data.second\n", 1448 | " del currentNode\n", 1449 | " return\n", 1450 | " \n", 1451 | " # No pair with key k\n", 1452 | " s.rightChild = b.leftChild = None\n", 1453 | " small.root = sHead.rightChild\n", 1454 | " del sHead\n", 1455 | " big.root = bHead.leftChild\n", 1456 | " del bHead\n", 1457 | " mid = None\n", 1458 | " return\n", 1459 | " \n", 1460 | "BST.Split = _Split" 1461 | ], 1462 | "language": "python", 1463 | "metadata": {}, 1464 | "outputs": [], 1465 | "prompt_number": 31 1466 | }, 1467 | { 1468 | "cell_type": "code", 1469 | "collapsed": false, 1470 | "input": [ 1471 | "# Example problem on BST ( NOT IN TEXTBOOK )\n", 1472 | "\n", 1473 | "node_2 = TreeNode(None, Pair(2,\"Two\"), None) \n", 1474 | "# Here 2 is the key and \"Two\" is the value of the Pair object\n", 1475 | "# Which forms the data of the TreeNode object\n", 1476 | "node_5 = TreeNode(node_2, Pair(5,\"Two\"), None)\n", 1477 | "\n", 1478 | "node_80 = TreeNode(None, Pair(80, \"Eighty\"), None)\n", 1479 | "node_40 = TreeNode(None, Pair(40, \"Forty\"), node_80)\n", 1480 | "\n", 1481 | "# Root node\n", 1482 | "node_30 = TreeNode(node_5, Pair(30, \"Thirty\"), node_40)\n", 1483 | "\n", 1484 | "bst_1 = BST(node_30)\n", 1485 | "\n", 1486 | "print \"The Inorder traversal of the bst before Insert : \"\n", 1487 | "bst_1.Inorder()\n", 1488 | "\n", 1489 | "bst_1.Insert(Pair(35, \"Thirty Five\"))\n", 1490 | "\n", 1491 | "print \"\\n\\nThe Inorder traversal of the bst after Inserting : \"\n", 1492 | "bst_1.Inorder()" 1493 | ], 1494 | "language": "python", 1495 | "metadata": {}, 1496 | "outputs": [ 1497 | { 1498 | "output_type": "stream", 1499 | "stream": "stdout", 1500 | "text": [ 1501 | "The Inorder traversal of the bst before Insert : \n", 1502 | "( 2 , Two ) ( 5 , Two ) ( 30 , Thirty ) ( 40 , Forty ) ( 80 , Eighty ) \n", 1503 | "\n", 1504 | "The Inorder traversal of the bst after Inserting : \n", 1505 | "( 2 , Two ) ( 5 , Two ) ( 30 , Thirty ) ( 35 , Thirty Five ) ( 40 , Forty ) ( 80 , Eighty )\n" 1506 | ] 1507 | } 1508 | ], 1509 | "prompt_number": 32 1510 | }, 1511 | { 1512 | "cell_type": "code", 1513 | "collapsed": false, 1514 | "input": [ 1515 | "# Ilustration of splitting the tree :\n", 1516 | "print \"Splitting the tree with key k = 30\"\n", 1517 | "print \"--------------------------------------\"\n", 1518 | "small_subtree = BST()\n", 1519 | "mid_pair = Pair()\n", 1520 | "big_subtree = BST()\n", 1521 | "bst_1.Split(30, small_subtree, mid_pair, big_subtree )\n", 1522 | "\n", 1523 | "print \"\\nThe small_subtree ( Inorder traversal ) is : \"\n", 1524 | "small_subtree.Inorder()\n", 1525 | "\n", 1526 | "print \"\\n\\nThe mid_pair ( key, value ) is : \"\n", 1527 | "print mid_pair\n", 1528 | "\n", 1529 | "print \"\\n\\nThe big_subtree ( Inorder traversal ) is : \"\n", 1530 | "big_subtree.Inorder()" 1531 | ], 1532 | "language": "python", 1533 | "metadata": {}, 1534 | "outputs": [ 1535 | { 1536 | "output_type": "stream", 1537 | "stream": "stdout", 1538 | "text": [ 1539 | "Splitting the tree with key k = 30\n", 1540 | "--------------------------------------\n", 1541 | "\n", 1542 | "The small_subtree ( Inorder traversal ) is : \n", 1543 | "( 2 , Two ) ( 5 , Two ) \n", 1544 | "\n", 1545 | "The mid_pair ( key, value ) is : \n", 1546 | "( 30 , Thirty )\n", 1547 | "\n", 1548 | "\n", 1549 | "The big_subtree ( Inorder traversal ) is : \n", 1550 | "( 35 , Thirty Five ) ( 40 , Forty ) ( 80 , Eighty )\n" 1551 | ] 1552 | } 1553 | ], 1554 | "prompt_number": 33 1555 | }, 1556 | { 1557 | "cell_type": "heading", 1558 | "level": 2, 1559 | "metadata": {}, 1560 | "source": [ 1561 | "PROGRAM 5.23, PAGE 307" 1562 | ] 1563 | }, 1564 | { 1565 | "cell_type": "code", 1566 | "collapsed": false, 1567 | "input": [ 1568 | "# Class definition and constructor for sets\n", 1569 | "class Sets(object):\n", 1570 | " def __init__(self, numberOfElements):\n", 1571 | " if ( numberOfElements < 2 ):\n", 1572 | " raise Exception(\"Must have at least 2 elements\")\n", 1573 | " self.n = numberOfElements\n", 1574 | " self.parent = [-1]*n" 1575 | ], 1576 | "language": "python", 1577 | "metadata": {}, 1578 | "outputs": [], 1579 | "prompt_number": 34 1580 | }, 1581 | { 1582 | "cell_type": "heading", 1583 | "level": 2, 1584 | "metadata": {}, 1585 | "source": [ 1586 | "PROGRAM 5.24, PAGE 308" 1587 | ] 1588 | }, 1589 | { 1590 | "cell_type": "code", 1591 | "collapsed": false, 1592 | "input": [ 1593 | "# Simple functions for union and find\n", 1594 | "def _SimpleUnion(self, i, j):\n", 1595 | " # Replace the disjoint sets with roots i and j, i != j with their union\n", 1596 | " self.parent[i] = j\n", 1597 | "\n", 1598 | "Sets.SimpleUnion = _SimpleUnion\n", 1599 | " \n", 1600 | "def _SimpleFind(self, i):\n", 1601 | " while ( parent[i] >= 0 ):\n", 1602 | " i = parent[i]\n", 1603 | " return\n", 1604 | "\n", 1605 | "Sets.SimpleFind = _SimpleFind" 1606 | ], 1607 | "language": "python", 1608 | "metadata": {}, 1609 | "outputs": [], 1610 | "prompt_number": 35 1611 | }, 1612 | { 1613 | "cell_type": "heading", 1614 | "level": 2, 1615 | "metadata": {}, 1616 | "source": [ 1617 | "PROGRAM 5.26, PAGE 313" 1618 | ] 1619 | }, 1620 | { 1621 | "cell_type": "code", 1622 | "collapsed": false, 1623 | "input": [ 1624 | "# Collapsing Rule\n", 1625 | "def _CollapsingFind(self, i):\n", 1626 | " # Find the root of the tree containing element i,\n", 1627 | " # Use the collapsing root rule to calculate all nodes from i to the root\n", 1628 | " r = i\n", 1629 | " while sellf.parent[r] >= 0:\n", 1630 | " r = parent[r]\n", 1631 | " \n", 1632 | " while i != r:\n", 1633 | " # Collapse\n", 1634 | " s = parent[i]\n", 1635 | " parent[i] = r\n", 1636 | " i = s\n", 1637 | " \n", 1638 | " return r" 1639 | ], 1640 | "language": "python", 1641 | "metadata": {}, 1642 | "outputs": [], 1643 | "prompt_number": 36 1644 | }, 1645 | { 1646 | "cell_type": "code", 1647 | "collapsed": false, 1648 | "input": [], 1649 | "language": "python", 1650 | "metadata": {}, 1651 | "outputs": [] 1652 | } 1653 | ], 1654 | "metadata": {} 1655 | } 1656 | ] 1657 | } -------------------------------------------------------------------------------- /Chapter 6 - Graphs.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:43a9354001c83189e570a9c2c7574faee340a75df29385a34abed713b1c30d56" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "heading", 13 | "level": 2, 14 | "metadata": {}, 15 | "source": [ 16 | "ADT 6.1, PAGE 331" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "collapsed": false, 22 | "input": [ 23 | "# For practical implementation into bigger projects, one may refer to\n", 24 | "# standard libraries such as networkx - https://networkx.github.io/\n", 25 | "\n", 26 | "class Graph(object):\n", 27 | " def __init__():\n", 28 | " pass\n", 29 | " \n", 30 | " def is_empty():\n", 31 | " \"\"\"Returns true if the Graph is empty.\"\"\"\n", 32 | " \n", 33 | " \n", 34 | " \n", 35 | " \n", 36 | " " 37 | ], 38 | "language": "python", 39 | "metadata": {}, 40 | "outputs": [] 41 | } 42 | ], 43 | "metadata": {} 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Data Structures By Horowitz - As iPython Notebooks 2 | 3 | Run these notebooks online - [![Binder](http://mybinder.org/badge.svg)](http://mybinder.org/repo/raghavrv/Data-Structures-By-Horowitz-in-Python) 4 | 5 | 6 | Python implementation of the examples in the text book [Fundamentals of 7 | Data Structures in C++ by E.Horowitz, S.Sahni and 8 | Mehta](http://www.amazon.in/dp/8173716064/ref=cm_sw_r_tw_dp_P0I9sb188T11M). 9 | 10 | This is a part of my contribution to the textbook companionship project 11 | organized by the [FOSSEE](http://python.fossee.in/) initiative of 12 | [IIT Bombay](https://www.iitb.ac.in/). 13 | 14 | 15 | #### Sneak Peek 16 | 17 | ##### Chapter 1 18 | **Plotting the Fibonacci Spiral in Python!** 19 | 20 | 21 | 22 | 23 | **Profiling the time cost of sequential search** 24 | 25 | 26 | 27 | ##### Chapter 2 28 | 29 | **The LaTeX enabled Polynomial module** 30 | 31 | 32 | 33 | **Find vs Fast Find** 34 | 35 | 36 | 37 | ##### Chapter 3 38 | 39 | **Maze Path Finder (Application of stack)** 40 | 41 | 42 | 43 | ##### Chapter 7 44 | **Visualizing Heap sort using graph viz plots** 45 | 46 | ``` 47 | The input array ( Represented as dictionary ) : 48 | {1: 26, 2: 5, 3: 77, 4: 1, 5: 61, 6: 11, 7: 59, 8: 15, 9: 48, 10: 19} 49 | ``` 50 | 51 | ![](https://i.imgur.com/pcZKyBZ.png) 52 | 53 | (One of the intermediate steps) 54 | 55 | ![](https://i.imgur.com/IsjZXDy.png) 56 | 57 | ``` 58 | Sorted : [77, 61, 59, 48, 26] 59 | ``` 60 | 61 | (Final step and the sorted array) 62 | 63 | ![](https://i.imgur.com/tPqbLGs.png) 64 | 65 | ``` 66 | Sorted : [77, 61, 59, 48, 26, 19, 15, 11, 5] 67 | The final sorted array is : [77, 61, 59, 48, 26, 19, 15, 11, 5, 1] 68 | ``` 69 | 70 | ##### Chapter 8 71 | **RSA hash generation flowchart in Python!!** 72 | 73 | 74 | **Hashmap collision avoidance using chaining** 75 | 76 | 77 | #### Contribute 78 | If you wish to contribute too, visit [FOSSEE](http://fossee.in/) and 79 | see if you can find anything matching your interests. 80 | 81 | #### Copyright 82 | The copyrights for all the codes belong to the FOSSEE Department of IIT 83 | Bombay. 84 | 85 | #### Contact 86 | rvraghav93@gmail.com 87 | --------------------------------------------------------------------------------