├── .gitignore ├── 01-TableOfContents.ipynb ├── AlgorithmAnalysis.ipynb ├── ArrayList.ipynb ├── CS1-Review.ipynb ├── Class-OperatorOverloading.ipynb ├── ClassTemplates.ipynb ├── DoublyLinkedLists.ipynb ├── Exceptions.ipynb ├── FunctionTemplates.ipynb ├── Introduction.ipynb ├── LICENSE ├── LinkedLists.ipynb ├── MemorySegments.ipynb ├── OOP-Intro.ipynb ├── Pointers.ipynb ├── Queues.ipynb ├── README.md ├── Recursions.ipynb ├── SearchAlgorithms.ipynb ├── Stacks.ipynb ├── StaticVariables.ipynb ├── Struct.ipynb ├── demo-programs ├── RectangleBasic │ ├── Rectangle.cpp │ ├── Rectangle.h │ └── main.cpp ├── RectangleClass │ ├── Rectangle.cpp │ ├── RectangleFriend.cpp │ ├── RectangleFriend1.cpp │ └── RectangleMember.cpp ├── classTemplates.cpp ├── exception.cpp ├── memory_segments.cpp ├── operator-overloading │ ├── ComplexNumber │ │ ├── a.out │ │ ├── complex.cpp │ │ ├── complex.h │ │ └── main.cpp │ └── a.out └── recursions │ └── countDown.cpp ├── pdfs ├── 00-Introduction.pdf ├── ArrayList.pdf ├── CS1-Review.pdf ├── Class-OperatorOverloading.pdf ├── ClassTemplates.pdf ├── DoublyLinkedLists.pdf ├── Exceptions.pdf ├── FunctionTemplates.pdf ├── LinkedLists.pdf ├── MemorySegments.pdf ├── OOP-Intro.pdf ├── Pointers.pdf ├── Queues.pdf ├── Recursions.pdf ├── SearchAlgorithms.pdf ├── Stacks.pdf ├── StaticVariables.pdf └── Struct.pdf └── resources ├── DataRecords.png ├── DoublyLinkedList1.png ├── MemorySegments.png ├── OOPCM.png ├── betterLinkedList1.png ├── betterLinkedList2.png ├── growthRates.png ├── growthRatesZoom.png ├── growthrates.gif ├── linkedlist1.png ├── linkedlist2.png ├── pointers-in-c.jpg ├── queue.png ├── seqSearchBestWorstAvg.png └── stacks.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # others 107 | *.DS_Store 108 | *.pickle 109 | *.db 110 | .vscode/ 111 | .ipynb_checkpoints/ 112 | *.pickle 113 | __pycache__/ 114 | 115 | *.log 116 | *.out 117 | *.exe 118 | *.bin -------------------------------------------------------------------------------- /01-TableOfContents.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# CS2: Data Structures & Applications\n", 8 | "\n", 9 | "## Table of Contents\n", 10 | "1. **[Introduction](#intro)**
\n", 11 | "2. **[CS1 Review](./CS1-Review.ipynb)**
\n", 12 | "3. **[Kattis Demos & Automated Testing](https://github.com/rambasnet/kattisdemos)**
\n", 13 | "4. **[Struct](./Struct.ipynb)**
\n", 14 | "5. **[Memory Segments](./MemorySegments.ipynb)**
\n", 15 | "6. **[Static Variables](./StaticVariables.ipynb)**
\n", 16 | "7. **[Function Templates](./FunctionTemplates.ipynb)**
\n", 17 | "8. **[Pointers](./Pointers.ipynb)**
\n", 18 | "9. **[STL Containers and Algorithms Libraries](https://github.com/rambasnet/stl-notebooks)**
\n", 19 | "10. **[Classes - OOP Introduction](./OOP-Intro.ipynb)**
\n", 20 | "11. **[Operator Overloading](./Class-OperatorOverloading.ipynb)**
\n", 21 | "12. **[Class Templates](./ClassTemplates.ipynb)**
\n", 22 | "13. **[Exceptions](./Exceptions.ipynb)**
\n", 23 | "14. **[Recursions](./Recursions.ipynb)**
\n", 24 | "15. **[Array-based Lists](./ArrayList.ipynb)**
\n", 25 | "16. **[Singly Linked Lists](./LinkedLists.ipynb)**
\n", 26 | "17. **[Doubly Linked Lists](./DoublyLinkedLists.ipynb)**
\n", 27 | "18. **[Stacks](./Stacks.ipynb)**
\n", 28 | "19. **[Queues](./Queues.ipynb)**
\n", 29 | "20. **[Algorithm Analysis](./AlgorithmAnalysis.ipynb)**
\n", 30 | "21. **[Search Algorithms](./SearchAlgorithms.ipynb)**
" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [] 39 | } 40 | ], 41 | "metadata": { 42 | "kernelspec": { 43 | "display_name": "C++14", 44 | "language": "C++14", 45 | "name": "xcpp14" 46 | }, 47 | "language_info": { 48 | "codemirror_mode": "text/x-c++src", 49 | "file_extension": ".cpp", 50 | "mimetype": "text/x-c++src", 51 | "name": "c++", 52 | "version": "14" 53 | } 54 | }, 55 | "nbformat": 4, 56 | "nbformat_minor": 4 57 | } 58 | -------------------------------------------------------------------------------- /ArrayList.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Array-based List\n", 8 | "https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/ListADT.html\n", 9 | "\n", 10 | "## Table of Contents\n", 11 | "- **[List Definition](#intro)**
\n", 12 | "- **[Defining List ADT](#adt)**
\n", 13 | "- **[Using List ADT](#app)**
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## List\n", 28 | "- C++ STL provides several data structures/containers; often we need to design our own\n", 29 | "- we'll build **list** Abstract Data Type (ADT) in this chapter\n", 30 | "- **list**: finite, sequence of data items/elements\n", 31 | "- some terminologies and definitions:\n", 32 | "- a list is said to be **empty** when it contains no elements\n", 33 | "- number of elements currently stored is called the **length**\n", 34 | "- the beginning of the list is called **head**\n", 35 | "- the end of the list is called **tail**" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "## Defining List ADT\n", 50 | "- how do we store elements? C-Array is one of the easier options!\n", 51 | "- what basic operations do we want our list to support?\n", 52 | "- some intuition and experience in using STL container says, we want our list to be able to:\n", 53 | " 1. add more elements\n", 54 | " 2. delete elements\n", 55 | " 3. clear elements\n", 56 | " 4. access elements\n", 57 | " 5. know the length and many more...\n", 58 | "- operations similar to STL Vector\n", 59 | "- Tricky Operations:\n", 60 | " - insert element in the middle\n", 61 | " - remove element from the middle" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 1, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "#pragma once\n", 71 | "\n", 72 | "#include \n", 73 | "#include \n", 74 | "#include \n", 75 | "\n", 76 | "using namespace std;" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 2, 82 | "metadata": { 83 | "code_folding": [ 84 | 65, 85 | 72, 86 | 81, 87 | 87, 88 | 93, 89 | 99, 90 | 105, 91 | 119, 92 | 125, 93 | 140, 94 | 151, 95 | 158, 96 | 176, 97 | 189, 98 | 195, 99 | 204, 100 | 223 101 | ] 102 | }, 103 | "outputs": [], 104 | "source": [ 105 | "/*\n", 106 | "Class interface and definition for dynamic array-based ListType template.\n", 107 | "\n", 108 | "Class template definition can't be in separate file because\n", 109 | "the compiler needs to know all the implementation details of the class\n", 110 | "so it can instantiate different versions of the code, depending on the \n", 111 | "actual types provided for each template parameters.\n", 112 | "\n", 113 | "Remember that a template doesn't represent code directly, but a\n", 114 | "template for several versions of that code.\n", 115 | "*/\n", 116 | "\n", 117 | "template \n", 118 | "class ListType\n", 119 | "{\n", 120 | "private:\n", 121 | " T *list;\n", 122 | " int length;\n", 123 | " int maxSize;\n", 124 | "public:\n", 125 | " ListType(size_t max = 10000); // constructor\n", 126 | " ListType(const ListType &other); // copy constructor\n", 127 | " ~ListType(); // destructor\n", 128 | " \n", 129 | " // **** LIST META-DATA AND CAPACITY INFO ****\n", 130 | " // return true if list is empty\n", 131 | " bool isEmpty() const;\n", 132 | " // return true if list is full\n", 133 | " bool isFull() const;\n", 134 | " // get the length/size of the list\n", 135 | " int listSize() const;\n", 136 | " // get the max list size\n", 137 | " int listMaxSize() const;\n", 138 | " \n", 139 | " // **** ELEMENT ACCESS ****\n", 140 | " // retrieve the element at given index\n", 141 | " T at(size_t index) const;\n", 142 | " // access the last/back element\n", 143 | " T back();\n", 144 | " // access the first element\n", 145 | " T front();\n", 146 | " // overload operator[] as member function\n", 147 | " T operator[](int index) const;\n", 148 | " \n", 149 | " // **** MODIFIERS ***\n", 150 | " // insert at the end of the list\n", 151 | " void pushBack(const T &item);\n", 152 | " // delete the last element\n", 153 | " void popBack();\n", 154 | " // insert given item at the given index\n", 155 | " void insertAt(size_t index, const T &item);\n", 156 | " // deletes all the elements in the list and resets the list\n", 157 | " void clear();\n", 158 | " // replace element at index with new item\n", 159 | " void replaceAt(size_t index, const T &item);\n", 160 | " // remove the element at given index\n", 161 | " void removeAt(size_t index);\n", 162 | " \n", 163 | " // do a linear search on given searchItem and return index if found -1 otherwise\n", 164 | " int search(const T &searchItem);\n", 165 | " // find the item in the container and remove it\n", 166 | " void remove(const T &item);\n", 167 | "};\n", 168 | "\n", 169 | "template \n", 170 | "ListType::ListType(size_t max) {\n", 171 | " this->maxSize = max;\n", 172 | " this->length = 0;\n", 173 | " this->list = new T[maxSize]; // dynamic array!\n", 174 | "}\n", 175 | "\n", 176 | "template \n", 177 | "ListType::ListType(const ListType &other) {\n", 178 | " this->length = other.length;\n", 179 | " this->maxSize = other.maxSize;\n", 180 | " this->list = new T[maxSize];\n", 181 | " for (int i = 0; ilist[i] = other.list[i];\n", 183 | "}\n", 184 | "\n", 185 | "template \n", 186 | "ListType::~ListType() {\n", 187 | " delete[] list;\n", 188 | "}\n", 189 | "\n", 190 | "// return true if list is empty\n", 191 | "template \n", 192 | "bool ListType::isEmpty() const {\n", 193 | " return (length == 0);\n", 194 | "}\n", 195 | "\n", 196 | "// return true if list is full\n", 197 | "template \n", 198 | "bool ListType::isFull() const {\n", 199 | " return (length == maxSize);\n", 200 | "}\n", 201 | "\n", 202 | "// return size/length of the list\n", 203 | "template \n", 204 | "int ListType::listSize() const {\n", 205 | " return this->length;\n", 206 | "}\n", 207 | "\n", 208 | "// return the max size of list\n", 209 | "template \n", 210 | "int ListType::listMaxSize() const {\n", 211 | " return this->maxSize;\n", 212 | "}\n", 213 | "\n", 214 | "// retrieve the element at given index\n", 215 | "template \n", 216 | "T ListType::at(size_t index) const {\n", 217 | " if (index < 0 || index >= length)\n", 218 | " throw out_of_range(\"Index out of range.\");\n", 219 | " \n", 220 | " return list[index];\n", 221 | "}\n", 222 | "\n", 223 | "template\n", 224 | "T ListType::back() {\n", 225 | " // doesn't check if the list is empty!\n", 226 | " return list[length-1];\n", 227 | "}\n", 228 | "\n", 229 | "template\n", 230 | "T ListType::front() {\n", 231 | " // doesn't check if the list is empty!\n", 232 | " return list[0];\n", 233 | "}\n", 234 | "\n", 235 | "//return the reference to the value at given index\n", 236 | "template \n", 237 | "T ListType::operator[](int index) const {\n", 238 | " if (index < 0 || index >= length)\n", 239 | " throw out_of_range(\"Index out of range.\");\n", 240 | " return list[index];\n", 241 | "}\n", 242 | "\n", 243 | "// insert at the end of the list\n", 244 | "template \n", 245 | "void ListType::pushBack(const T &item) {\n", 246 | " if (isFull())\n", 247 | " throw overflow_error(\"List is full.\");\n", 248 | " else {\n", 249 | " list[length] = item;\n", 250 | " length++;\n", 251 | " }\n", 252 | "}\n", 253 | "\n", 254 | "// delete the last element\n", 255 | "template \n", 256 | "void ListType::popBack() {\n", 257 | " removeAt(length-1);\n", 258 | "}\n", 259 | "\n", 260 | "// insert item at the index\n", 261 | "// Exception: out_of_range thrown when list it full or index is out of bounds\n", 262 | "template \n", 263 | "void ListType::insertAt(size_t index, const T &item) {\n", 264 | " if (index < 0 || index >= length)\n", 265 | " throw out_of_range(\"Index out of range.\");\n", 266 | " else if (isFull()) {\n", 267 | " throw overflow_error(\"List is full.\");\n", 268 | " }\n", 269 | " else {\n", 270 | " // move the elements down from the index\n", 271 | " // starting from the end\n", 272 | " for (int i = length; i > index; i--)\n", 273 | " list[i] = list[i - 1];\n", 274 | " list[index] = item; // insert the item at the specified index\n", 275 | " length++; // increment the length\n", 276 | " }\n", 277 | "}\n", 278 | "\n", 279 | "// remove the element at given index\n", 280 | "template \n", 281 | "void ListType::removeAt(size_t index) {\n", 282 | " if (index < 0 || index >= length)\n", 283 | " throw out_of_range(\"Index out of range.\");\n", 284 | " else {\n", 285 | " // move elements up one position one at a time \n", 286 | " for (int i = index; i < length - 1; i++)\n", 287 | " list[i] = list[i + 1];\n", 288 | " length--; // decrease list length by 1\n", 289 | " }\n", 290 | "}\n", 291 | "\n", 292 | "// deletes all the elements in the list and resets the list\n", 293 | "template \n", 294 | "void ListType::clear() {\n", 295 | " length = 0;\n", 296 | "}\n", 297 | "\n", 298 | "// replace element at index with new item\n", 299 | "template \n", 300 | "void ListType::replaceAt(size_t index, const T &item) {\n", 301 | " if (index < 0 || index >= length)\n", 302 | " throw out_of_range(\"Index out of range.\");\n", 303 | " else\n", 304 | " list[index] = item;\n", 305 | "}\n", 306 | "\n", 307 | "// do a linear search on given searchItem and return index if found, -1 otherwise\n", 308 | "template \n", 309 | "int ListType::search(const T &searchItem) {\n", 310 | " int index = 0;\n", 311 | " bool found = false;\n", 312 | " while (index < length && !found)\n", 313 | " {\n", 314 | " if (list[index] == searchItem)\n", 315 | " found = true;\n", 316 | " else\n", 317 | " index++;\n", 318 | " }\n", 319 | " if (found)\n", 320 | " return index;\n", 321 | " else\n", 322 | " return -1;\n", 323 | "}\n", 324 | "\n", 325 | "// find the item in the container and remove it\n", 326 | "template \n", 327 | "void ListType::remove(const T &item)\n", 328 | "{\n", 329 | " int index = -1;\n", 330 | " if (isEmpty())\n", 331 | " throw underflow_error(\"List is empty.\");\n", 332 | " else\n", 333 | " {\n", 334 | " index = seqSearch(item);\n", 335 | " if (index != -1)\n", 336 | " removeAt(index);\n", 337 | " }\n", 338 | "}" 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": 3, 344 | "metadata": { 345 | "code_folding": [ 346 | 3 347 | ] 348 | }, 349 | "outputs": [], 350 | "source": [ 351 | "// print all the elements in the list\n", 352 | "// overload operator<<\n", 353 | "template\n", 354 | "ostream& operator<<(ostream& out, const ListType& alist){\n", 355 | " out << \"max size = \" << alist.listMaxSize() << endl;\n", 356 | " out << \"length = \" << alist.listSize() << endl;\n", 357 | " out << \"list contents: \" << endl;\n", 358 | " for (int i = 0; i" 370 | ] 371 | }, 372 | { 373 | "cell_type": "markdown", 374 | "metadata": {}, 375 | "source": [ 376 | "## Using ListType ADT" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 4, 382 | "metadata": {}, 383 | "outputs": [], 384 | "source": [ 385 | "// Test ListType\n", 386 | "ListType ilist(100);" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": 5, 392 | "metadata": {}, 393 | "outputs": [ 394 | { 395 | "name": "stdout", 396 | "output_type": "stream", 397 | "text": [ 398 | "max size = 100\n", 399 | "length = 1\n", 400 | "list contents: \n", 401 | "10 \n" 402 | ] 403 | } 404 | ], 405 | "source": [ 406 | "ilist.pushBack(10);\n", 407 | "cout << ilist;" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": 6, 413 | "metadata": {}, 414 | "outputs": [ 415 | { 416 | "name": "stdout", 417 | "output_type": "stream", 418 | "text": [ 419 | "max size = 100\n", 420 | "length = 2\n", 421 | "list contents: \n", 422 | "20 10 \n" 423 | ] 424 | } 425 | ], 426 | "source": [ 427 | "ilist.insertAt(0, 20);\n", 428 | "cout << ilist;" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": 7, 434 | "metadata": {}, 435 | "outputs": [ 436 | { 437 | "name": "stdout", 438 | "output_type": "stream", 439 | "text": [ 440 | "max size = 100\n", 441 | "length = 0\n", 442 | "list contents: \n", 443 | "\n" 444 | ] 445 | } 446 | ], 447 | "source": [ 448 | "ilist.clear();\n", 449 | "cout << ilist;" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "execution_count": 8, 455 | "metadata": {}, 456 | "outputs": [ 457 | { 458 | "ename": "Error", 459 | "evalue": "", 460 | "output_type": "error", 461 | "traceback": [ 462 | "Error: " 463 | ] 464 | } 465 | ], 466 | "source": [ 467 | "ilist.replaceAt(0, 200);\n", 468 | "cout << ilist;" 469 | ] 470 | }, 471 | { 472 | "cell_type": "code", 473 | "execution_count": 9, 474 | "metadata": {}, 475 | "outputs": [], 476 | "source": [ 477 | "int i;" 478 | ] 479 | }, 480 | { 481 | "cell_type": "code", 482 | "execution_count": 10, 483 | "metadata": {}, 484 | "outputs": [ 485 | { 486 | "name": "stdout", 487 | "output_type": "stream", 488 | "text": [ 489 | "element not found..." 490 | ] 491 | } 492 | ], 493 | "source": [ 494 | "i = ilist.search(10);\n", 495 | "if (i < 0)\n", 496 | " cout << \"element not found...\";\n", 497 | "else\n", 498 | " cout << \"element found at index: \" << i << endl;" 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": {}, 504 | "source": [ 505 | "### Exercise\n", 506 | "- In an array-based list, the successive elements in the list:\n", 507 | " 1. Need not occupy contiguous space in memory\n", 508 | " - Must occupy contiguous space in memory\n", 509 | " - None of these\n", 510 | " - Must not occupy contigious space in memory" 511 | ] 512 | }, 513 | { 514 | "cell_type": "code", 515 | "execution_count": null, 516 | "metadata": {}, 517 | "outputs": [], 518 | "source": [] 519 | } 520 | ], 521 | "metadata": { 522 | "kernelspec": { 523 | "display_name": "C++14", 524 | "language": "C++14", 525 | "name": "xeus-cling-cpp14" 526 | }, 527 | "language_info": { 528 | "codemirror_mode": "text/x-c++src", 529 | "file_extension": ".cpp", 530 | "mimetype": "text/x-c++src", 531 | "name": "c++", 532 | "version": "-std=c++14" 533 | } 534 | }, 535 | "nbformat": 4, 536 | "nbformat_minor": 2 537 | } 538 | -------------------------------------------------------------------------------- /Class-OperatorOverloading.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Overloading Operators\n", 8 | "http://www.cplusplus.com/doc/tutorial/templates/\n", 9 | "\n", 10 | "## Table of Contents\n", 11 | "- [Overloading operators](#overloading)\n", 12 | "- [Overloading operators as non-member functions](#non-member)\n", 13 | "- [Friend functions & application](#friend)\n", 14 | "- [Overloading with member functions](#member)\n", 15 | "- [Constant objects and methods](#const)" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "## header includes used in this notebook" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 1, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "#include \n", 32 | "#include \n", 33 | "\n", 34 | "using namespace std;" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "## Overloading operators\n", 49 | "- classes, essentially, define new types to be used in C++ code\n", 50 | "- for fundamental type such as int, float, certain operations have been defined using various operators\n", 51 | " - such operators such as (+, -, ==, >, etc.) have unambiguous meaning\n", 52 | " - c++ basic string class template has most of these operators overloaded. see: https://en.cppreference.com/w/cpp/string/basic_string\n", 53 | "- classes (user defined types) on the other hand doesn't support these operators out-of-the box\n", 54 | "- C++ allows most operators to be overloaded so that their behavior can be defined for just about any type...\n", 55 | "\n", 56 | "### Overloadable operators\n", 57 | "- +, -, %, \\*, /, =, +=, \\*=, /=, %=\n", 58 | "- <<, >>, <<=, >>=, \n", 59 | "- <, >, ==, != <=, >=, \n", 60 | "- ++, --\n", 61 | "- &, ^, !, |\n", 62 | "- ~, &=, ^=, |=\n", 63 | "- &&, ||\n", 64 | "- [ ], ( ), ->, ->\\*\n", 65 | "- new, delete, new[], delete[]\n", 66 | "\n", 67 | "- Syntax to overload operators:\n", 68 | "```c++\n", 69 | "type operator sign (parameters) {\n", 70 | " // sign is the operator symbol being overloaded\n", 71 | " // function body\n", 72 | "}\n", 73 | "```\n", 74 | "- operators may be overloaded in two forms: \n", 75 | " - either as **member function** or as a **non-member function**\n", 76 | " " 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "## Overloading operators with non-member functions\n", 91 | "- simply define functions that overload operator for some class type!\n", 92 | "- some operators can NOT be overloaded as non-member functions\n", 93 | " - e.g., =, +=, [ ], -=, ( ), ->, etc.\n", 94 | "- some operators can be ONLY overloaded as non-member functions\n", 95 | " - e.g., input insertion (>>) and output extraction operator (<<)\n", 96 | "\n", 97 | "**NOTE**: if you see error in notebook, see complete code provided in demo-programs/operator-overloading/Rectangle.cpp" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "## Friend functions\n", 112 | "- friend functions can access private members of a class\n", 113 | "- class can declare functions as friends, but functions can't declare themselves as a friend to class\n", 114 | "- friend functions are not member of a class\n", 115 | "- application of friend function:\n", 116 | " - if members are private (they typically are), friend functions can help overload operators as non-member functions\n", 117 | "- use keyword `friend` in front of function name while marking a function as friend inside any class definition\n", 118 | "\n", 119 | "For example see: demo-programs/operator-overloading/RectangleFriend.cpp" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 2, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "// non-member function overload example\n", 129 | "class Rectangle {\n", 130 | " friend void printRectangleFriend(const Rectangle& r);\n", 131 | " private:\n", 132 | " float length, width;\n", 133 | " public: \n", 134 | " // default and overloaded constructor\n", 135 | " Rectangle(float length=0, float width=0) { \n", 136 | " if (length < 0)\n", 137 | " length = 0;\n", 138 | " if (width == 0)\n", 139 | " width = 0;\n", 140 | " this->length = length;\n", 141 | " this->width = width;\n", 142 | " } \n", 143 | " \n", 144 | " float findArea() const {\n", 145 | " return this->length*this->width;\n", 146 | " }\n", 147 | " \n", 148 | " float findPerimeter() const {\n", 149 | " return 2*(this->length + this->width);\n", 150 | " }\n", 151 | "};" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 3, 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [ 160 | "void printRectangle(const Rectangle& r) {\n", 161 | " //cout << \"length = \" << r.length << endl; // can't do this!!\n", 162 | " //cout << \"width = \" << r.width << endl; // can't do this too!!\n", 163 | " cout << \"area = \" << r.findArea() << endl; // can do this!\n", 164 | " cout << \"perimeter = \" << r.findPerimeter() << endl; // can do this!!\n", 165 | "}" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 4, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "void printRectangleFriend(const Rectangle& r) {\n", 175 | " cout << \"length = \" << r.length << endl; // can't do this!!\n", 176 | " cout << \"width = \" << r.width << endl; // can't do this too!!\n", 177 | " cout << \"area = \" << r.findArea() << endl; // can do this!\n", 178 | " cout << \"perimeter = \" << r.findPerimeter() << endl; // can do this!!\n", 179 | "}" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 5, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "Rectangle smallRect = {4, 2};" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": 6, 194 | "metadata": {}, 195 | "outputs": [ 196 | { 197 | "name": "stdout", 198 | "output_type": "stream", 199 | "text": [ 200 | "length = 4\n", 201 | "width = 2\n", 202 | "area = 8\n", 203 | "perimeter = 12\n" 204 | ] 205 | } 206 | ], 207 | "source": [ 208 | "printRectangleFriend(smallRect);" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "## Overloading operator with member functions\n", 223 | "- some operators may be loaded in two forms: either as a member or as a non-member\n", 224 | " - e.g., +, -, \\*, /, >, <, ==, etc.\n", 225 | "- some operators can be overloaded only as member functions\n", 226 | " - e.g., =, +=, [ ], -=, ( ), ->, etc.\n", 227 | " \n", 228 | "NOTE: See demo-programs/operator-overloading/RectangleMember.cpp for working fully example!" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 7, 234 | "metadata": { 235 | "code_folding": [] 236 | }, 237 | "outputs": [], 238 | "source": [ 239 | "// overloading with member functions example\n", 240 | "class Rectangle1 {\n", 241 | " private:\n", 242 | " float length, width;\n", 243 | " \n", 244 | " public:\n", 245 | " // default and overloaded constructor\n", 246 | " Rectangle1(float length=0, float width=0) { \n", 247 | " if (length < 0)\n", 248 | " length = 0;\n", 249 | " if (width == 0)\n", 250 | " width = 0;\n", 251 | " this->length = length;\n", 252 | " this->width = width;\n", 253 | " }; \n", 254 | " \n", 255 | " float findArea() const {\n", 256 | " return this->length*this->width;\n", 257 | " }\n", 258 | " \n", 259 | " float findPerimeter() const {\n", 260 | " return 2*(this->length + this->width);\n", 261 | " }\n", 262 | " \n", 263 | " // overload + operator\n", 264 | " Rectangle1 operator+(const Rectangle1& rhs) {\n", 265 | " Rectangle1 temp;\n", 266 | " temp.length = this->length + rhs.length;\n", 267 | " temp.width = this->width + rhs.width;\n", 268 | " return temp;\n", 269 | " }\n", 270 | " \n", 271 | " // overload [] operator\n", 272 | " float operator[](unsigned int index) {\n", 273 | " if (index == 0)\n", 274 | " return this->length;\n", 275 | " else\n", 276 | " return this->width;\n", 277 | " }\n", 278 | "};" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": 8, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "Rectangle1 r1 = {20, 10};\n", 288 | "Rectangle1 r2 = {10, 5};" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 9, 294 | "metadata": {}, 295 | "outputs": [], 296 | "source": [ 297 | "Rectangle1 r = r1 + r2;" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": 10, 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "name": "stdout", 307 | "output_type": "stream", 308 | "text": [ 309 | "length = 30 width = 15\n" 310 | ] 311 | } 312 | ], 313 | "source": [ 314 | "cout << \"length = \" << r[0] << \" width = \" << r[1] << endl;" 315 | ] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": {}, 320 | "source": [ 321 | "" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": {}, 327 | "source": [ 328 | "## Constant objects and methods\n", 329 | "- when an object of a class is qualified as a const object:\n", 330 | "```c++\n", 331 | "const SomeClass someObject;\n", 332 | "```\n", 333 | " - the access to its data members from outside the class is restricted to read-only, as if all its data members were const for those accessing them from outside the class\n", 334 | " - Note: constructor is still called and is allowed to initialize and modify these data members" 335 | ] 336 | }, 337 | { 338 | "cell_type": "code", 339 | "execution_count": null, 340 | "metadata": {}, 341 | "outputs": [], 342 | "source": [ 343 | "class SomeClass {\n", 344 | " public:\n", 345 | " int x;\n", 346 | " SomeClass(int val=0) { this->x = val;}\n", 347 | " int getX() { return x; }\n", 348 | "};" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": null, 354 | "metadata": {}, 355 | "outputs": [], 356 | "source": [ 357 | "const SomeClass someObj(10);" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": {}, 364 | "outputs": [], 365 | "source": [ 366 | "someObj.x = 100; // not allowed becuase someObj is const" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": {}, 373 | "outputs": [], 374 | "source": [ 375 | "cout << \"x = \" << someObj.x << endl; // x is public member" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": null, 381 | "metadata": {}, 382 | "outputs": [], 383 | "source": [ 384 | "cout << \"x = \" << someObj.getX() << endl; // getX is not marked constant!" 385 | ] 386 | }, 387 | { 388 | "cell_type": "code", 389 | "execution_count": null, 390 | "metadata": {}, 391 | "outputs": [], 392 | "source": [ 393 | "class MyClass {\n", 394 | " public:\n", 395 | " int x;\n", 396 | " MyClass(int val=0) { this->x = val;}\n", 397 | " int getX() const { return x; }\n", 398 | "};" 399 | ] 400 | }, 401 | { 402 | "cell_type": "code", 403 | "execution_count": null, 404 | "metadata": {}, 405 | "outputs": [], 406 | "source": [ 407 | "const MyClass myObj(20);" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": null, 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [ 416 | "cout << \"x = \" << myObj.getX() << endl;" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": null, 422 | "metadata": {}, 423 | "outputs": [], 424 | "source": [ 425 | "// passing const class objects to function is very common\n", 426 | "void myPrint(const MyClass& obj) {\n", 427 | " cout << \"x = \" << obj.getX() << endl;\n", 428 | "}" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": {}, 435 | "outputs": [], 436 | "source": [ 437 | "// myObj is passed by const ref\n", 438 | "myPrint(myObj);" 439 | ] 440 | }, 441 | { 442 | "cell_type": "markdown", 443 | "metadata": {}, 444 | "source": [ 445 | "" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "metadata": {}, 451 | "source": [ 452 | "#### See /demo-programs/operator-overloading/ComplexNumber/ for complete example working with complex numbers and operator overloading" 453 | ] 454 | }, 455 | { 456 | "cell_type": "code", 457 | "execution_count": null, 458 | "metadata": {}, 459 | "outputs": [], 460 | "source": [] 461 | } 462 | ], 463 | "metadata": { 464 | "kernelspec": { 465 | "display_name": "C++14", 466 | "language": "C++14", 467 | "name": "xeus-cling-cpp14" 468 | }, 469 | "language_info": { 470 | "codemirror_mode": "text/x-c++src", 471 | "file_extension": ".cpp", 472 | "mimetype": "text/x-c++src", 473 | "name": "c++", 474 | "version": "-std=c++14" 475 | } 476 | }, 477 | "nbformat": 4, 478 | "nbformat_minor": 2 479 | } 480 | -------------------------------------------------------------------------------- /ClassTemplates.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Class Templates\n", 8 | "\n", 9 | "## Table of Contents\n", 10 | "- **[Class Templates](#intro)**
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "## header includes used in this notebook" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 1, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "#include \n", 27 | "#include \n", 28 | "\n", 29 | "using namespace std;" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "## Class Templates\n", 44 | "- just like function templates, we can also create class templates\n", 45 | " - class templates allow to generalize data types of class members\n", 46 | "- class templates let us define a different implementation for a template when a specific type is passed as template argument (template specialization)\n", 47 | "- e.g., Rectangle class below only works on length and width values of different types!" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 2, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "// Class Templates\n", 57 | "// for template class, class interface and definition must be in \n", 58 | "// the same file if header (.h) file is used!\n", 59 | "template\n", 60 | "class Rectangle {\n", 61 | " private:\n", 62 | " T length, width;\n", 63 | " public:\n", 64 | " // default and overloaded constructor\n", 65 | " Rectangle(T length=0, T width=0) { \n", 66 | " this->setLength(length);\n", 67 | " this->setWidth(width);\n", 68 | " }; \n", 69 | " \n", 70 | " void setLength(T length) {\n", 71 | " if (length < 0)\n", 72 | " length = 0;\n", 73 | " this->length = length;\n", 74 | " }\n", 75 | " \n", 76 | " void setWidth(T width) {\n", 77 | " if (width == 0)\n", 78 | " width = 0;\n", 79 | " this->width = width;\n", 80 | " }\n", 81 | " \n", 82 | " T findArea() const {\n", 83 | " return this->length*this->width;\n", 84 | " }\n", 85 | " \n", 86 | " T getPerimeter() const {\n", 87 | " return 2*(this->length + this->width);\n", 88 | " }\n", 89 | " \n", 90 | " // overload + operator\n", 91 | " Rectangle operator+(const Rectangle& rhs) {\n", 92 | " Rectangle temp;\n", 93 | " temp.length = this->length + rhs.length;\n", 94 | " temp.width = this->width + rhs.width;\n", 95 | " return temp;\n", 96 | " }\n", 97 | " \n", 98 | " void print() {\n", 99 | " cout << \"length = \" << length;\n", 100 | " cout << \" width = \" << width;\n", 101 | " cout << \" area= \" << findArea();\n", 102 | " }\n", 103 | "};" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 3, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "Rectangle r1 = {20, 10};\n", 113 | "Rectangle r2 = {10, 5};" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 4, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "Rectangle r = r1 + r2;" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 5, 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "name": "stdout", 132 | "output_type": "stream", 133 | "text": [ 134 | "length = 30 width = 15 area= 450" 135 | ] 136 | } 137 | ], 138 | "source": [ 139 | "r.print();" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 6, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "#include \n", 149 | "using namespace std;" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 7, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "template\n", 159 | "class MyPair {\n", 160 | " T values[2];\n", 161 | " public:\n", 162 | " MyPair(T first, T second) {\n", 163 | " values[0] = first;\n", 164 | " values[1] = second;\n", 165 | " }\n", 166 | " void print() {\n", 167 | " cout << \"first: \" << values[0] << \" second: \" << values[1] << endl;\n", 168 | " }\n", 169 | "};" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 8, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "MyPair p1(10, 100);\n", 179 | "MyPair p2(10, 100.99);\n", 180 | "MyPair p3(\"hello\", \"john\");\n", 181 | "MyPairp4('A', 'a');" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": 9, 187 | "metadata": {}, 188 | "outputs": [ 189 | { 190 | "name": "stdout", 191 | "output_type": "stream", 192 | "text": [ 193 | "first: 10 second: 100\n", 194 | "first: 10 second: 100.99\n", 195 | "first: hello second: john\n", 196 | "first: A second: a\n" 197 | ] 198 | } 199 | ], 200 | "source": [ 201 | "p1.print();\n", 202 | "p2.print();\n", 203 | "p3.print();\n", 204 | "p4.print();" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 10, 210 | "metadata": {}, 211 | "outputs": [], 212 | "source": [ 213 | "template\n", 214 | "class Pair {\n", 215 | " T1 first;\n", 216 | " T2 second;\n", 217 | " public:\n", 218 | " Pair(T1 first, T2 second) {\n", 219 | " this->first = first;\n", 220 | " this->second = second;\n", 221 | " }\n", 222 | " void print() {\n", 223 | " cout << \"first: \" << this->first << \" second: \" << this->second << endl;\n", 224 | " }\n", 225 | "};" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 11, 231 | "metadata": {}, 232 | "outputs": [], 233 | "source": [ 234 | "Pair p5(10, 100);\n", 235 | "Pair p6(10, 100.99);\n", 236 | "Pair p7(\"hello\", 4.5);\n", 237 | "Pairp8('A', 200);" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 12, 243 | "metadata": {}, 244 | "outputs": [ 245 | { 246 | "name": "stdout", 247 | "output_type": "stream", 248 | "text": [ 249 | "first: 10 second: 100\n", 250 | "first: 10 second: 100.99\n", 251 | "first: hello second: 4.5\n", 252 | "first: A second: 200\n" 253 | ] 254 | } 255 | ], 256 | "source": [ 257 | "p5.print();\n", 258 | "p6.print();\n", 259 | "p7.print();\n", 260 | "p8.print();" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": {}, 267 | "outputs": [], 268 | "source": [] 269 | } 270 | ], 271 | "metadata": { 272 | "kernelspec": { 273 | "display_name": "C++14", 274 | "language": "C++14", 275 | "name": "xcpp14" 276 | }, 277 | "language_info": { 278 | "codemirror_mode": "text/x-c++src", 279 | "file_extension": ".cpp", 280 | "mimetype": "text/x-c++src", 281 | "name": "c++", 282 | "version": "14" 283 | } 284 | }, 285 | "nbformat": 4, 286 | "nbformat_minor": 2 287 | } 288 | -------------------------------------------------------------------------------- /DoublyLinkedLists.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Doubly Linked Lists\n", 8 | "- https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/ListDouble.html\n", 9 | "- https://en.cppreference.com/w/cpp/container/list\n", 10 | "\n", 11 | "### Table of Contents\n", 12 | "- **[Introduction](#intro)**
\n", 13 | "- **[Implementation of Node](#node)**
\n", 14 | "- **[Operations on Doubly Linked List](#operations)**
\n", 15 | "- **[Doubly Linked List as ADT](#adt)**
\n", 16 | "\n", 17 | "## Introduction\n", 18 | "- **Singly Linked List** allows for direct access from a list node only to the next node in forward direction\n", 19 | "- **Doubly Linked List** allows access in both directions -- forward and backward \n", 20 | " - giving easy access to next node and previous node" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Doubly Linked List\n", 28 | "- also called two-way list\n", 29 | "- each node is depicted with three boxes (members) each holding:\n", 30 | " 1. data (middle box)\n", 31 | " 2. address/pointer to the next node (right box)\n", 32 | " 3. address/pointer to the previous node (left box)\n", 33 | " \n", 34 | "\n", 35 | "\n", 36 | "- diagonal slash (see last and first node) represents NULL pointer meaning it's not pointing to another node\n", 37 | "- head or first is a special pointer pointing to the first (header) node\n", 38 | "- tail or last is a special pointer pointing to the last (trailer) node\n", 39 | "- use pointer to traverse through the linked list (unlike index in array-based list)\n", 40 | "\n", 41 | "\n", 42 | "## Common Operations\n", 43 | "- inserting and deleting nodes are common operations but need to deal with many cases.\n", 44 | "- if header and trailer nodes are used without actually storing the data, simplifies many special cases\n", 45 | " - see visualization at: https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/ListDouble.html" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "## Implemenation of Node\n", 53 | "- since a node is a complex type with data (of various type) and pointers, we use struct or class to implement it" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 1, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "#include \n", 63 | "using namespace std;" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 2, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "struct Int_Node {\n", 73 | " int data; // int data\n", 74 | " Int_Node * next; // address of the next node\n", 75 | " Int_Node * prev; // address of the previous node\n", 76 | "};" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "// better implementation\n", 86 | "template \n", 87 | "struct Node {\n", 88 | " T data; // data of some type T\n", 89 | " Node * next;\n", 90 | " Node * prev;\n", 91 | "};" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "## Creating a Doubly Linked List\n", 99 | "- add elements 10, 20, 30, etc.\n", 100 | "- doubly linked list of: 10 <-> 20 <-> 30" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "Int_Node *head, *tail, *temp;" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "// create empty header and trailer nodes as shown in figure above\n", 119 | "temp = new Int_Node;\n", 120 | "temp->data = 0;\n", 121 | "temp->prev = NULL;\n", 122 | "temp->next = NULL;\n", 123 | "head = temp; // head points to header node\n", 124 | "\n", 125 | "temp = new Int_Node;\n", 126 | "temp->data = 0;\n", 127 | "temp->prev = head; // trailer points to header\n", 128 | "temp->next = NULL;\n", 129 | "tail = temp;\n", 130 | "\n", 131 | "head->next = tail; // header points to trailer" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "## Push Back Element\n", 139 | "- inserting element at the end of the doubly linked list\n", 140 | "- algorithm steps:\n", 141 | " 1. create a new node with data\n", 142 | " - make new node's next point to trailer node\n", 143 | " - make new node's prev point to trailer's prev node\n", 144 | " - make trailer node's prev next point to the new node\n", 145 | " - make trailer node's prev point to the new node" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "// create and add the new node with 10 at the end\n", 155 | "temp = new Int_Node;\n", 156 | "temp->data = 10;\n", 157 | "temp->next = tail;\n", 158 | "temp->prev = tail->prev;\n", 159 | "tail->prev->next = temp;\n", 160 | "tail->prev = temp;" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [ 169 | "// create and add the new node with 20 at the end\n", 170 | "temp = new Int_Node;\n", 171 | "temp->data = 20;\n", 172 | "temp->next = tail;\n", 173 | "temp->prev = tail->prev;\n", 174 | "tail->prev->next = temp;\n", 175 | "tail->prev = temp;" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "// create and add the new node with 20 at the end\n", 185 | "temp = new Int_Node;\n", 186 | "temp->data = 30;\n", 187 | "temp->next = tail;\n", 188 | "temp->prev = tail->prev;\n", 189 | "tail->prev->next = temp;\n", 190 | "tail->prev = temp;" 191 | ] 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": {}, 196 | "source": [ 197 | "## Traversing Doubly Linked List\n", 198 | "- visiting every node of the linked list\n", 199 | " - access data, check and or update data\n", 200 | "- can be traversed both in forward and backward directions" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": {}, 207 | "outputs": [], 208 | "source": [ 209 | "void traverseForward(Int_Node *head) { \n", 210 | " // start from header's next and go through every node\n", 211 | " // stop before trailer\n", 212 | " Int_Node * curr = head->next;\n", 213 | " cout << \"[\";\n", 214 | " while (curr != tail) {\n", 215 | " cout << \" \" << curr->data;\n", 216 | " curr = curr->next;\n", 217 | " }\n", 218 | " cout << \" ]\";\n", 219 | "}" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 11, 225 | "metadata": {}, 226 | "outputs": [ 227 | { 228 | "name": "stdout", 229 | "output_type": "stream", 230 | "text": [ 231 | "[ 10 20 30 ]" 232 | ] 233 | } 234 | ], 235 | "source": [ 236 | "traverseForward(head);" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 12, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [ 245 | "void traverseBackward(Int_Node *tail) {\n", 246 | " // start from trailers's prev and go through every node\n", 247 | " // stop before header\n", 248 | " Int_Node * curr = tail->prev;\n", 249 | " cout << \"[\";\n", 250 | " while (curr != head) {\n", 251 | " cout << \" \" << curr->data;\n", 252 | " curr = curr->prev;\n", 253 | " }\n", 254 | " cout << \" ]\";\n", 255 | "}" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 13, 261 | "metadata": {}, 262 | "outputs": [ 263 | { 264 | "name": "stdout", 265 | "output_type": "stream", 266 | "text": [ 267 | "[ 30 20 10 ]" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "traverseBackward(tail);" 273 | ] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "## Push Front Element\n", 280 | "- inserting element at the beginning of the doubly linked list\n", 281 | "- similar to push back operation\n", 282 | "- algorithm steps:\n", 283 | " 1. create a new node with data\n", 284 | " - make new node->next point to the head->next\n", 285 | " - make new node->prev point to the head\n", 286 | " - make head->next point to the new node\n", 287 | " - make new node->next->prev point to the new node" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": 14, 293 | "metadata": {}, 294 | "outputs": [], 295 | "source": [ 296 | "// insert a new node at the beginning (push_front)\n", 297 | "temp = new Int_Node;\n", 298 | "temp->data = 100;\n", 299 | "temp->next = head->next;\n", 300 | "temp->prev = head;\n", 301 | "head->next = temp;\n", 302 | "temp->next->prev = temp;" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 15, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "name": "stdout", 312 | "output_type": "stream", 313 | "text": [ 314 | "[ 100 10 20 30 ]" 315 | ] 316 | } 317 | ], 318 | "source": [ 319 | "traverseForward(head);" 320 | ] 321 | }, 322 | { 323 | "cell_type": "code", 324 | "execution_count": 16, 325 | "metadata": {}, 326 | "outputs": [ 327 | { 328 | "name": "stdout", 329 | "output_type": "stream", 330 | "text": [ 331 | "[ 30 20 10 100 ]" 332 | ] 333 | } 334 | ], 335 | "source": [ 336 | "traverseBackward(tail);" 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": 17, 342 | "metadata": {}, 343 | "outputs": [], 344 | "source": [ 345 | "// insert a new node at the beginning (push_front)\n", 346 | "temp = new Int_Node;\n", 347 | "temp->data = 200;\n", 348 | "temp->next = head->next;\n", 349 | "temp->prev = head;\n", 350 | "head->next = temp;\n", 351 | "temp->next->prev = temp;" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 18, 357 | "metadata": {}, 358 | "outputs": [ 359 | { 360 | "name": "stdout", 361 | "output_type": "stream", 362 | "text": [ 363 | "[ 200 100 10 20 30 ]" 364 | ] 365 | } 366 | ], 367 | "source": [ 368 | "traverseForward(head);" 369 | ] 370 | }, 371 | { 372 | "cell_type": "markdown", 373 | "metadata": {}, 374 | "source": [ 375 | "## Doubly Linked List Remove\n", 376 | "- remove an element/node from the linked list\n", 377 | "- algorithm steps:\n", 378 | " 1. use a pointer, current\n", 379 | " - current is the node that needs to be deleted if found\n", 380 | " 2. if node is found delete it\n", 381 | " - update the doubly linked list" 382 | ] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "execution_count": 19, 387 | "metadata": {}, 388 | "outputs": [], 389 | "source": [ 390 | "Int_Node * curr;" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 23, 396 | "metadata": {}, 397 | "outputs": [], 398 | "source": [ 399 | "// delete 2nd node from the list\n", 400 | "// NOTE: header is not an actual node!\n", 401 | "curr = head->next->next;\n", 402 | "curr->prev->next = curr->next;\n", 403 | "curr->next->prev = curr->prev;\n", 404 | "delete curr;" 405 | ] 406 | }, 407 | { 408 | "cell_type": "code", 409 | "execution_count": 24, 410 | "metadata": {}, 411 | "outputs": [ 412 | { 413 | "name": "stdout", 414 | "output_type": "stream", 415 | "text": [ 416 | "[ 200 20 30 ]" 417 | ] 418 | } 419 | ], 420 | "source": [ 421 | "traverseForward(head);" 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "metadata": {}, 427 | "source": [ 428 | "## Doubly Linked List Insert\n", 429 | "- insert an element/node after certain node in the linked list\n", 430 | "- similar to push front operation\n", 431 | "- algorithm steps:\n", 432 | " 1. create a new node with the data\n", 433 | " - find the location where the new node needs to be inserted after, say curr\n", 434 | " - insert the new node at that location\n", 435 | " - update doubly linked list" 436 | ] 437 | }, 438 | { 439 | "cell_type": "code", 440 | "execution_count": null, 441 | "metadata": {}, 442 | "outputs": [], 443 | "source": [ 444 | "// insert element as the 2nd node (after the first node) with key value 100\n", 445 | "// NOTE: header node is not an actual node!\n", 446 | "curr = head->next;\n", 447 | "temp = new Int_Node;\n", 448 | "temp->data = 100;\n", 449 | "temp->next = curr->next;\n", 450 | "temp->prev = curr;\n", 451 | "curr->next = temp;\n", 452 | "temp->next->prev = temp;" 453 | ] 454 | }, 455 | { 456 | "cell_type": "code", 457 | "execution_count": null, 458 | "metadata": {}, 459 | "outputs": [], 460 | "source": [ 461 | "traverseForward(head);" 462 | ] 463 | }, 464 | { 465 | "cell_type": "markdown", 466 | "metadata": {}, 467 | "source": [ 468 | "## Doubly Linked List Implementation as ADT\n", 469 | "- following Doulby Linked list as ADT works for integer data\n", 470 | "- it can be easily converted into a template class\n", 471 | " - this is left as an exercise" 472 | ] 473 | }, 474 | { 475 | "cell_type": "code", 476 | "execution_count": 3, 477 | "metadata": {}, 478 | "outputs": [], 479 | "source": [ 480 | "#include \n", 481 | "using namespace std;" 482 | ] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "execution_count": 4, 487 | "metadata": {}, 488 | "outputs": [ 489 | { 490 | "name": "stderr", 491 | "output_type": "stream", 492 | "text": [ 493 | "\u001b[1minput_line_12:1:8: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mredefinition of 'Int_Node'\u001b[0m\n", 494 | "struct Int_Node {\n", 495 | "\u001b[0;1;32m ^\n", 496 | "\u001b[0m\u001b[1minput_line_9:1:8: \u001b[0m\u001b[0;1;30mnote: \u001b[0mprevious definition is here\u001b[0m\n", 497 | "struct Int_Node {\n", 498 | "\u001b[0;1;32m ^\n", 499 | "\u001b[0m" 500 | ] 501 | }, 502 | { 503 | "ename": "Interpreter Error", 504 | "evalue": "", 505 | "output_type": "error", 506 | "traceback": [ 507 | "Interpreter Error: " 508 | ] 509 | } 510 | ], 511 | "source": [ 512 | "struct Int_Node {\n", 513 | " int data; // int data\n", 514 | " Int_Node * next; // address of the next node\n", 515 | " Int_Node * prev; // address of the previous node\n", 516 | "};" 517 | ] 518 | }, 519 | { 520 | "cell_type": "code", 521 | "execution_count": 5, 522 | "metadata": {}, 523 | "outputs": [], 524 | "source": [ 525 | "class IntDoublyList {\n", 526 | " private:\n", 527 | " Int_Node * head;\n", 528 | " Int_Node * tail;\n", 529 | " size_t count;\n", 530 | " // removes curr node\n", 531 | " void remove(Int_Node* curr) {\n", 532 | " curr->prev->next = curr->next;\n", 533 | " curr->next->prev = curr->prev;\n", 534 | " delete curr;\n", 535 | " this->count--;\n", 536 | " }\n", 537 | " \n", 538 | " public:\n", 539 | " IntDoublyList() {\n", 540 | " this->count = 0;\n", 541 | " // create empty header and trailer nodes as shown in figure above\n", 542 | " Int_Node * temp = new Int_Node; //create header node\n", 543 | " temp->data = 0;\n", 544 | " temp->prev = NULL;\n", 545 | " temp->next = NULL;\n", 546 | " head = temp; // head points to header node\n", 547 | "\n", 548 | " temp = new Int_Node; // create trailer node\n", 549 | " temp->data = 0;\n", 550 | " temp->prev = head; // trailer points to header\n", 551 | " temp->next = NULL;\n", 552 | " tail = temp;\n", 553 | "\n", 554 | " head->next = tail; // header points to trailer\n", 555 | " }\n", 556 | " \n", 557 | " bool empty() const {\n", 558 | " return this->count == 0;\n", 559 | " }\n", 560 | " \n", 561 | " // adds an element to the end\n", 562 | " void push_back(int data) {\n", 563 | " Int_Node * node = new Int_Node;\n", 564 | " node->data = data;\n", 565 | " node->next = tail;\n", 566 | " node->prev = tail->prev;\n", 567 | " tail->prev->next = node;\n", 568 | " tail->prev = node;\n", 569 | " this->count++;\n", 570 | " }\n", 571 | " // inserts an element to the beginning\n", 572 | " void push_front(int data) {\n", 573 | " // FIXME\n", 574 | " }\n", 575 | " // access the last element\n", 576 | " int back() {\n", 577 | " return tail->prev->data;\n", 578 | " }\n", 579 | " \n", 580 | " // return the size of the list\n", 581 | " size_t size() {\n", 582 | " return this->count;\n", 583 | " }\n", 584 | " \n", 585 | " // access the first element\n", 586 | " // FIXME - implement method to access the data in first node\n", 587 | " \n", 588 | " // removes the last element\n", 589 | " void pop_back() {\n", 590 | " // nothing to do in an empty list\n", 591 | " if (empty()) return;\n", 592 | " this->remove(tail->prev);\n", 593 | " }\n", 594 | " \n", 595 | " // removes the first element\n", 596 | " // FIXME - implement a method to remove the first node\n", 597 | " \n", 598 | " // visits every node and prints the data\n", 599 | " // traverse in forward direction\n", 600 | " void traverseForward() {\n", 601 | " cout << \"[\";\n", 602 | " Int_Node * curr = head->next;\n", 603 | " while (curr != tail) {\n", 604 | " cout << \" \" << curr->data;\n", 605 | " curr = curr->next;\n", 606 | " }\n", 607 | " cout << \" ]\";\n", 608 | " }\n", 609 | " \n", 610 | " // traverseBackward\n", 611 | " // visits every node and prints the data in backward direction\n", 612 | " void traverseBackward() {\n", 613 | " // FIXME...\n", 614 | " }\n", 615 | " \n", 616 | " // insert a node with a given data after the node with the after_key value\n", 617 | " // if the element with after_key not found, insert data at the end\n", 618 | " void insert_after(int after_key, int data) {\n", 619 | " // FIXME: \n", 620 | " }\n", 621 | " \n", 622 | " // clears the linked list deleting all the nodes \n", 623 | " // except for the header and trailer nodes\n", 624 | " void clear() {\n", 625 | " // FIXME...\n", 626 | " }\n", 627 | "};" 628 | ] 629 | }, 630 | { 631 | "cell_type": "code", 632 | "execution_count": 6, 633 | "metadata": {}, 634 | "outputs": [], 635 | "source": [ 636 | "// test IntDoublyList with some data\n", 637 | "IntDoublyList ilist;" 638 | ] 639 | }, 640 | { 641 | "cell_type": "code", 642 | "execution_count": 8, 643 | "metadata": {}, 644 | "outputs": [ 645 | { 646 | "name": "stdout", 647 | "output_type": "stream", 648 | "text": [ 649 | "[ ]" 650 | ] 651 | } 652 | ], 653 | "source": [ 654 | "ilist.traverseForward();" 655 | ] 656 | }, 657 | { 658 | "cell_type": "code", 659 | "execution_count": 9, 660 | "metadata": {}, 661 | "outputs": [ 662 | { 663 | "name": "stdout", 664 | "output_type": "stream", 665 | "text": [ 666 | "[ 10 ]" 667 | ] 668 | } 669 | ], 670 | "source": [ 671 | "ilist.push_back(10);\n", 672 | "ilist.traverseForward();" 673 | ] 674 | }, 675 | { 676 | "cell_type": "code", 677 | "execution_count": 10, 678 | "metadata": {}, 679 | "outputs": [ 680 | { 681 | "name": "stdout", 682 | "output_type": "stream", 683 | "text": [ 684 | "[ 10 20 30 ]" 685 | ] 686 | } 687 | ], 688 | "source": [ 689 | "ilist.push_back(20);\n", 690 | "ilist.push_back(30);\n", 691 | "ilist.traverseForward();" 692 | ] 693 | }, 694 | { 695 | "cell_type": "code", 696 | "execution_count": 11, 697 | "metadata": {}, 698 | "outputs": [ 699 | { 700 | "name": "stdout", 701 | "output_type": "stream", 702 | "text": [ 703 | "[ 10 20 ]" 704 | ] 705 | } 706 | ], 707 | "source": [ 708 | "ilist.pop_back();\n", 709 | "ilist.traverseForward();" 710 | ] 711 | }, 712 | { 713 | "cell_type": "markdown", 714 | "metadata": {}, 715 | "source": [ 716 | "### Exercises\n", 717 | "1. Linked lists are better than array-based lists when the final size of the list is known in advance.\n", 718 | " 1. True\n", 719 | " - False\n", 720 | "\n", 721 | "2. Fix all the FIXMEs and test the fixes of doubly linked list ADT.\n", 722 | "3. Convert Doubly Linked List ADT as a template class to store data of any type in the node." 723 | ] 724 | }, 725 | { 726 | "cell_type": "code", 727 | "execution_count": null, 728 | "metadata": {}, 729 | "outputs": [], 730 | "source": [] 731 | } 732 | ], 733 | "metadata": { 734 | "kernelspec": { 735 | "display_name": "C++14", 736 | "language": "C++14", 737 | "name": "xeus-cling-cpp14" 738 | }, 739 | "language_info": { 740 | "codemirror_mode": "text/x-c++src", 741 | "file_extension": ".cpp", 742 | "mimetype": "text/x-c++src", 743 | "name": "c++", 744 | "version": "-std=c++14" 745 | } 746 | }, 747 | "nbformat": 4, 748 | "nbformat_minor": 2 749 | } 750 | -------------------------------------------------------------------------------- /Exceptions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Errors & Exceptions\n", 8 | "http://www.cplusplus.com/doc/tutorial/exceptions/\n", 9 | "http://openbookproject.net/thinkcs/python/english3e/exceptions.html\n", 10 | "\n", 11 | "## Table of Contents\n", 12 | "- **[Errors](#errors)**
\n", 13 | "- **[Exceptions](#exceptions)**
\n", 14 | "- **[Define Exceptions](#defineexception)**
\n" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "## Errors\n", 29 | "- errors are also called bugs in computer programs\n", 30 | "- as long as humans will write computer programs, there will always be some bugs in programs\n", 31 | "- the process of finding and getting rid of bugs is called debugging and is an integral part of programming\n", 32 | "- three types of errors:\n", 33 | " 1. **Syntax Errors**\n", 34 | " - errors in the grammar dictated by the programming language\n", 35 | " - programs will not run if there is a syntax error\n", 36 | " - compiler usually provides feedback on syntax errors\n", 37 | " - annoying in the beginning but one will get better as they become more proficient and experienced with the language\n", 38 | " - e.g., forgetting a colon or } or ] where they need to be\n", 39 | " - **Semantic Errors**\n", 40 | " - semantic errors are errors in programs that produce wrong answers\n", 41 | " - program will run successfully without generating any error messages\n", 42 | " - program will not do the right thing (does what you tell it to do!)\n", 43 | " - essentially, the problem is that the program you wrote is not the program you wanted to write\n", 44 | " - the meaning of the program (its semantics) is wrong\n", 45 | " - testing your program with lots of input samples will help you reveal semantic errors\n", 46 | " - identifying semantic errors can be tricky and requires you to work backward (traceback) by looking at the output and figure out what it is doing\n", 47 | " - **Exceptions**\n", 48 | " - run-time errors that may manifest at certain circumstances\n", 49 | " \n", 50 | "### Exercise\n", 51 | "Which of the following is a semantic error?\n", 52 | "1. Attempting to divide by 0\n", 53 | "- Forgetting a semicolon at the end of a statement where one is required\n", 54 | "- Forgetting to divide by 100 when printing a percentage amount" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "## Exceptions\n", 69 | "- exceptions are runtime errors that may occur in exceptional circumstances\n", 70 | "- unlike syntax error and logical/semantic errors, exceptions may or may not manifest while the program is being executed\n", 71 | "- when exception is thrown, program will halt if the exception is not handled!\n", 72 | " - can be catastrophic if the OS of Satellites, Mars Rovers, Airplanes halts (crashes)\n", 73 | "- C++ provides a mechanism to react to exceptional circumstances (runtime errors) in programs by transferring control to special functions called **handlers**\n", 74 | "- to catch exceptions, a portion of code is placed under exception inspection block called a **try-block**\n", 75 | "- when the exceptional circumstance arises within that block, an exception is thrown that transfers the control to the exception handler called **catch-block**\n", 76 | "- $3$ options to handle exceptions\n", 77 | " 1. if possible try to recover or correct error\n", 78 | " - if not possible to recover, log the error and continue\n", 79 | " - if option 1 or 2 is not possible, halt the program\n", 80 | "- if no exception is thrown, the code continues normally and all handlers (catch-blocks) are ignored\n", 81 | "- syntax:\n", 82 | "```c++\n", 83 | "try {\n", 84 | " // try code that may throw exceptions \n", 85 | "}\n", 86 | "catch(type1 name1) {\n", 87 | " // first handler that throws exception of type1\n", 88 | "}\n", 89 | "catch(type2 name2) {\n", 90 | " // second handler that throws exception of type2\n", 91 | "}\n", 92 | "... // other handlers\n", 93 | " // more generic handlers should be written towards the end\n", 94 | "catch(...) { // ellipsis\n", 95 | " // catch all exceptions if previous handler couldn't catch\n", 96 | "}\n", 97 | "```\n", 98 | "- various exception types\n", 99 | " - https://en.cppreference.com/w/cpp/error/exception" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 2, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "#include \n", 109 | "#include \n", 110 | "#include \n", 111 | "#include \n", 112 | "#include \n", 113 | "\n", 114 | "using namespace std;" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 2, 120 | "metadata": {}, 121 | "outputs": [ 122 | { 123 | "name": "stdout", 124 | "output_type": "stream", 125 | "text": [ 126 | "executed...\n", 127 | "Exception occured. #: 20\n" 128 | ] 129 | } 130 | ], 131 | "source": [ 132 | "try {\n", 133 | " cout << \"executed...\" << endl;\n", 134 | " throw 20; //throw an integer exception\n", 135 | "}\n", 136 | "catch (int ex) {\n", 137 | " cout << \"Exception occured. #: \" << ex << endl;\n", 138 | "}" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "## Example 1 - string.at() and string.substr() may throw out_of_range exception" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 3, 151 | "metadata": {}, 152 | "outputs": [ 153 | { 154 | "name": "stdout", 155 | "output_type": "stream", 156 | "text": [ 157 | "J\n" 158 | ] 159 | } 160 | ], 161 | "source": [ 162 | "// at method of string class throws std::out_of_range if pos >= size().\n", 163 | "string name = \"John Doe\";\n", 164 | "cout << name.at(0) << endl;" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 4, 170 | "metadata": {}, 171 | "outputs": [ 172 | { 173 | "ename": "Error", 174 | "evalue": "", 175 | "output_type": "error", 176 | "traceback": [ 177 | "Error: " 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "cout << name.at(20) << endl;\n", 183 | "cout << \"continue with the rest...\" << endl; // never executes" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 5, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "name": "stdout", 193 | "output_type": "stream", 194 | "text": [ 195 | "exception occured: basic_string\n", 196 | "continue with the rest...\n" 197 | ] 198 | }, 199 | { 200 | "data": { 201 | "text/plain": [ 202 | "@0x104a8c010" 203 | ] 204 | }, 205 | "execution_count": 5, 206 | "metadata": {}, 207 | "output_type": "execute_result" 208 | } 209 | ], 210 | "source": [ 211 | "// handle the exception\n", 212 | "try {\n", 213 | " cout << name.at(20) << endl;\n", 214 | "}\n", 215 | "catch(const out_of_range& e) {\n", 216 | " cout << \"exception occured: \" << e.what() << endl;\n", 217 | "}\n", 218 | "cout << \"continue with the rest...\" << endl; // will continue from here" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 6, 224 | "metadata": {}, 225 | "outputs": [ 226 | { 227 | "name": "stdout", 228 | "output_type": "stream", 229 | "text": [ 230 | "Doe\n", 231 | "continue with other code...\n" 232 | ] 233 | } 234 | ], 235 | "source": [ 236 | "// substr() method throws out_of_range exception\n", 237 | "cout << name.substr(5) << endl;\n", 238 | "cout << \"continue with other code...\" << endl;" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 7, 244 | "metadata": {}, 245 | "outputs": [ 246 | { 247 | "ename": "Error", 248 | "evalue": "", 249 | "output_type": "error", 250 | "traceback": [ 251 | "Error: " 252 | ] 253 | } 254 | ], 255 | "source": [ 256 | "try {\n", 257 | " cout << name.substr(20) << endl;\n", 258 | "}\n", 259 | "catch(int e1) {\n", 260 | " cout << \"Interger exception occured: exception #: \" << e1 << endl;\n", 261 | "}\n", 262 | "cout << \"continue with other code...\" << endl;" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 11, 268 | "metadata": {}, 269 | "outputs": [ 270 | { 271 | "name": "stdout", 272 | "output_type": "stream", 273 | "text": [ 274 | "exception: out_of_range: basic_string\n", 275 | "continue with other code...\n" 276 | ] 277 | } 278 | ], 279 | "source": [ 280 | "// substr() method throws out_of_range exception\n", 281 | "try {\n", 282 | " cout << name.substr(20) << endl;\n", 283 | "}\n", 284 | "catch(int e1) {\n", 285 | " cout << \"Interger exception occured: exception #: \" << e1 << endl;\n", 286 | "}\n", 287 | "catch(const out_of_range & ofr) {\n", 288 | " cout << \"exception: out_of_range: \" << ofr.what() << endl;\n", 289 | " // can catch out_of_range exception to know exactly what exception was thrown\n", 290 | "}\n", 291 | "catch(...) { \n", 292 | " cout << \"some exception flew by...\" << endl;\n", 293 | "}\n", 294 | "cout << \"continue with other code...\" << endl;" 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "metadata": {}, 300 | "source": [ 301 | "## Example 2 - bad_alloc exception\n", 302 | "https://en.cppreference.com/w/cpp/memory/new/bad_alloc" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 1, 308 | "metadata": {}, 309 | "outputs": [], 310 | "source": [ 311 | "#include \n", 312 | "using namespace std;" 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": 2, 318 | "metadata": {}, 319 | "outputs": [], 320 | "source": [ 321 | "unsigned long long int n;\n", 322 | "int *nums;" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": 4, 328 | "metadata": {}, 329 | "outputs": [ 330 | { 331 | "name": "stdout", 332 | "output_type": "stream", 333 | "text": [ 334 | "Enter how many integers would you like to store?100000000000000\n" 335 | ] 336 | }, 337 | { 338 | "ename": "Standard Exception", 339 | "evalue": "std::bad_alloc", 340 | "output_type": "error", 341 | "traceback": [ 342 | "Standard Exception: std::bad_alloc" 343 | ] 344 | } 345 | ], 346 | "source": [ 347 | "cout << \"Enter how many integers would you like to store?\";\n", 348 | "cin >> n;\n", 349 | "nums = new int[n]; // try 10000000000000\n", 350 | "cout << \"successfully allocated memory to store \" << n << \" integers\\n\";" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": 5, 356 | "metadata": {}, 357 | "outputs": [ 358 | { 359 | "name": "stdout", 360 | "output_type": "stream", 361 | "text": [ 362 | "Enter how many integers would you like to store?1000000000000000\n", 363 | "Exception occured: std::bad_alloc\n", 364 | "continue...\n" 365 | ] 366 | } 367 | ], 368 | "source": [ 369 | "n = 0;\n", 370 | "cout << \"Enter how many integers would you like to store?\";\n", 371 | "cin >> n;\n", 372 | "try {\n", 373 | " nums = new int[n]; // try 10000000000000\n", 374 | " cout << \"successfully allocated memory to store \" << n << \" integers\\n\";\n", 375 | "}\n", 376 | "catch(const bad_alloc & e) {\n", 377 | " cout << \"Exception occured: \" << e.what() << endl;\n", 378 | "}\n", 379 | "cout << \"continue...\" << endl;" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": 6, 385 | "metadata": {}, 386 | "outputs": [ 387 | { 388 | "name": "stdout", 389 | "output_type": "stream", 390 | "text": [ 391 | "Exception occured: std::bad_alloc\n", 392 | "size of nums = 10\n" 393 | ] 394 | } 395 | ], 396 | "source": [ 397 | "vector v(10);\n", 398 | "try {\n", 399 | " // try resizing vector to a large value\n", 400 | " v.resize(1000000000000000000);\n", 401 | "}\n", 402 | "catch(const bad_alloc & e) {\n", 403 | " cout << \"Exception occured: \" << e.what() << endl;\n", 404 | "}\n", 405 | "cout << \"size of nums = \" << v.size() << endl;" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "## Example 3 - input validation" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": 1, 418 | "metadata": {}, 419 | "outputs": [], 420 | "source": [ 421 | "int decimalNum;\n", 422 | "bool valid;" 423 | ] 424 | }, 425 | { 426 | "cell_type": "code", 427 | "execution_count": 5, 428 | "metadata": {}, 429 | "outputs": [ 430 | { 431 | "name": "stdout", 432 | "output_type": "stream", 433 | "text": [ 434 | "Enter a number in decimal: adsf324\n", 435 | "Enter a number in decimal: adf\n", 436 | "Enter a number in decimal: sdaf\n", 437 | "Enter a number in decimal: 234\n", 438 | "Thank you for entering a number: 234\n" 439 | ] 440 | } 441 | ], 442 | "source": [ 443 | "// User input with validation\n", 444 | "valid = false;\n", 445 | "do\n", 446 | "{\n", 447 | " cout << \"Enter a number in decimal: \";\n", 448 | " try\n", 449 | " {\n", 450 | " cin >> decimalNum;\n", 451 | " if (cin.fail())\n", 452 | " {\n", 453 | " throw \"Invalid input. Tray again!\";\n", 454 | " }\n", 455 | " valid = true;\n", 456 | " }\n", 457 | " catch (const char *error)\n", 458 | " {\n", 459 | " cin.clear(); // clear the cin failure state\n", 460 | " cin.ignore(100, '\\n'); // ignore next 100 characters or up to \\n char\n", 461 | " printf(\"%s\\n\", error);\n", 462 | " }\n", 463 | "} while (!valid);\n", 464 | "\n", 465 | "cout << \"Thank you for entering a number: \" << decimalNum << endl;" 466 | ] 467 | }, 468 | { 469 | "cell_type": "markdown", 470 | "metadata": {}, 471 | "source": [ 472 | "" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": {}, 478 | "source": [ 479 | "## Division by zero\n", 480 | "- in C++ division by zero is not an exception!\n", 481 | "- typically program crashes without throwing an exception" 482 | ] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "execution_count": 6, 487 | "metadata": {}, 488 | "outputs": [ 489 | { 490 | "name": "stderr", 491 | "output_type": "stream", 492 | "text": [ 493 | "\u001b[1minput_line_13:2:11: \u001b[0m\u001b[0;1;35mwarning: \u001b[0m\u001b[1mdivision by zero is undefined [-Wdivision-by-zero]\u001b[0m\n", 494 | " cout << 3/0 << endl;\n", 495 | "\u001b[0;1;32m ^~\n", 496 | "\u001b[0m" 497 | ] 498 | }, 499 | { 500 | "name": "stdout", 501 | "output_type": "stream", 502 | "text": [ 503 | "21\n" 504 | ] 505 | } 506 | ], 507 | "source": [ 508 | "cout << 3/0 << endl;" 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": {}, 514 | "source": [ 515 | "## Create your own exception class" 516 | ] 517 | }, 518 | { 519 | "cell_type": "code", 520 | "execution_count": 9, 521 | "metadata": {}, 522 | "outputs": [], 523 | "source": [ 524 | "// DivisionByZero class inherits from base exception class\n", 525 | "class DivisionByZero {\n", 526 | " private:\n", 527 | " string description;\n", 528 | " public:\n", 529 | " DivisionByZero(const string& des=\"Zero Division Error\") {\n", 530 | " this->description = des;\n", 531 | " }\n", 532 | " string what() const {\n", 533 | " return this->description;\n", 534 | " } \n", 535 | "};" 536 | ] 537 | }, 538 | { 539 | "cell_type": "code", 540 | "execution_count": 7, 541 | "metadata": {}, 542 | "outputs": [], 543 | "source": [ 544 | "int divisor, dividend;\n", 545 | "int quotient;" 546 | ] 547 | }, 548 | { 549 | "cell_type": "code", 550 | "execution_count": 11, 551 | "metadata": {}, 552 | "outputs": [ 553 | { 554 | "name": "stdout", 555 | "output_type": "stream", 556 | "text": [ 557 | "Enter divisor and dividend separated by space: 0 4\n", 558 | "Exception: Zero Division Error\n", 559 | "continue..." 560 | ] 561 | } 562 | ], 563 | "source": [ 564 | "cout << \"Enter divisor and dividend separated by space: \";\n", 565 | "cin >> divisor >> dividend;\n", 566 | "//assert(divisor != 0); // can do this\n", 567 | "try { \n", 568 | " if (divisor == 0)\n", 569 | " throw DivisionByZero();\n", 570 | " quotient = dividend/divisor;\n", 571 | " cout << dividend << \" / \" << divisor << \" = \" << quotient << endl;\n", 572 | "}\n", 573 | "catch(const DivisionByZero& e) {\n", 574 | " cout << \"Exception: \" << e.what() << endl;\n", 575 | "}\n", 576 | "cout << \"continue...\";" 577 | ] 578 | }, 579 | { 580 | "cell_type": "code", 581 | "execution_count": null, 582 | "metadata": {}, 583 | "outputs": [], 584 | "source": [] 585 | } 586 | ], 587 | "metadata": { 588 | "kernelspec": { 589 | "display_name": "C++14", 590 | "language": "C++14", 591 | "name": "xeus-cling-cpp14" 592 | }, 593 | "language_info": { 594 | "codemirror_mode": "text/x-c++src", 595 | "file_extension": ".cpp", 596 | "mimetype": "text/x-c++src", 597 | "name": "c++", 598 | "version": "-std=c++14" 599 | } 600 | }, 601 | "nbformat": 4, 602 | "nbformat_minor": 2 603 | } 604 | -------------------------------------------------------------------------------- /FunctionTemplates.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Function Overloading and Templates\n", 8 | "- http://www.cplusplus.com/doc/oldtutorial/templates/\n", 9 | "\n", 10 | "## Table of Contents\n", 11 | "- [Function overloading](#overloading)\n", 12 | "- [Function templates](#templates)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "## Headers and helper functions\n", 20 | "- run include headers and helper function cells if Kernel crashes or is restarted" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 11, 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "// headers and namespace required in this notebook demo codes\n", 30 | "#include \n", 31 | "#include \n", 32 | "#include //stringstream type\n", 33 | "#include //typeid operator\n", 34 | "\n", 35 | "using namespace std;" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "## Function overloading\n", 50 | "- a function works only on the types, it is defined to work on!\n", 51 | "- we can define the same function name several times to work on different types; called function overloading\n", 52 | "- same function name can be redefined as long as the type and number of parameters differ from each other" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 2, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "int add(int n1, int n2) {\n", 62 | " int sum = n1 + n2;\n", 63 | " return sum;\n", 64 | "}" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 3, 70 | "metadata": {}, 71 | "outputs": [ 72 | { 73 | "name": "stdout", 74 | "output_type": "stream", 75 | "text": [ 76 | "110\n" 77 | ] 78 | } 79 | ], 80 | "source": [ 81 | "cout << add(10, 100) << endl;" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 4, 87 | "metadata": {}, 88 | "outputs": [ 89 | { 90 | "name": "stderr", 91 | "output_type": "stream", 92 | "text": [ 93 | "\u001b[1minput_line_12:5:13: \u001b[0m\u001b[0;1;35mwarning: \u001b[0m\u001b[1mimplicit conversion from 'float' to 'int' changes value from 10.5 to 10 [-Wliteral-conversion]\u001b[0m\n", 94 | "cout << add(10.5f, 100.99f) << endl;\n", 95 | "\u001b[0;1;32m ~~~ ^~~~~\n", 96 | "\u001b[0m\u001b[1minput_line_12:5:20: \u001b[0m\u001b[0;1;35mwarning: \u001b[0m\u001b[1mimplicit conversion from 'float' to 'int' changes value from 100.99 to 100\n", 97 | " [-Wliteral-conversion]\u001b[0m\n", 98 | "cout << add(10.5f, 100.99f) << endl;\n", 99 | "\u001b[0;1;32m ~~~ ^~~~~~~\n", 100 | "\u001b[0m\u001b[1minput_line_12:6:13: \u001b[0m\u001b[0;1;35mwarning: \u001b[0m\u001b[1mimplicit conversion from 'double' to 'int' changes value from 100.2 to 100\n", 101 | " [-Wliteral-conversion]\u001b[0m\n", 102 | "cout << add(100.2, 200.8) << endl;\n", 103 | "\u001b[0;1;32m ~~~ ^~~~~\n", 104 | "\u001b[0m\u001b[1minput_line_12:6:20: \u001b[0m\u001b[0;1;35mwarning: \u001b[0m\u001b[1mimplicit conversion from 'double' to 'int' changes value from 200.8 to 200\n", 105 | " [-Wliteral-conversion]\u001b[0m\n", 106 | "cout << add(100.2, 200.8) << endl;\n", 107 | "\u001b[0;1;32m ~~~ ^~~~~\n", 108 | "\u001b[0m" 109 | ] 110 | }, 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "110\n", 116 | "300\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "// what about float, and double?\n", 122 | "// by default decimal numbers are stored as double;\n", 123 | "// so, add f at the end to tell compiler to treat it as a float\n", 124 | "cout << add(10.5f, 100.99f) << endl;\n", 125 | "cout << add(100.2, 200.8) << endl;" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 5, 131 | "metadata": {}, 132 | "outputs": [ 133 | { 134 | "name": "stderr", 135 | "output_type": "stream", 136 | "text": [ 137 | "\u001b[1minput_line_13:2:10: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mno matching function for call to 'add'\u001b[0m\n", 138 | " cout << add(string(\"hello\"), string(\"world!\"));\n", 139 | "\u001b[0;1;32m ^~~\n", 140 | "\u001b[0m\u001b[1minput_line_10:1:5: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate function not viable: no known conversion from 'std::__1::string' (aka\n", 141 | " 'basic_string, allocator >') to 'int' for 1st argument\u001b[0m\n", 142 | "int add(int n1, int n2) {\n", 143 | "\u001b[0;1;32m ^\n", 144 | "\u001b[0m" 145 | ] 146 | }, 147 | { 148 | "ename": "Interpreter Error", 149 | "evalue": "", 150 | "output_type": "error", 151 | "traceback": [ 152 | "Interpreter Error: " 153 | ] 154 | } 155 | ], 156 | "source": [ 157 | "cout << add(string(\"hello\"), string(\"world!\"));" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 8, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "// overload add function to work on float type\n", 167 | "float add(float n1, float n2) {\n", 168 | " float s = n1 + n2;\n", 169 | " return s;\n", 170 | "}" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 9, 176 | "metadata": {}, 177 | "outputs": [ 178 | { 179 | "name": "stdout", 180 | "output_type": "stream", 181 | "text": [ 182 | "111.49\n" 183 | ] 184 | } 185 | ], 186 | "source": [ 187 | "cout << add(10.5f, 100.99f) << endl;" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": 11, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "// overload add function to work on double type\n", 197 | "double add(double n1, double n2) {\n", 198 | " double s = n1 + n2;\n", 199 | " return s;\n", 200 | "}" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 12, 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "name": "stdout", 210 | "output_type": "stream", 211 | "text": [ 212 | "301\n" 213 | ] 214 | } 215 | ], 216 | "source": [ 217 | "cout << add(100.2, 200.8) << endl;" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 13, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "// overload add function to work on string type\n", 227 | "string add(string s1, string s2) {\n", 228 | " string s = s1 + s2;\n", 229 | " return s;\n", 230 | "}" 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": 15, 236 | "metadata": {}, 237 | "outputs": [ 238 | { 239 | "name": "stdout", 240 | "output_type": "stream", 241 | "text": [ 242 | "helloworld!" 243 | ] 244 | } 245 | ], 246 | "source": [ 247 | "cout << add(string(\"hello\"), string(\"world!\"));" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": 9, 253 | "metadata": {}, 254 | "outputs": [], 255 | "source": [ 256 | "// overload add function to work on char types\n", 257 | "string add(char c1, char c2) {\n", 258 | " string s = string(1, c1) + string(1, c2);\n", 259 | " return s;\n", 260 | "}" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": 10, 266 | "metadata": {}, 267 | "outputs": [ 268 | { 269 | "name": "stdout", 270 | "output_type": "stream", 271 | "text": [ 272 | "AB\n" 273 | ] 274 | } 275 | ], 276 | "source": [ 277 | "cout << add('A', 'B') << endl;" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 14, 283 | "metadata": {}, 284 | "outputs": [], 285 | "source": [ 286 | "// another implementation to overload add function to work on char types\n", 287 | "string addChar(char c1, char c2) {\n", 288 | " stringstream ss;\n", 289 | " ss << c1 << c2;\n", 290 | " string s;\n", 291 | " ss >> s;\n", 292 | " return s;\n", 293 | "}" 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 15, 299 | "metadata": {}, 300 | "outputs": [ 301 | { 302 | "name": "stdout", 303 | "output_type": "stream", 304 | "text": [ 305 | "AB\n" 306 | ] 307 | } 308 | ], 309 | "source": [ 310 | "cout << addChar('A', 'B') << endl;" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "metadata": {}, 316 | "source": [ 317 | "" 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "## Function templates\n", 325 | "- special function that can operate with generic types\n", 326 | "- allows us to create a single function that can be adapted to more than one type or class without repeating entire code for each type as in function overloading\n", 327 | "- template parameters allow us to pass parameters types to functions\n", 328 | "- syntax:\n", 329 | "```c++\n", 330 | "template \n", 331 | "T1 functionName(T1 para1, T2 para2, ...) {\n", 332 | " // function body\n", 333 | "}\n", 334 | "```" 335 | ] 336 | }, 337 | { 338 | "cell_type": "code", 339 | "execution_count": 2, 340 | "metadata": {}, 341 | "outputs": [], 342 | "source": [ 343 | "template \n", 344 | "T addition(T para1, T para2) {\n", 345 | " T result = para1 + para2;\n", 346 | " return result;\n", 347 | "}" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 3, 353 | "metadata": {}, 354 | "outputs": [ 355 | { 356 | "name": "stdout", 357 | "output_type": "stream", 358 | "text": [ 359 | "30\n", 360 | "31\n", 361 | "31\n", 362 | "hi there!" 363 | ] 364 | } 365 | ], 366 | "source": [ 367 | "// implicit: types are automatically inferred based on the types of arguments\n", 368 | "cout << addition(10, 20) << endl;\n", 369 | "cout << addition(10.5f, 20.5f) << endl;\n", 370 | "cout << addition(10.5, 20.5) << endl;\n", 371 | "cout << addition(string(\"hi \"), string(\"there!\"));" 372 | ] 373 | }, 374 | { 375 | "cell_type": "code", 376 | "execution_count": 4, 377 | "metadata": {}, 378 | "outputs": [ 379 | { 380 | "name": "stdout", 381 | "output_type": "stream", 382 | "text": [ 383 | "30\n", 384 | "31\n", 385 | "301\n", 386 | "hi there!" 387 | ] 388 | } 389 | ], 390 | "source": [ 391 | "// explicit: types are explicitly passed\n", 392 | "cout << addition(10, 20) << endl;\n", 393 | "cout << addition(10.5, 20.5) << endl; // notice no f at the end of numbers\n", 394 | "cout << addition(100.5, 200.5) << endl; \n", 395 | "cout << addition(string(\"hi \"), string(\"there!\"));" 396 | ] 397 | }, 398 | { 399 | "cell_type": "code", 400 | "execution_count": 10, 401 | "metadata": {}, 402 | "outputs": [ 403 | { 404 | "name": "stderr", 405 | "output_type": "stream", 406 | "text": [ 407 | "\u001b[1minput_line_20:3:9: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mno template named 'addition'; did you mean 'addition1'?\u001b[0m\n", 408 | "cout << addition('A', 'B') << endl;\n", 409 | "\u001b[0;1;32m ^~~~~~~~\n", 410 | "\u001b[0m\u001b[0;32m addition1\n", 411 | "\u001b[0m\u001b[1minput_line_10:2:9: \u001b[0m\u001b[0;1;30mnote: \u001b[0m'addition1' declared here\u001b[0m\n", 412 | "returnT addition1(T para1, T para2) {\n", 413 | "\u001b[0;1;32m ^\n", 414 | "\u001b[0m\u001b[1minput_line_20:3:9: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mno matching function for call to 'addition1'\u001b[0m\n", 415 | "cout << addition('A', 'B') << endl;\n", 416 | "\u001b[0;1;32m ^~~~~~~~~~~~~~~~\n", 417 | "\u001b[0m\u001b[1minput_line_10:2:9: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate template ignored: couldn't infer template argument 'returnT'\u001b[0m\n", 418 | "returnT addition1(T para1, T para2) {\n", 419 | "\u001b[0;1;32m ^\n", 420 | "\u001b[0m" 421 | ] 422 | }, 423 | { 424 | "ename": "Interpreter Error", 425 | "evalue": "", 426 | "output_type": "error", 427 | "traceback": [ 428 | "Interpreter Error: " 429 | ] 430 | } 431 | ], 432 | "source": [ 433 | "// expected output AB, but get error!\n", 434 | "cout << addition('A', 'B') << endl;" 435 | ] 436 | }, 437 | { 438 | "cell_type": "code", 439 | "execution_count": 7, 440 | "metadata": {}, 441 | "outputs": [ 442 | { 443 | "name": "stdout", 444 | "output_type": "stream", 445 | "text": [ 446 | "c\n", 447 | "f\n", 448 | "d\n", 449 | "NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE\n", 450 | "i\n" 451 | ] 452 | } 453 | ], 454 | "source": [ 455 | "// typeid operator found in typeinfo header comes to rescue!!\n", 456 | "//https://en.cppreference.com/w/cpp/language/typeid\n", 457 | "// if we can find type of generic type T, we can write more generic template function\n", 458 | "// that works for addition of char type as well!\n", 459 | "cout << typeid(char).name() << endl;\n", 460 | "cout << typeid(float).name() << endl;\n", 461 | "cout << typeid(double).name() << endl;\n", 462 | "cout << typeid(string).name() << endl;\n", 463 | "cout << typeid(int).name() << endl;" 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": 2, 469 | "metadata": {}, 470 | "outputs": [], 471 | "source": [ 472 | "template \n", 473 | "returnT addition1(T para1, T para2) {\n", 474 | " returnT result;\n", 475 | " stringstream ss;\n", 476 | " if (typeid(T).name() == typeid(char).name()) {\n", 477 | " ss << para1 << para2;\n", 478 | " ss >> result;\n", 479 | " }\n", 480 | " else\n", 481 | " result = para1 + para2;\n", 482 | " return result;\n", 483 | "}" 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": 4, 489 | "metadata": {}, 490 | "outputs": [ 491 | { 492 | "name": "stdout", 493 | "output_type": "stream", 494 | "text": [ 495 | "30\n", 496 | "31\n", 497 | "301\n", 498 | "hi there!" 499 | ] 500 | } 501 | ], 502 | "source": [ 503 | "// may help in overflow situations! addition of two large ints could overflow!!\n", 504 | "cout << addition1(10, 20) << endl;\n", 505 | "cout << addition1(10.5, 20.5) << endl; // notice no f at the end of numbers\n", 506 | "cout << addition1(100.5, 200.5) << endl; \n", 507 | "cout << addition1(string(\"hi \"), string(\"there!\"));" 508 | ] 509 | }, 510 | { 511 | "cell_type": "code", 512 | "execution_count": 9, 513 | "metadata": {}, 514 | "outputs": [ 515 | { 516 | "name": "stdout", 517 | "output_type": "stream", 518 | "text": [ 519 | "AB\n" 520 | ] 521 | } 522 | ], 523 | "source": [ 524 | "cout << addition1('A', 'B') << endl;" 525 | ] 526 | }, 527 | { 528 | "cell_type": "code", 529 | "execution_count": null, 530 | "metadata": {}, 531 | "outputs": [], 532 | "source": [] 533 | } 534 | ], 535 | "metadata": { 536 | "kernelspec": { 537 | "display_name": "C++14", 538 | "language": "C++14", 539 | "name": "xcpp14" 540 | }, 541 | "language_info": { 542 | "codemirror_mode": "text/x-c++src", 543 | "file_extension": ".cpp", 544 | "mimetype": "text/x-c++src", 545 | "name": "c++", 546 | "version": "14" 547 | } 548 | }, 549 | "nbformat": 4, 550 | "nbformat_minor": 2 551 | } 552 | -------------------------------------------------------------------------------- /Introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Introduction\n", 8 | "in-depth: https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/IntroDSA.html" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "- Some problems to think about...\n", 16 | " 1. What is the fastest route from Los Angeles, CA to NYC, NY? \n", 17 | " - how long does it take to get there?\n", 18 | " 2. What is the most reliable source on the Internet to learn about data structures and algorithms?\n", 19 | " 3. Who was the most influential celebrity/politician of last year?\n", 20 | " 4. What is an average salary of a software engineer?\n", 21 | " 5. What is the cheapest way to travel from Grand Junction, CO, to Kathmandu, Nepal?\n", 22 | " 6. How does Apple's Siri know what appointment you have next when you ask it? " 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "## Computer Science (CS) fundamentals" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "- the core of CS is representing data so that it can be efficiently stored and retrieved\n", 37 | " - many computer programs sole functionality is to do just that, but as fast as possible. e.g., search engines like, Google, Bing, etc.\n", 38 | "- some programs may do heavy mathematical computation as fast as possible, e.g., wolframalpha computational intelligence (https://www.wolframalpha.com)\n", 39 | " - find factorial(10000) or 10000!\n", 40 | " \n", 41 | "**the study of data structures and the alogrithms that manipulate them to solve a given problem in feasible time and resource is the heart of compuer science**" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "## Goals of Data Structure (DS) and Algorithm courses" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "1. present a collection of commonly used data structures and algorithms, programmer's basic \"toolkit\"\n", 56 | " - for many problems these toolkit out-of-the box will provide efficient solutions\n", 57 | " - \"toolkit\" forms the basis/foundations to build more advanced data structures\n", 58 | "2. introduce the idea of trade-offs between the costs and benefits associated with every data structure or algorithm, e.g., trade-offs between memory and time\n", 59 | "3. learn to measure the effectiveness of a data structure or algorithm so you can pick the right ones for the job\n", 60 | " - also allows you to quickly judge the merits of new data structures or algorithms that you or others might invent" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## Solving problems" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | " - the primary job of computer scientists is to solve problems!\n", 75 | " - there are often too many approaches to solve a problem\n", 76 | " - at the heart of computer program designs are two (sometimes conflicting) goals:\n", 77 | " 1. to design an algorithm that is easy to understand, code, and debug\n", 78 | " 2. to design an algorithm that makes efficient use of the computer's resources\n", 79 | " - \"elegant\" solutions meet both these goals!\n", 80 | " - software engineering focuses on goal 1, though we emphasize it from CS1!\n", 81 | " - CS2 and CS3 usually focuses on goal 2." 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "## Why faster DS and algorithms when we've faster computers?" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "- according to Moore's law https://en.wikipedia.org/wiki/Moore%27s_law, no. of transistors in computer's circuit board doubles every two years.\n", 96 | "- so, if processor speed and memory size continue to improve, won't today's hard problem be solved by tomorrow's hardware?\n", 97 | "- additional computing power enables us to tackle more complex problems, such as sophisticated user interfaces such as in mobile devices, bigger problem sizes (big data), or new problems previously deemed computationally infeasible\n", 98 | "- resources are always limited...\n", 99 | "- efficient solution solves the problem within the required *resource constraints*.\n", 100 | " - may require fewer resources than known alternatives, regardless of whether it meets any particular requirements\n", 101 | "- **cost** of a solution is the amount of resources that the solution consumes\n", 102 | " - measured typically in terms of one key resource such as time implying it meets all other resource constraints \n", 103 | " - e.g., fastest solution on open.kattis.com problems meeting memory requirements: https://open.kattis.com/problems/cd/statistics" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "## Selecting a Data Structure" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "1. analyze your problem to determine the **basic operations** e.g., inserting data item into the data structure, deleting, finding a specified data item\n", 118 | "- quantify the resource constraints for each operation\n", 119 | "- select the data structure that best meets these requirements\n", 120 | "\n", 121 | "### Some questions to think about to determine the importance of operations\n", 122 | "1. is the application static or dynamic?\n", 123 | " - in static applications, data is loaded at the beginning and new data are not inserted\n", 124 | " - in dynamic applications, new data items are inserted and may be inserted in any locations\n", 125 | "- can data items be deleted? this may make the implementation more complicated\n", 126 | "- how are the data items processed? in some well-defined order, random access?" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "## Exercises\n", 134 | "1. Which of these is NOT a definition for efficiency in a computer program?\n", 135 | " - it solves the problem within the required resource constraints\n", 136 | " - it requires fewer resources than known alternatives\n", 137 | " - it runs in linear time" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": null, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [] 146 | } 147 | ], 148 | "metadata": { 149 | "kernelspec": { 150 | "display_name": "C++14", 151 | "language": "C++14", 152 | "name": "xcpp14" 153 | }, 154 | "language_info": { 155 | "codemirror_mode": "text/x-c++src", 156 | "file_extension": ".cpp", 157 | "mimetype": "text/x-c++src", 158 | "name": "c++", 159 | "version": "14" 160 | } 161 | }, 162 | "nbformat": 4, 163 | "nbformat_minor": 2 164 | } 165 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ram Basnet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MemorySegments.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Memory segments\n", 8 | "https://www.geeksforgeeks.org/memory-layout-of-c-program/\n", 9 | "\n", 10 | "## Table of Contents\n", 11 | "- [Memory segments](#segments)\n", 12 | "- [Demo program](#demo1)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "## Memory segments in C/C++ programs\n", 27 | "- main memory (RAM) is typically divided into 2 main spaces:\n", 28 | " 1. kernel space - reserved for running the kernel (OS background processes, device drivers, etc.)\n", 29 | " - loaded in lower addresses\n", 30 | " 2. user space - user-mode applications are loaded\n", 31 | " - loaded in higher addresses\n", 32 | " \n", 33 | "- in C/C++ programs, user space is divided into 5 different areas, called segments:\n", 34 | "\n", 35 | "\n", 36 | "\n", 37 | "### Stack segment\n", 38 | "- also called scratch pad\n", 39 | "- function parameters, local variables, and other function-related register variables are stored\n", 40 | "- grows and shrinks based on program needs\n", 41 | "\n", 42 | "### Heap segment\n", 43 | "- dynamically allocated variables (using pointers) are allocated from this segment\n", 44 | "- Heap size is normally much larger compared to stack size\n", 45 | "- size (actual) grows and shrinks based on program needs\n", 46 | " \n", 47 | "### BSS segment (Block Started by Symbol)\n", 48 | "- also called the uninitialized data segment)\n", 49 | "- zero-initialized or uninitialized global and static variables are stored\n", 50 | " \n", 51 | "### Data segment\n", 52 | "- also called the initialized data segment\n", 53 | "- initialized global and static variables are stored\n", 54 | "\n", 55 | "### Text segment (also called a code segment)\n", 56 | "- compiled program/code is loaded\n", 57 | "- code segment is typically read-only.\n", 58 | "\n", 59 | "Programmers primarily focus on the heap and the stack, as that is where most of the interesting stuff takes place." 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "## Demo program\n", 74 | "[memory_segments.cpp](./demo-programs/memory_segments.cpp)\n", 75 | " - compile and run memory_segments.cpp inside demo-programs folder to see various memory segements in use by a C++ program" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [] 84 | } 85 | ], 86 | "metadata": { 87 | "kernelspec": { 88 | "display_name": "C++14", 89 | "language": "C++14", 90 | "name": "xeus-cling-cpp14" 91 | }, 92 | "language_info": { 93 | "codemirror_mode": "text/x-c++src", 94 | "file_extension": ".cpp", 95 | "mimetype": "text/x-c++src", 96 | "name": "c++", 97 | "version": "-std=c++14" 98 | } 99 | }, 100 | "nbformat": 4, 101 | "nbformat_minor": 2 102 | } 103 | -------------------------------------------------------------------------------- /Queues.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Queues\n", 8 | "- https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/Queue.html\n", 9 | "- https://en.cppreference.com/w/cpp/container/queue\n", 10 | "\n", 11 | "\n", 12 | "## Table of Contents\n", 13 | "- **[Introduction](#intro)**
\n", 14 | "- **[Array-based Queue](#queue)**
\n", 15 | "- **[Linked Queue](#linked)**
" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "## Introduction\n", 30 | "- queue is a list-like data structure in which elements are inserted at the back and removed from front\n", 31 | " - less flexible than list\n", 32 | " - more efficient and easier to implement\n", 33 | "- operates as **FIFO** (First-In, First-Out) data structure\n", 34 | "- many applications require the limited form of insert and remove operations that queue provides\n", 35 | "- mimics real-world queues (lines) e.g., line of customers at restaurants/banks, queue of cars in drive-through\n", 36 | "\n", 37 | "\n", 38 | "### Applications\n", 39 | "- in computers, CPU scheduling, disk scheduling, file IO, network IO, etc.\n", 40 | "- email queues, print queues\n", 41 | "\n", 42 | "### Operations\n", 43 | "- enqueue : insert element at the back of queue\n", 44 | "- dequeue : remove and return element from the front of the queue" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "## Implementations of Queue as ADT\n", 59 | "- Queue can be implemented using array or linked-list\n", 60 | "\n", 61 | "### Array implementation of Queue\n", 62 | "- implementing array-based queue is as simple as stack\n", 63 | "- below is the array-based queue\n", 64 | "\n", 65 | "### Visualization of Array-based Queue\n", 66 | "https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/Queue.html" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "#include \n", 76 | "#include \n", 77 | "\n", 78 | "using namespace std;" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "template\n", 88 | "class ArrayQueue {\n", 89 | " private:\n", 90 | " size_t maxSize;\n", 91 | " size_t front, back;\n", 92 | " T * queue;\n", 93 | " size_t count;\n", 94 | " \n", 95 | " public:\n", 96 | " ArrayQueue(size_t mSize=100) { //constructor \n", 97 | " assert(mSize > 0);\n", 98 | " maxSize = mSize;\n", 99 | " queue = new T[maxSize];\n", 100 | " front = back = 0;\n", 101 | " count = 0;\n", 102 | " }\n", 103 | " \n", 104 | " // clear the queue\n", 105 | " void clear() { front = back = count = 0; }\n", 106 | " \n", 107 | " // get the size of the queue\n", 108 | " size_t size() { return count; }\n", 109 | " \n", 110 | " // check if queue is empty\n", 111 | " bool empty() { return count == 0; };\n", 112 | " \n", 113 | " // check if queue is full\n", 114 | " bool full() { return count == maxSize; }\n", 115 | " \n", 116 | " // return the max size\n", 117 | " size_t max_size() { return maxSize; }\n", 118 | " \n", 119 | " // add element to the end of queue\n", 120 | " void enqueue(T value) {\n", 121 | " if (full()) return;\n", 122 | " queue[back] = value;\n", 123 | " // circular increment\n", 124 | " back = (back+1)%maxSize;\n", 125 | " count++;\n", 126 | " }\n", 127 | " \n", 128 | " // remove and return the element from the front of the queue\n", 129 | " T dequeue() { \n", 130 | " T data = queue[front];\n", 131 | " //circular increment\n", 132 | " front = (front+1)%maxSize;\n", 133 | " count--;\n", 134 | " return data; \n", 135 | " }\n", 136 | " \n", 137 | " T next() {\n", 138 | " return queue[front];\n", 139 | " }\n", 140 | "};" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "## Test ArrayQueue Implementation" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": null, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "ArrayQueue aQ(5);" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 4, 162 | "metadata": {}, 163 | "outputs": [ 164 | { 165 | "name": "stdout", 166 | "output_type": "stream", 167 | "text": [ 168 | "size of aQ = 3" 169 | ] 170 | } 171 | ], 172 | "source": [ 173 | "aQ.enqueue(10);\n", 174 | "aQ.enqueue(20);\n", 175 | "aQ.enqueue(30);\n", 176 | "cout << \"size of aQ = \" << aQ.size();" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": 5, 182 | "metadata": {}, 183 | "outputs": [ 184 | { 185 | "name": "stdout", 186 | "output_type": "stream", 187 | "text": [ 188 | "front of the queue is: 10\n", 189 | "now the aQ size = 2\n" 190 | ] 191 | } 192 | ], 193 | "source": [ 194 | "cout << \"front of the queue is: \" << aQ.dequeue() << endl;\n", 195 | "cout << \"now the aQ size = \" << aQ.size() << endl;" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 12, 201 | "metadata": {}, 202 | "outputs": [ 203 | { 204 | "name": "stdout", 205 | "output_type": "stream", 206 | "text": [ 207 | "size of aQ = 5" 208 | ] 209 | } 210 | ], 211 | "source": [ 212 | "aQ.enqueue(40);\n", 213 | "aQ.enqueue(50);\n", 214 | "aQ.enqueue(60);\n", 215 | "cout << \"size of aQ = \" << aQ.size();" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 10, 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "name": "stdout", 225 | "output_type": "stream", 226 | "text": [ 227 | "size of aQ = 1" 228 | ] 229 | } 230 | ], 231 | "source": [ 232 | "aQ.enqueue(70);\n", 233 | "cout << \"size of aQ = \" << aQ.size();" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": 8, 239 | "metadata": {}, 240 | "outputs": [ 241 | { 242 | "name": "stdout", 243 | "output_type": "stream", 244 | "text": [ 245 | "max_size of aQ = 5" 246 | ] 247 | } 248 | ], 249 | "source": [ 250 | "cout << \"max_size of aQ = \" << aQ.max_size();" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 13, 256 | "metadata": {}, 257 | "outputs": [ 258 | { 259 | "name": "stdout", 260 | "output_type": "stream", 261 | "text": [ 262 | " next element = 70\n", 263 | " next element = 40\n", 264 | " next element = 50\n", 265 | " next element = 60\n", 266 | " next element = 40\n" 267 | ] 268 | } 269 | ], 270 | "source": [ 271 | "while (!aQ.empty()) {\n", 272 | " cout << \" next element = \" << aQ.dequeue() << endl; \n", 273 | "}" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "## Linked Queue Implementation\n", 288 | "- https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/QueueLinked.html\n", 289 | "- elements are inserted after the tail and removed only from the head of the list\n", 290 | "- header nodes are not required because no special-cases need to be handled\n", 291 | "- implementation and test is left as an assignment" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 14, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "#include \n", 301 | "#include \n", 302 | "\n", 303 | "using namespace std;" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": null, 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [ 312 | "template\n", 313 | "struct Node {\n", 314 | " T data;\n", 315 | " Node * next;\n", 316 | "};" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": null, 322 | "metadata": {}, 323 | "outputs": [], 324 | "source": [ 325 | "template\n", 326 | "class LinkedQueue{\n", 327 | " private:\n", 328 | " size_t nodeCount;\n", 329 | " Node * head;\n", 330 | " Node * tail;\n", 331 | " public:\n", 332 | " //constructor\n", 333 | " LinkedQueue();\n", 334 | " \n", 335 | " // clear the Queue\n", 336 | " void clear();\n", 337 | " \n", 338 | " // get the size of the Queue\n", 339 | " size_t size();\n", 340 | " \n", 341 | " // check if Queue is empty\n", 342 | " bool empty();\n", 343 | " \n", 344 | " //insert data at the end of the Queue\n", 345 | " void enqueue(T value);\n", 346 | " \n", 347 | " // remove and return element from front of the Queue\n", 348 | " T dequeue();\n", 349 | "};" 350 | ] 351 | }, 352 | { 353 | "cell_type": "markdown", 354 | "metadata": {}, 355 | "source": [ 356 | "## Test Linked Queue Implementation" 357 | ] 358 | }, 359 | { 360 | "cell_type": "code", 361 | "execution_count": null, 362 | "metadata": {}, 363 | "outputs": [], 364 | "source": [ 365 | "LinkedQueue lQ;" 366 | ] 367 | }, 368 | { 369 | "cell_type": "code", 370 | "execution_count": null, 371 | "metadata": {}, 372 | "outputs": [], 373 | "source": [ 374 | "lQ.enqueue(10);\n", 375 | "lQ.enqueue(20);\n", 376 | "lQ.enqueue(30);\n", 377 | "cout << \"size of lQ = \" << lQ.size();" 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": {}, 383 | "source": [ 384 | "## Exercises\n", 385 | "1. Server - https://open.kattis.com/problems/server\n", 386 | "- Ferry Loading III - https://open.kattis.com/problems/ferryloading3\n", 387 | "- Foosball Dynasty - https://open.kattis.com/problems/foosball\n" 388 | ] 389 | }, 390 | { 391 | "cell_type": "code", 392 | "execution_count": null, 393 | "metadata": {}, 394 | "outputs": [], 395 | "source": [] 396 | } 397 | ], 398 | "metadata": { 399 | "kernelspec": { 400 | "display_name": "C++14", 401 | "language": "C++14", 402 | "name": "xeus-cling-cpp14" 403 | }, 404 | "language_info": { 405 | "codemirror_mode": "text/x-c++src", 406 | "file_extension": ".cpp", 407 | "mimetype": "text/x-c++src", 408 | "name": "c++", 409 | "version": "-std=c++14" 410 | } 411 | }, 412 | "nbformat": 4, 413 | "nbformat_minor": 2 414 | } 415 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data Structures & Applications 2 | 3 | - Jupyter Notebooks for teaching and learning Data structures using C++ 4 | - Some chapters of notebooks are based on open-source textbook: [CS2 Software Design & Data Structures](https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/IntroDSA.html) from Virginia Tech's OpenDSA Project 5 | 6 | 7 | ## Requirements 8 | 9 | - Linux/MacOS/WSL on Windows (Not tested on Windows itself) 10 | - Jupyter Notebook 11 | - xeus-cling notebook kernel 12 | - git 13 | 14 | ## Install required tools 15 | 16 | - Note: these libraries and tools need to be installed just once, if you've Jupyter Notebook with C++, you can safely ignore this section. 17 | 18 | - Install Miniconda: [https://conda.io/miniconda.html](https://conda.io/miniconda.html) 19 | - open a terminal/shell and run the following commands 20 | - create a virual environment to keep C++ specific installtions seperate from base installation 21 | 22 | ```bash 23 | conda create -n cpp python=3.7 # create virtual env named cpp with Python3.7 support 24 | conda activate cpp #activate the virual environemnt 25 | conda install notebook 26 | conda install -c conda-forge xeus-cling 27 | conda install -c conda-forge jupyter_contrib_nbextensions 28 | conda install -c conda-forge jupyter_nbextensions_configurator 29 | jupyter nbextensions_configurator enable --user 30 | ``` 31 | 32 | ## Run notebooks 33 | 34 | - clone the repository locally once the tools are installed 35 | - open a terminal and cd into this cloned repo and run jupyter notebook 36 | 37 | 38 | ```bash 39 | cd 40 | jupyter notebook 41 | ``` 42 | 43 | - open 00-TableOfContents notebook or open individual chapters 44 | 45 | ## Stop Jupyter Notebook server 46 | 47 | - Enter ctrl+c to stop jupyter notebook from the terminal where its running from 48 | 49 | ```bash 50 | $ conda deactivate # to deactivate the virtual env and go back to base installation 51 | ``` 52 | -------------------------------------------------------------------------------- /Recursions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Recursions\n", 8 | "https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/RecIntro.html\n", 9 | "\n", 10 | "### Table of Contents\n", 11 | "- **[Introduction](#intro)**
\n", 12 | "- **[Writing Recursive Functions](#writing)**
" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "
" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "## Recursion Introduction\n", 27 | "- an algorithm (or a function in a computer program) is recursive if it invokes itself to do part of its work\n", 28 | "- the process of solving a large problem by reducing it to one or more sub-problems which are identical in structure to the original problem and somewhat simpler to solve\n", 29 | " - eventually sub-problems become so simple that they can be solved without further division\n", 30 | "- for a recursive approach to be successful, the recursive \"call to itself\" must be on a smaller problem than the one originally attempted\n", 31 | "- in general, recursive algorithm must have two parts:\n", 32 | " 1. **base case** - handles a simple input that has direct answer (stops recursion)\n", 33 | " - must have at least one or more base cases\n", 34 | " 2. **general case** - recursive part that contains one or more recursive calls to the algorithm\n", 35 | " - must have at least one or more general cases\n", 36 | " - each general case leads to one of the base cases\n", 37 | " \n", 38 | "## pros\n", 39 | "- makes it possible to solve complex problems with concise solutions that may directly map the recursive problem statement (Tower of Hanoii problem)\n", 40 | "- focus on base case and how to combine the sub-problems (process of delegating tasks)\n", 41 | "\n", 42 | "## cons\n", 43 | "- not intuitive to understand and may not have a counterpart in everyday problem solving\n", 44 | " - must adopt the attitude that sub-problems take care of themselves (taking a leap of faith)\n", 45 | "- typically less efficient compared to iterative counterparts\n", 46 | " - lots of function calls have computational and memory overhead\n", 47 | "- must be able to understand how to read and write recursive functions\n", 48 | "\n", 49 | "## Real-world example\n", 50 | "### example 1\n", 51 | "- a project manager divides a large project and delegates sub-tasks to many workers \n", 52 | " - s/he simply uses the reports from each worker to submit a final report of completion\n", 53 | " - assuming each sub-task is similar\n", 54 | " \n", 55 | "### example 2\n", 56 | "- Let's say you're in the last row of a movie theater and want to know the row number. How can you find out?" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "## Writing a recursive function\n", 64 | "- think of the smallest version of the problem and solve it and expand it to the larger\n", 65 | "- steps:\n", 66 | " 1. write a function header in a way that you can call it to solve the smallest problem\n", 67 | " - call the function with the smallest problem case\n", 68 | " - mark this as your base case in function implementation\n", 69 | " - expand the function header to solve a generic larger problem if necessary\n", 70 | " - add this as the general case \n", 71 | " - use the solution from the base case if necessary\n", 72 | "- example:\n", 73 | " \n", 74 | " ```cpp\n", 75 | " returnType functionName(inputData) {\n", 76 | " if (base case) {\n", 77 | " // answer directly found and return if necessary\n", 78 | " }\n", 79 | " else {\n", 80 | " // call functionName(smallerInputData)\n", 81 | " // use the result if functionName returns a value\n", 82 | " // return your final answer\n", 83 | " }\n", 84 | " }\n", 85 | "```" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "### Exercise 1\n", 93 | "- Write a recursive solution to a countdown problem (countdown to \"Happy New Year!\", \"Blast Off!\", etc.)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 1, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "#include \n", 103 | "using namespace std;" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 2, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "void countDown(int n) {\n", 113 | " // base case\n", 114 | " if (n == 0)\n", 115 | " cout << \"Blast Off!\" << endl;\n", 116 | " // general case\n", 117 | " else {\n", 118 | " cout << n << endl;\n", 119 | " countDown(n-1);\n", 120 | " }\n", 121 | "}" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 3, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stdout", 131 | "output_type": "stream", 132 | "text": [ 133 | "10\n", 134 | "9\n", 135 | "8\n", 136 | "7\n", 137 | "6\n", 138 | "5\n", 139 | "4\n", 140 | "3\n", 141 | "2\n", 142 | "1\n", 143 | "Blast Off!\n" 144 | ] 145 | } 146 | ], 147 | "source": [ 148 | "countDown(10);" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "### visualize it at pythontutor.com: https://goo.gl/LB3ET6\n", 156 | "### Compile and run demo-programs/recursions/countDown.cpp" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "### Exercise 2\n", 164 | "- Find sum of n elements stored in an array using recursive solution.\n", 165 | " - using loop would be easier, right?" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 1, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "// demonstrate it in the class from scratch\n", 175 | "#include \n", 176 | "using namespace std;" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": 2, 182 | "metadata": {}, 183 | "outputs": [], 184 | "source": [ 185 | "// sum of 1 number is that number\n", 186 | "// sum of n number is firstNumber + sum(remainingNumbers)\n", 187 | "// which one is base and which one is general?\n", 188 | "int sum(int nums[], int startIndex, int endIndex) {\n", 189 | " if (startIndex == endIndex)\n", 190 | " return nums[startIndex];\n", 191 | " else {\n", 192 | " int s = nums[startIndex] + sum(nums, startIndex + 1, endIndex);\n", 193 | " return s;\n", 194 | " }\n", 195 | "}" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 3, 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [ 204 | "int s = 0;\n", 205 | "int nums[] = {100};" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 4, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "int nums1[] = {10, 20, 30};" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 5, 220 | "metadata": {}, 221 | "outputs": [ 222 | { 223 | "name": "stdout", 224 | "output_type": "stream", 225 | "text": [ 226 | "sum = 60\n" 227 | ] 228 | } 229 | ], 230 | "source": [ 231 | "s = sum(nums1, 0, 2);\n", 232 | "cout << \"sum = \" << s << endl;" 233 | ] 234 | }, 235 | { 236 | "cell_type": "markdown", 237 | "metadata": {}, 238 | "source": [ 239 | "### Exercise 3\n", 240 | "- Find maximum/minimum value in an array of n elements using recursive solution\n", 241 | "- Practice it!!" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 6, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "int max(int nums[], int i, int j) {\n", 251 | " // FIMXE: base case\n", 252 | " // FIXME: general case\n", 253 | " return 0;\n", 254 | "}" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "### Exercise 4\n", 262 | "- Find a factorial of n (n!) using recursive solution\n", 263 | "- Definition:\n", 264 | " - 1! = 1\n", 265 | " - n! = n * (n-1)!" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 1, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [ 274 | "// solve exercise 4\n", 275 | "long fact(int n) {\n", 276 | " if (n == 1)\n", 277 | " return 1;\n", 278 | " else\n", 279 | " return n*fact(n-1);\n", 280 | "}" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "#### visualize it at pythontutor.com: https://goo.gl/qL17S8" 288 | ] 289 | }, 290 | { 291 | "cell_type": "markdown", 292 | "metadata": {}, 293 | "source": [ 294 | "### Exercise 5\n", 295 | "- Compute the Fibonacci sequence for a given number. The Fibonacci Sequence is the series of numbers: 1, 1, 2, 3, 5, 8, 13, 21, ...\n", 296 | "- Definition:\n", 297 | " - fib(1) = 1\n", 298 | " - fib(2) = 1\n", 299 | " - fib(n) = fin(n-1) + fib(n-2)" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 11, 305 | "metadata": {}, 306 | "outputs": [], 307 | "source": [ 308 | "// solve exercise 5\n", 309 | "int fib(int n) {\n", 310 | " if (n == 1) //base case\n", 311 | " return 1;\n", 312 | " else if (n == 2) // base case\n", 313 | " return 1;\n", 314 | " else //general case\n", 315 | " return fib(n-1) + fib(n-2);\n", 316 | "}" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 12, 322 | "metadata": {}, 323 | "outputs": [ 324 | { 325 | "name": "stdout", 326 | "output_type": "stream", 327 | "text": [ 328 | "fib(10) = 55\n" 329 | ] 330 | } 331 | ], 332 | "source": [ 333 | "cout << \"fib(10) = \" << fib(10) << endl;" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "### how many time is the fib() called for fib(10)?\n", 341 | "- visualize it with pythontutor.com for answer: https://goo.gl/a6RrDW\n", 342 | "\n", 343 | "### better way... using memoization technique\n", 344 | "https://en.wikipedia.org/wiki/Memoization\n", 345 | "- optimization technique where you save/remember/cache the previously calculated answer to avoid recalculating for the same input" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": 2, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "#include \n", 355 | "#include \n", 356 | "\n", 357 | "using namespace std;" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": 14, 363 | "metadata": {}, 364 | "outputs": [], 365 | "source": [ 366 | "unordered_map FibDict;\n", 367 | "int call = 0;" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": 15, 373 | "metadata": {}, 374 | "outputs": [], 375 | "source": [ 376 | "// solve exercise 5 using memoization technique\n", 377 | "// first run as it is and see how the value of call\n", 378 | "// then use memoization technique and run and see the value of call\n", 379 | "int fibMemoized(int n) {\n", 380 | " call += 1;\n", 381 | " if (n == 1) //base case\n", 382 | " return 1;\n", 383 | " else if (n == 2) // base case\n", 384 | " return 1;\n", 385 | " else {//general case \n", 386 | " // check if fib of n is already calculated\n", 387 | " //auto search = FibDict.find(n);\n", 388 | " //if (search != FibDict.end())\n", 389 | " // return search->second;\n", 390 | " int ans = fibMemoized(n-1) + fibMemoized(n-2);\n", 391 | " //FibDict[n] = ans;\n", 392 | " return ans;\n", 393 | " }\n", 394 | "}" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": 16, 400 | "metadata": {}, 401 | "outputs": [ 402 | { 403 | "name": "stdout", 404 | "output_type": "stream", 405 | "text": [ 406 | "fib(10) = 55\n", 407 | "total fibMemoized call = 109\n" 408 | ] 409 | } 410 | ], 411 | "source": [ 412 | "cout << \"fib(10) = \" << fibMemoized(10) << endl;\n", 413 | "cout << \"total fibMemoized call = \" << call << endl;" 414 | ] 415 | }, 416 | { 417 | "cell_type": "markdown", 418 | "metadata": {}, 419 | "source": [ 420 | "### Exercise 6\n", 421 | "- Use memoization technique to improve recursive factorial function.\n", 422 | "- Practice it!" 423 | ] 424 | }, 425 | { 426 | "cell_type": "markdown", 427 | "metadata": {}, 428 | "source": [ 429 | "### Exercise 7\n", 430 | "- Find greatest common divisor (gcd) of a given two integers using recursive solution.\n", 431 | "- Definition:\n", 432 | " - gcd(n, 0) = n\n", 433 | " - gcd(n, m) = gcd(m, n%m)\n", 434 | " \n", 435 | "- Solve it!" 436 | ] 437 | }, 438 | { 439 | "cell_type": "markdown", 440 | "metadata": {}, 441 | "source": [ 442 | "### Exercise 8\n", 443 | "- Print the steps needed to solve Tower of Hanoi puzzle: https://www.khanacademy.org/computing/computer-science/algorithms/towers-of-hanoi/a/towers-of-hanoi\n", 444 | "- recursive algorithm:\n", 445 | "- let's say disks are numbered from 1 to n (n is the largest)\n", 446 | " 1. move n-1 disks from peg A to peg B with the help of peg C\n", 447 | " 2. move disk n from peg A to peg C\n", 448 | " 3. move n-1 disks from peg B to peg C with the help of peg 1" 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": 3, 454 | "metadata": {}, 455 | "outputs": [], 456 | "source": [ 457 | "void moveDisks(int n, char from, char helper, char dest)\n", 458 | "{\n", 459 | " if (n >= 1)\n", 460 | " {\n", 461 | " moveDisks(n-1, from, dest, helper);\n", 462 | " cout << \"Move disk #\" << n << \" from peg \" << from << \" to peg \" << dest << endl;\n", 463 | " moveDisks(n-1, helper, from, dest);\n", 464 | " }\n", 465 | "}" 466 | ] 467 | }, 468 | { 469 | "cell_type": "code", 470 | "execution_count": 4, 471 | "metadata": {}, 472 | "outputs": [ 473 | { 474 | "name": "stdout", 475 | "output_type": "stream", 476 | "text": [ 477 | "Move disk #1 from peg A to peg B\n", 478 | "Move disk #2 from peg A to peg C\n", 479 | "Move disk #1 from peg B to peg C\n" 480 | ] 481 | } 482 | ], 483 | "source": [ 484 | "moveDisks(2, 'A', 'B', 'C');" 485 | ] 486 | }, 487 | { 488 | "cell_type": "markdown", 489 | "metadata": {}, 490 | "source": [ 491 | "### How long will it take to move 64 golden disks?\n", 492 | "- total moves $\\approx$ $2^{64} \\approx 1.8446744e+19$\n", 493 | "- if monks work 24/7 moving 1 disk/second non-stop and not making a single mistake\n", 494 | " - would take: $5,848,682,331$ ($> 5B$ centuries)\n", 495 | "- computer doing the same @ $1B$ moves/second would take about $500$ years!" 496 | ] 497 | }, 498 | { 499 | "cell_type": "markdown", 500 | "metadata": {}, 501 | "source": [ 502 | "### Exercise 9 - Cumulative Sum\n", 503 | "- Write a recursive solution to find and return the sum of the values from 1 to n.\n", 504 | "- test cases:\n", 505 | " - assert(sum(5) == 15);\n", 506 | " - assert(sum(3) == 6);" 507 | ] 508 | }, 509 | { 510 | "cell_type": "markdown", 511 | "metadata": {}, 512 | "source": [ 513 | "### Exercise 10 - Add Odd Values\n", 514 | "- Write a recursive solution to add and return the sum of the positive odd values from 1 to n given some positive integer n.\n", 515 | "- test cases:\n", 516 | " - assert(addOdd(1) == 1);\n", 517 | " - assert(addOdd(2) == 1);\n", 518 | " - assert(addOdd(3) == 4);\n", 519 | " - assert(addOdd(7) == 16);" 520 | ] 521 | }, 522 | { 523 | "cell_type": "markdown", 524 | "metadata": {}, 525 | "source": [ 526 | "### Exercise 11 - Sum of the Digits\n", 527 | "- Write a recursive solution to add and return the sum of the digits in a given non-negative integer.\n", 528 | "- test cases:\n", 529 | " - assert(sumOfDigits(1234) == 10);\n", 530 | " - assert(sumOfDigits(999) == 27);" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": {}, 536 | "source": [ 537 | "### Exercise 12 - Count Characters\n", 538 | "- Write a recursive solution to count the number of times a letter 'A' appears in given string str.\n", 539 | "- test cases:\n", 540 | " - assert(countChr(\"ctcowcAt\") == 1);\n", 541 | " - assert(countChr(\"AAbAt\") == 3);" 542 | ] 543 | }, 544 | { 545 | "cell_type": "code", 546 | "execution_count": null, 547 | "metadata": {}, 548 | "outputs": [], 549 | "source": [] 550 | } 551 | ], 552 | "metadata": { 553 | "kernelspec": { 554 | "display_name": "C++14", 555 | "language": "C++14", 556 | "name": "xeus-cling-cpp14" 557 | }, 558 | "language_info": { 559 | "codemirror_mode": "text/x-c++src", 560 | "file_extension": ".cpp", 561 | "mimetype": "text/x-c++src", 562 | "name": "c++", 563 | "version": "-std=c++14" 564 | } 565 | }, 566 | "nbformat": 4, 567 | "nbformat_minor": 2 568 | } 569 | -------------------------------------------------------------------------------- /SearchAlgorithms.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Search Algorithms\n", 8 | "\n", 9 | "## Table of Contents\n", 10 | "- **[Sequential Search](#linear)**
\n", 11 | "- **[Sequential Search Asymptotic Analysis](#linearanalysis)**
\n", 12 | "- **[Binary Search](#binary)**
\n", 13 | "- **[Binary Search Asymptotic Analysis](#binaryanalysis)**
\n", 14 | "- **[Sequential Search vs Binary Search Empirical Analysis](#empirical)**
\n" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## header includes required for this notebook" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "#include \n", 31 | "#include \n", 32 | "#include \n", 33 | "#include \n", 34 | "#include \n", 35 | "#include \n", 36 | "#include \n", 37 | "\n", 38 | "using namespace std;" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 2, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "// operator<< overloaded to print a vector\n", 48 | "template\n", 49 | "ostream& operator<<(ostream& out, const vector& v) {\n", 50 | " char comma[3] = {'\\0', ' ', '\\0'};\n", 51 | " out << '[';\n", 52 | " for (auto& e: v) {\n", 53 | " out << comma << e;\n", 54 | " comma[0] = ',';\n", 55 | " }\n", 56 | " out << \"]\";\n", 57 | " return out;\n", 58 | "}" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "## Sequential Search\n", 66 | "- find a key in a sequence container\n", 67 | "- input is unsorted vector\n", 68 | "- output is the index if key found, -1 if key not found\n", 69 | "- Algorithm:\n", 70 | " 1. start from the first index\n", 71 | " 2. if the key matches with the element at the index, return index\n", 72 | " 3. otherwise move to the next element (index)\n", 73 | " 4. repeat from step 2\n", 74 | " 5. if key doesn't match with any of the element, return -1" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 3, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "template\n", 84 | "int sequentialSearch(const vector & v, T key) {\n", 85 | " int index = 0;\n", 86 | " while (index < v.size()) {\n", 87 | " if (v[index] == key) // found our element; key comparison that controls the loop\n", 88 | " return index;\n", 89 | " else\n", 90 | " index ++;\n", 91 | " }\n", 92 | " return -1;\n", 93 | "}" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 4, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "void generateRandomNumbers(vector &rands, int count, int start, int end) {\n", 103 | " // fill the vectors with random numbers\n", 104 | " random_device rd;\n", 105 | " //https://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine\n", 106 | " // generates high quality random unsigned ints\n", 107 | " mt19937 mt(rd());\n", 108 | " uniform_int_distribution<> dis(start, end); // numbers between start and end inclusive\n", 109 | " generate(rands.begin(), rands.end(), bind(dis, ref(mt)));\n", 110 | "}" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 5, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "vector nums(20);" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 6, 125 | "metadata": {}, 126 | "outputs": [ 127 | { 128 | "name": "stdout", 129 | "output_type": "stream", 130 | "text": [ 131 | "[14, 0, 4, 6, 3, 1, 18, 3, 3, 5, 12, 18, 0, 11, 19, 16, 18, 15, 0, 4]\n" 132 | ] 133 | } 134 | ], 135 | "source": [ 136 | "generateRandomNumbers(nums, 20, 0, 20);\n", 137 | "cout << nums << endl;" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 7, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [ 146 | "int key;\n", 147 | "int searchIndex;" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 8, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "// generate a random number and search in nums vector...\n", 157 | "srand(time(NULL));\n", 158 | "key = rand()%20;" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 9, 164 | "metadata": {}, 165 | "outputs": [ 166 | { 167 | "name": "stdout", 168 | "output_type": "stream", 169 | "text": [ 170 | "0 found at index 1\n" 171 | ] 172 | } 173 | ], 174 | "source": [ 175 | "searchIndex = sequentialSearch(nums, key);\n", 176 | "if (searchIndex >= 0)\n", 177 | " cout << key << \" found at index \" << searchIndex << endl;\n", 178 | "else\n", 179 | " cout << key << \" not found!\" << endl;" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "## Sequential Search Asymptotic Analysis\n", 194 | "- look for key comparison/operation\n", 195 | "- Best case: $1$ comparison, $O(1)$\n", 196 | "- Average case: $n/2$ comparison, $O(n)$\n", 197 | "- Worst case: $n$ comparison, $O(n)$" 198 | ] 199 | }, 200 | { 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "## Binary Search\n", 212 | "- input is a sequence sorted in increasing order\n", 213 | "- imagine searching for a word in a dictionary or someone's name in a phone directory\n", 214 | "- uses divide and conquer technique\n", 215 | " - in each iteration, the search space is reduced by half\n", 216 | " - if key is found at the middle, return the index\n", 217 | " - repeat the search in lower or upper half of the sequence until sequence is exhausted\n", 218 | "- visualize binary search: https://opendsa-server.cs.vt.edu/ODSA/Books/CS3/html/AnalProgram.html" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 10, 224 | "metadata": {}, 225 | "outputs": [], 226 | "source": [ 227 | "template \n", 228 | "int binarySearch(const vector &v, T key) {\n", 229 | " int low = 0;\n", 230 | " int high = v.size()-1;\n", 231 | " while (low <= high) { // stop when low and high cross\n", 232 | " int mid = (low+high)/2; // check middle of sequence\n", 233 | " if (v[mid] == key) // found it\n", 234 | " return mid; // return the index\n", 235 | " else if (v[mid] > key) // check in left half\n", 236 | " high = mid - 1;\n", 237 | " else // check in right half\n", 238 | " low = mid + 1;\n", 239 | " }\n", 240 | " return -1;\n", 241 | "}" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 11, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "vector nums1(20);" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 12, 256 | "metadata": {}, 257 | "outputs": [ 258 | { 259 | "name": "stdout", 260 | "output_type": "stream", 261 | "text": [ 262 | "[1, 13, 13, 7, 18, 1, 3, 15, 17, 2, 18, 15, 7, 3, 3, 8, 6, 19, 1, 5]\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "generateRandomNumbers(nums1, 20, 0, 20);\n", 268 | "cout << nums1 << endl;" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 13, 274 | "metadata": {}, 275 | "outputs": [ 276 | { 277 | "name": "stdout", 278 | "output_type": "stream", 279 | "text": [ 280 | "[1, 1, 1, 2, 3, 3, 3, 5, 6, 7, 7, 8, 13, 13, 15, 15, 17, 18, 18, 19]\n" 281 | ] 282 | } 283 | ], 284 | "source": [ 285 | "// for binary search to work, sequence must be sorted\n", 286 | "sort(nums1.begin(), nums1.end());\n", 287 | "cout << nums1 << endl;" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": 14, 293 | "metadata": {}, 294 | "outputs": [ 295 | { 296 | "name": "stdout", 297 | "output_type": "stream", 298 | "text": [ 299 | " key to search = 8\n" 300 | ] 301 | } 302 | ], 303 | "source": [ 304 | "// generate a random number and search in nums1 vector...\n", 305 | "srand(time(NULL));\n", 306 | "key = rand()%20;\n", 307 | "cout << \" key to search = \" << key << endl;" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 15, 313 | "metadata": {}, 314 | "outputs": [ 315 | { 316 | "name": "stdout", 317 | "output_type": "stream", 318 | "text": [ 319 | "8 found at index 11\n" 320 | ] 321 | } 322 | ], 323 | "source": [ 324 | "searchIndex = binarySearch(nums1, key);\n", 325 | "if (searchIndex >= 0)\n", 326 | " cout << key << \" found at index \" << searchIndex << endl;\n", 327 | "else\n", 328 | " cout << key << \" not found!\" << endl;" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": {}, 341 | "source": [ 342 | "## Binary Search Asymptotic Analysis\n", 343 | "- Best case: $1$ comparison $O(1)$\n", 344 | "- Average and Worst cases: $(O(logn))$\n", 345 | "- binary search analysis visualization: https://opendsa-server.cs.vt.edu/ODSA/Books/CS3/html/AnalProgram.html\n", 346 | "- each loop of binarySearch cuts the size of the sequence (problem size) approximately in half and for each problem size, we do $O(1)$ comparison for a total of $\\sum_{i=0}^{log n}1$" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "### as $n$ grows, the $O(n)$ running time for sequential search in the average and worst cases quickly becomes much larger than the $O(log n)$ of binary search" 354 | ] 355 | }, 356 | { 357 | "cell_type": "markdown", 358 | "metadata": {}, 359 | "source": [ 360 | "" 361 | ] 362 | }, 363 | { 364 | "cell_type": "markdown", 365 | "metadata": {}, 366 | "source": [ 367 | "## Empirical Analysis: Linear Search Vs Binary Search" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": 16, 373 | "metadata": {}, 374 | "outputs": [], 375 | "source": [ 376 | "// function to time sequentialSearch and binarySearch\n", 377 | "double timeit(const vector &v, int key, int (*searchFunc)(const vector &, int)) {\n", 378 | " clock_t begin = clock();\n", 379 | " int i = (*searchFunc)(v, key);\n", 380 | " clock_t end = clock();\n", 381 | " double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;\n", 382 | " return elapsed_secs;\n", 383 | "}" 384 | ] 385 | }, 386 | { 387 | "cell_type": "code", 388 | "execution_count": 31, 389 | "metadata": {}, 390 | "outputs": [], 391 | "source": [ 392 | "void compareSearchAlgos(int N) {\n", 393 | " vector nums(N);\n", 394 | " generateRandomNumbers(nums, N, 0, N);\n", 395 | " // make a copy of nums\n", 396 | " vector sortedNums = nums;\n", 397 | " sort(sortedNums.begin(), sortedNums.end());\n", 398 | " // generate a random number and search in nums1 vector...\n", 399 | " srand(time(NULL));\n", 400 | " int key = rand()%N+1;\n", 401 | " cout << \"key to search = \" << key << endl;\n", 402 | " cout << \"Sequential Search time: \" << timeit(nums, key, sequentialSearch) << \" seconds.\" << endl;\n", 403 | " cout << \"Binary Search time: \" << timeit(sortedNums, key, binarySearch) << \" seconds.\" << endl;\n", 404 | "}" 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "metadata": {}, 410 | "source": [ 411 | "### Sequential and Binary Search Comparison with 100 K integers" 412 | ] 413 | }, 414 | { 415 | "cell_type": "code", 416 | "execution_count": 32, 417 | "metadata": {}, 418 | "outputs": [ 419 | { 420 | "name": "stdout", 421 | "output_type": "stream", 422 | "text": [ 423 | " key to search = 23182\n", 424 | "Sequential Search time: 0.002065\n", 425 | "Binary Search time: 1.8e-05\n" 426 | ] 427 | } 428 | ], 429 | "source": [ 430 | "compareSearchAlgos(100000);" 431 | ] 432 | }, 433 | { 434 | "cell_type": "markdown", 435 | "metadata": {}, 436 | "source": [ 437 | "### Sequential and Binary Search Comparison with 1 M integers" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": 33, 443 | "metadata": {}, 444 | "outputs": [ 445 | { 446 | "name": "stdout", 447 | "output_type": "stream", 448 | "text": [ 449 | " key to search = 251777\n", 450 | "Sequential Search time: 0.000768\n", 451 | "Binary Search time: 1.4e-05\n" 452 | ] 453 | } 454 | ], 455 | "source": [ 456 | "compareSearchAlgos(1000000);" 457 | ] 458 | }, 459 | { 460 | "cell_type": "markdown", 461 | "metadata": {}, 462 | "source": [ 463 | "### Sequential and Binary Search Comparison with 1 B integers" 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": 34, 469 | "metadata": {}, 470 | "outputs": [ 471 | { 472 | "name": "stdout", 473 | "output_type": "stream", 474 | "text": [ 475 | " key to search = 505016941\n", 476 | "Sequential Search time: 2.88439\n", 477 | "Binary Search time: 4e-05\n" 478 | ] 479 | } 480 | ], 481 | "source": [ 482 | "compareSearchAlgos(1000000000);\n", 483 | "/*\n", 484 | "// sorting took much longer!\n", 485 | "key to search = 505016941\n", 486 | "Sequential Search time: 2.88439 seconds\n", 487 | "Binary Search time: 4e-05 seconds\n", 488 | "*/" 489 | ] 490 | }, 491 | { 492 | "cell_type": "code", 493 | "execution_count": null, 494 | "metadata": {}, 495 | "outputs": [], 496 | "source": [] 497 | } 498 | ], 499 | "metadata": { 500 | "kernelspec": { 501 | "display_name": "C++14", 502 | "language": "C++14", 503 | "name": "xeus-cling-cpp14" 504 | }, 505 | "language_info": { 506 | "codemirror_mode": "text/x-c++src", 507 | "file_extension": ".cpp", 508 | "mimetype": "text/x-c++src", 509 | "name": "c++", 510 | "version": "-std=c++14" 511 | } 512 | }, 513 | "nbformat": 4, 514 | "nbformat_minor": 2 515 | } 516 | -------------------------------------------------------------------------------- /Stacks.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Stacks\n", 8 | "- https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/StackArray.html\n", 9 | "- https://en.cppreference.com/w/cpp/container/stack\n", 10 | "\n", 11 | "\n", 12 | "## Table of Contents\n", 13 | "- **[Introduction](#intro)**
\n", 14 | "- **[Array-based Stack](#stack)**
\n", 15 | "- **[Linked Stack](#linked)**
" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "## Introduction\n", 30 | "- stack is a list-like data structure in which elements may be inserted or removed from only one end\n", 31 | " - less flexible than list\n", 32 | " - more efficient and easy to implement\n", 33 | "- **LIFO** (Last-In, First-Out) data structure\n", 34 | "- many applications require the limited form of insert and remove operations that stacks provide\n", 35 | "- uses real-world analogy of stacks e.g., stacks of coins, books, boxes, plates, etc.\n", 36 | "\n", 37 | "\n", 38 | "### Applications\n", 39 | "- stack structure is used in memory management for local variables\n", 40 | "- used to evaluate prefix, postfix and infix expressions\n", 41 | "- can be used to convert expression in one form to anther\n", 42 | "- parse syntax in programming language to verify grammar\n", 43 | "- backtracking in solving games and puzzles\n", 44 | "- checking for valid parenthesis\n", 45 | "\n", 46 | "### Operations\n", 47 | "- push : insert element at the top of the stack\n", 48 | "- pop : remove and return element from the top of the stack" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "## Implementations of Stacks as ADT\n", 63 | "- Stacks can be implemented using array or linked-list\n", 64 | "\n", 65 | "### Array implementation of Stack\n", 66 | "- array-based stack is as simple as array-based list\n", 67 | "- below is the array-based stack\n", 68 | "\n", 69 | "### Visualization of Array-based Stack\n", 70 | "https://opendsa-server.cs.vt.edu/ODSA/Books/CS2/html/StackArray.html" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": null, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "#include \n", 80 | "#include \n", 81 | "\n", 82 | "using namespace std;" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "template\n", 92 | "class ArrayStack {\n", 93 | " private:\n", 94 | " size_t maxSize;\n", 95 | " size_t top;\n", 96 | " T * stack;\n", 97 | " public:\n", 98 | " ArrayStack(size_t mSize=100) { //constructor \n", 99 | " assert(mSize > 0);\n", 100 | " maxSize = mSize;\n", 101 | " stack = new T[maxSize];\n", 102 | " top = 0;\n", 103 | " }\n", 104 | " \n", 105 | " // clear the stack\n", 106 | " void clear() { top = 0; }\n", 107 | " \n", 108 | " // get the size of the stack\n", 109 | " size_t size() { return top; }\n", 110 | " \n", 111 | " // check if stack is empty\n", 112 | " bool empty() { return top == 0; };\n", 113 | " \n", 114 | " // check if stack is full\n", 115 | " bool full() { return top == maxSize; }\n", 116 | " \n", 117 | " // return the max size\n", 118 | " size_t max_size() { return maxSize; }\n", 119 | " \n", 120 | " //push data on the top of the stack\n", 121 | " void push(T value) {\n", 122 | " assert(!full());\n", 123 | " stack[top++] = value;\n", 124 | " }\n", 125 | " \n", 126 | " // remove and return the element from the top of the stack\n", 127 | " T pop() { \n", 128 | " assert(!empty());\n", 129 | " return stack[--top]; \n", 130 | " }\n", 131 | " // return the top element\n", 132 | " T get_top() {\n", 133 | " assert(!empty());\n", 134 | " return stack[top-1];\n", 135 | " }\n", 136 | "};" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## Test ArrayStack Implementation" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": null, 149 | "metadata": {}, 150 | "outputs": [], 151 | "source": [ 152 | "ArrayStack iStack;" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 4, 158 | "metadata": {}, 159 | "outputs": [ 160 | { 161 | "name": "stdout", 162 | "output_type": "stream", 163 | "text": [ 164 | "size of iStack = 3" 165 | ] 166 | } 167 | ], 168 | "source": [ 169 | "iStack.push(10);\n", 170 | "iStack.push(20);\n", 171 | "iStack.push(30);\n", 172 | "cout << \"size of iStack = \" << iStack.size();" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": 5, 178 | "metadata": {}, 179 | "outputs": [ 180 | { 181 | "name": "stdout", 182 | "output_type": "stream", 183 | "text": [ 184 | "top of the stack is: 30\n", 185 | "now the size = 2\n" 186 | ] 187 | } 188 | ], 189 | "source": [ 190 | "cout << \"top of the stack is: \" << iStack.pop() << endl;\n", 191 | "cout << \"now the size = \" << iStack.size() << endl;" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 6, 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "iStack.push(40);" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 7, 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "name": "stdout", 210 | "output_type": "stream", 211 | "text": [ 212 | "40\n", 213 | "20\n", 214 | "10\n" 215 | ] 216 | } 217 | ], 218 | "source": [ 219 | "while(!iStack.empty()) {\n", 220 | " cout << iStack.pop() << endl;\n", 221 | "}" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "## Linked Stack Implementation\n", 236 | "- elements are inserted and removed only from the head of the list\n", 237 | "- header node is not used because no special-cases need to be handled\n", 238 | "- below is linked stack implementation" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 1, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "#include \n", 248 | "#include \n", 249 | "\n", 250 | "using namespace std;" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 2, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "template\n", 260 | "struct Node {\n", 261 | " T data;\n", 262 | " Node * next;\n", 263 | "};" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": 3, 269 | "metadata": {}, 270 | "outputs": [], 271 | "source": [ 272 | "template\n", 273 | "class LinkedStack{\n", 274 | " private:\n", 275 | " size_t nodeCount;\n", 276 | " Node * head;\n", 277 | " public:\n", 278 | " //constructor\n", 279 | " LinkedStack() { \n", 280 | " nodeCount = 0; \n", 281 | " head = nullptr;\n", 282 | " }\n", 283 | " \n", 284 | " // clear the stack\n", 285 | " void clear() {\n", 286 | " nodeCount = 0;\n", 287 | " Node * curr = head;\n", 288 | " while ( curr != nullptr ) {\n", 289 | " head = head->next;\n", 290 | " delete curr;\n", 291 | " curr = head;\n", 292 | " }\n", 293 | " }\n", 294 | " \n", 295 | " // get the size of the stack\n", 296 | " size_t size() { return nodeCount; }\n", 297 | " \n", 298 | " // check if stack is empty\n", 299 | " bool empty() { return nodeCount == 0; };\n", 300 | " \n", 301 | " //push data on the top of the stack\n", 302 | " void push(T value) {\n", 303 | " Node * node = new Node;\n", 304 | " node->data = value;\n", 305 | " node->next = head;\n", 306 | " head = node;\n", 307 | " nodeCount++;\n", 308 | " }\n", 309 | " \n", 310 | " // remove and return element from top of the stack\n", 311 | " T pop() { \n", 312 | " assert(!empty());\n", 313 | " T data = head->data;\n", 314 | " // adjust head pointer and delete head node\n", 315 | " Node * curr = head;\n", 316 | " head = head->next;\n", 317 | " delete curr;\n", 318 | " nodeCount--;\n", 319 | " return data; \n", 320 | " }\n", 321 | " \n", 322 | " T top() {\n", 323 | " assert(!empty());\n", 324 | " return head->data;\n", 325 | " }\n", 326 | "};" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "## Test Linked Stack Implementation" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": 4, 339 | "metadata": {}, 340 | "outputs": [], 341 | "source": [ 342 | "LinkedStack lStack;" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": 5, 348 | "metadata": {}, 349 | "outputs": [ 350 | { 351 | "name": "stdout", 352 | "output_type": "stream", 353 | "text": [ 354 | "size of lStack = 3\n" 355 | ] 356 | } 357 | ], 358 | "source": [ 359 | "lStack.push(10);\n", 360 | "lStack.push(20);\n", 361 | "lStack.push(30);\n", 362 | "cout << \"size of lStack = \" << lStack.size() << endl;" 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": 6, 368 | "metadata": {}, 369 | "outputs": [ 370 | { 371 | "name": "stdout", 372 | "output_type": "stream", 373 | "text": [ 374 | "top element = 30\n", 375 | "now the size = 2\n" 376 | ] 377 | } 378 | ], 379 | "source": [ 380 | "cout << \"top element = \" << lStack.pop() << endl;\n", 381 | "cout << \"now the size = \" << lStack.size() << endl;" 382 | ] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "execution_count": 7, 387 | "metadata": {}, 388 | "outputs": [ 389 | { 390 | "name": "stdout", 391 | "output_type": "stream", 392 | "text": [ 393 | "is lStack empty? false" 394 | ] 395 | } 396 | ], 397 | "source": [ 398 | "cout << boolalpha;\n", 399 | "cout << \"is lStack empty? \" << lStack.empty();" 400 | ] 401 | }, 402 | { 403 | "cell_type": "code", 404 | "execution_count": 8, 405 | "metadata": {}, 406 | "outputs": [ 407 | { 408 | "name": "stdout", 409 | "output_type": "stream", 410 | "text": [ 411 | "20 10 " 412 | ] 413 | } 414 | ], 415 | "source": [ 416 | "while(!lStack.empty()) {\n", 417 | " cout << lStack.top() << \" \";\n", 418 | " lStack.pop();\n", 419 | "}" 420 | ] 421 | }, 422 | { 423 | "cell_type": "markdown", 424 | "metadata": {}, 425 | "source": [ 426 | "## Exercises\n", 427 | "1. Backspace problem: https://open.kattis.com/problems/backspace\n", 428 | "- Game of throwns: https://open.kattis.com/problems/throwns\n", 429 | "- Even Up Solitaire: https://open.kattis.com/problems/evenup\n", 430 | "- Working at the Restaurant: https://open.kattis.com/problems/restaurant\n", 431 | "- Pairing Socks: https://open.kattis.com/problems/pairingsocks\n", 432 | "- Find stack-based problems in Kattis: https://cpbook.net/methodstosolve search for stack" 433 | ] 434 | }, 435 | { 436 | "cell_type": "code", 437 | "execution_count": null, 438 | "metadata": {}, 439 | "outputs": [], 440 | "source": [] 441 | } 442 | ], 443 | "metadata": { 444 | "kernelspec": { 445 | "display_name": "C++14", 446 | "language": "C++14", 447 | "name": "xcpp14" 448 | }, 449 | "language_info": { 450 | "codemirror_mode": "text/x-c++src", 451 | "file_extension": ".cpp", 452 | "mimetype": "text/x-c++src", 453 | "name": "c++", 454 | "version": "14" 455 | } 456 | }, 457 | "nbformat": 4, 458 | "nbformat_minor": 2 459 | } 460 | -------------------------------------------------------------------------------- /StaticVariables.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Static Variables\n", 8 | "https://www.geeksforgeeks.org/static-variables-in-c/\n", 9 | "\n", 10 | "## Table of Contents\n", 11 | "- [Static variables](#static)\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Headers and helper functions\n", 19 | "- run include headers and helper function cells if Kernel crashes or is restarted" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 4, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "// headers required in this notebook demo codes\n", 29 | "#include \n", 30 | "#include \n", 31 | "\n", 32 | "using namespace std;" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "# Static variables\n", 47 | "- as opposed to auto variables, static variables' value \"stick\" or preserve even after they're out of their scope\n", 48 | "- once the static variables are initialized, they're not reinitialized in the subsequent calls\n", 49 | "- static variables if initialized are stored in data segment (see [Memory Segments](./MemorySegments.ipynb))\n", 50 | "- it static variables are not explictly initialized, they're 0 initialized and stored in BSS segment\n", 51 | "- syntax:\n", 52 | "```c++\n", 53 | " static type varName;\n", 54 | "```" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 2, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "void someFunction() {\n", 64 | " static int count = 0; // local scope; but store in BSS segment\n", 65 | " int num = 0;\n", 66 | " num++;\n", 67 | " count++;\n", 68 | " cout << \"num = \" << num << endl;\n", 69 | " cout << \"count = \" << count << endl;\n", 70 | "}" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 8, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "// can't access count from anywhere but from inside someFunction !\n", 80 | "//cout << count << endl;" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 3, 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "name": "stdout", 90 | "output_type": "stream", 91 | "text": [ 92 | "num = 1\n", 93 | "count = 1\n" 94 | ] 95 | } 96 | ], 97 | "source": [ 98 | "someFunction();" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "someFunction();" 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": {}, 113 | "source": [ 114 | "### visualize using pythontutor.com\n", 115 | "https://goo.gl/p3YVGP" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [] 124 | } 125 | ], 126 | "metadata": { 127 | "kernelspec": { 128 | "display_name": "C++14", 129 | "language": "C++14", 130 | "name": "xeus-cling-cpp14" 131 | }, 132 | "language_info": { 133 | "codemirror_mode": "text/x-c++src", 134 | "file_extension": ".cpp", 135 | "mimetype": "text/x-c++src", 136 | "name": "c++", 137 | "version": "-std=c++14" 138 | } 139 | }, 140 | "nbformat": 4, 141 | "nbformat_minor": 2 142 | } 143 | -------------------------------------------------------------------------------- /demo-programs/RectangleBasic/Rectangle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Rectangle.h" 4 | 5 | using namespace std; 6 | 7 | Rectangle::Rectangle() { // default constructor 8 | length = 0; 9 | width = 0; 10 | } 11 | //constructor with arguments 12 | Rectangle::Rectangle(int length, int width) { 13 | //this->length = length; 14 | //this->width = width; 15 | this->setLength(length); 16 | this->setWidth(width); 17 | } 18 | //destructor 19 | Rectangle::~Rectangle() { 20 | cout << "destructor called...!" << endl; 21 | } 22 | 23 | // member functions/methods 24 | int Rectangle::findArea() { 25 | int area = length * width; 26 | return area; 27 | } 28 | 29 | int Rectangle::findPrimeter() { 30 | return 2*(length + width); 31 | } 32 | 33 | void Rectangle::setLength(int length) { 34 | if (length < 0) 35 | length = 0; 36 | this->length = length; 37 | } 38 | 39 | void Rectangle::setWidth(int w) { 40 | //if (width <0 ) 41 | // w = 0; 42 | assert(w >= 0); 43 | width = w; 44 | } 45 | 46 | int Rectangle::getLength() { 47 | return length; 48 | } 49 | -------------------------------------------------------------------------------- /demo-programs/RectangleBasic/Rectangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Rectangle { 4 | // member variables 5 | private: 6 | int length; 7 | int width; 8 | public: 9 | // member functions/methods 10 | // finds area of rectange and returns it 11 | Rectangle(); 12 | Rectangle(int length, int width); 13 | ~Rectangle();//destructor 14 | int findArea(); 15 | int findPrimeter(); 16 | void setLength(int); 17 | void setWidth(int); 18 | int getLength(); 19 | }; -------------------------------------------------------------------------------- /demo-programs/RectangleBasic/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Rectangle.h" 4 | 5 | using namespace std; 6 | 7 | void test() { 8 | Rectangle r(20, 5); 9 | cout << "test area: " << r.findArea() << endl; 10 | cout << "test done" << endl; 11 | 12 | } 13 | 14 | int main() { 15 | Rectangle r2; 16 | Rectangle *r = new Rectangle(); // default constructor 17 | Rectangle *rPtr = &r2; 18 | //r.setLength(10); 19 | //r.setWidth(5); 20 | cout << "enter length and width separated by space: "; 21 | int length, width; 22 | cin >> length >> width; 23 | r->setLength(length); 24 | r->setWidth(width); 25 | cout << " length = " << r->getLength() << endl; 26 | cout << "area = " << r->findArea() << endl; 27 | cout << "perimter = " << r->findPrimeter() << endl; 28 | delete r; 29 | test(); 30 | cout << "done" << endl; 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /demo-programs/RectangleClass/Rectangle.cpp: -------------------------------------------------------------------------------- 1 | // operator overloading with non-member function 2 | #include 3 | 4 | using namespace std; 5 | 6 | // non-member function overload example 7 | class Rectangle { 8 | public: 9 | float length, width; 10 | // default and overloaded constructor 11 | Rectangle(float length=0, float width=0) { 12 | if (length < 0) 13 | length = 0; 14 | if (width == 0) 15 | width = 0; 16 | this->length = length; 17 | this->width = width; 18 | } 19 | 20 | float getArea() const { 21 | return this->length*this->width; 22 | } 23 | 24 | float getPerimeter() const { 25 | return 2*(this->length + this->width); 26 | } 27 | }; 28 | 29 | // overload + operator 30 | Rectangle operator+(const Rectangle& lhs, const Rectangle& rhs) { 31 | Rectangle temp; 32 | temp.length = lhs.length + rhs.length; 33 | temp.width = lhs.width + rhs.width; 34 | return temp; 35 | } 36 | 37 | void printRectangle(const Rectangle& r) { 38 | cout << "length = " << r.length << " width = " << r.width << '\n'; 39 | cout << "area = " << r.getArea() << " perimeter = " << r.getPerimeter() << '\n'; 40 | } 41 | 42 | //overload << operator 43 | ostream& operator<<(ostream &out, Rectangle r) { 44 | out << "[" << r.length << ", " << r.width << "]"; 45 | return out; 46 | } 47 | 48 | int main() { 49 | Rectangle r1 = {10, 5}; 50 | Rectangle r2 = {20, 10}; 51 | Rectangle r = r1 + r2; 52 | printRectangle(r); 53 | cout << r1 << " + " << r2 << " = " << r << '\n'; 54 | return 0; 55 | } -------------------------------------------------------------------------------- /demo-programs/RectangleClass/RectangleFriend.cpp: -------------------------------------------------------------------------------- 1 | // operator overloading with non-member friend functions 2 | #include 3 | 4 | using namespace std; 5 | 6 | // non-member function overload example 7 | class Rectangle { 8 | friend Rectangle operator+(const Rectangle& r1, const Rectangle& r2); 9 | friend void printRectangle(const Rectangle& r); 10 | friend ostream& operator<<(ostream &out, Rectangle r); 11 | private: 12 | float length, width; 13 | public: 14 | // default and overloaded constructor 15 | Rectangle(float length=0, float width=0) { 16 | if (length < 0) 17 | length = 0; 18 | if (width == 0) 19 | width = 0; 20 | this->length = length; 21 | this->width = width; 22 | }; 23 | 24 | float getArea() const { 25 | return this->length*this->width; 26 | } 27 | 28 | float getPerimeter() const { 29 | return 2*(this->length + this->width); 30 | } 31 | }; 32 | 33 | // overload + operator 34 | Rectangle operator+(const Rectangle& r1, const Rectangle& r2) { 35 | Rectangle temp; 36 | temp.length = r1.length + r2.length; 37 | temp.width = r1.width + r2.width; 38 | return temp; 39 | } 40 | 41 | void printRectangle(const Rectangle& r) { 42 | cout << "length = " << r.length << " width = " << r.width << '\n'; 43 | cout << "area = " << r.getArea() << " perimeter = " << r.getPerimeter() << '\n'; 44 | } 45 | 46 | //overload << operator 47 | ostream& operator<<(ostream &out, Rectangle r) { 48 | out << "{" << r.length << ", " << r.width << "}"; 49 | return out; 50 | } 51 | 52 | int main() { 53 | Rectangle r1 = {10, 5}; 54 | Rectangle r2 = {20, 10}; 55 | Rectangle r = r1 + r2; 56 | printRectangle(r); 57 | cout << r1 << " + " << r2 << " = " << r << '\n'; 58 | return 0; 59 | } -------------------------------------------------------------------------------- /demo-programs/RectangleClass/RectangleFriend1.cpp: -------------------------------------------------------------------------------- 1 | // Example 1 - Overloading as member function 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Rectangle { 7 | // cin >> and cout << operators can be overloaded only by 8 | // regular functions 9 | friend istream& operator>>(istream &, Rectangle &); 10 | friend ostream& operator<<(ostream &, Rectangle &); 11 | 12 | private: 13 | // member variables/attributes 14 | float length; 15 | float width; 16 | 17 | public: 18 | // member functions 19 | Rectangle(float length=0, float width=0) { 20 | this->setLength(length); 21 | this->setWidth(width); 22 | } 23 | 24 | float getArea() { 25 | return length*width; 26 | } 27 | 28 | float getPerimeter() { 29 | return 2*(length+width); 30 | } 31 | 32 | // getters 33 | float getLength() const { 34 | return length; 35 | } 36 | 37 | float getWidth() const { 38 | return width; 39 | } 40 | 41 | // setters 42 | void setLength(float length) { 43 | if (length < 0) 44 | length = 0; 45 | this->length = length; 46 | } 47 | 48 | void setWidth(float width) { 49 | if (width < 0) 50 | width = 0; 51 | this->width = width; 52 | } 53 | 54 | }; 55 | 56 | // overload >> (input extraction operator) 57 | istream& operator>>(istream &in, Rectangle &r) { 58 | in >> r.length >> r.width; 59 | return in; 60 | } 61 | 62 | // overload << (output insertion operator) 63 | ostream& operator<<(ostream &out, Rectangle &r) { 64 | out << "length = " << r.length << " width = " << r.width << endl; 65 | out << "area = " << r.getArea() << " perimeter = " << 66 | r.getPerimeter() << endl; 67 | return out; 68 | } 69 | 70 | int main() { 71 | Rectangle r; 72 | cout << "Enter length and width separated by space: "; 73 | cin >> r; 74 | cout << r; 75 | } -------------------------------------------------------------------------------- /demo-programs/RectangleClass/RectangleMember.cpp: -------------------------------------------------------------------------------- 1 | // overloading with member functions example 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Rectangle { 9 | friend ostream& operator<<(ostream &out, const Rectangle& r); 10 | friend istream& operator>>(istream &out, Rectangle& r); 11 | private: 12 | float length, width; 13 | public: 14 | // default and overloaded constructor 15 | Rectangle(float length=0, float width=0) { 16 | if (length < 0) 17 | length = 0; 18 | if (width == 0) 19 | width = 0; 20 | this->length = length; 21 | this->width = width; 22 | }; 23 | 24 | float getArea() const { 25 | return this->length*this->width; 26 | } 27 | 28 | float getPerimeter() const { 29 | return 2*(this->length + this->width); 30 | } 31 | 32 | // overload + operator 33 | Rectangle operator+(const Rectangle& rhs) { 34 | Rectangle temp; 35 | temp.length = this->length + rhs.length; 36 | temp.width = this->width + rhs.width; 37 | return temp; 38 | } 39 | 40 | // overload [] operator 41 | float operator[](size_t index) { 42 | if (index == 0) 43 | return this->length; 44 | else 45 | return this->width; 46 | } 47 | }; 48 | 49 | // overload << operator (only by non-member function) 50 | ostream& operator<<(ostream &out, const Rectangle& r) { 51 | out << '[' << r.length << ", " << r.width << ']'; 52 | return out; 53 | } 54 | 55 | // overload >> operator (only by non-member function) 56 | istream& operator>>(istream &in, Rectangle& r) { 57 | in >> r.length >> r.width; 58 | return in; 59 | } 60 | 61 | int main() { 62 | Rectangle r1 = {10, 5}; 63 | Rectangle r2 = {20, 10}; 64 | Rectangle r = r1 + r2; 65 | // same as 66 | // Rectangle r = operator+(r1, r2); 67 | cout << r1 << " + " << r2 << " = " << r << '\n'; 68 | cout << "length = " << r[0] << " width = " << r[1] << endl; 69 | // same as operator[](0) or operator[](1) 70 | cout << "Enter length and width of a rectangle separated by space: "; 71 | Rectangle r3; 72 | cin >> r3; 73 | cout << "Your rectangle's info: "; 74 | cout << r3 << endl; 75 | return 0; 76 | } 77 | 78 | /* Exercise 79 | 1. Overload subtraction (-) operator to subtract rhs (right hand side) rectangle from the lhs. 80 | 81 | */ -------------------------------------------------------------------------------- /demo-programs/classTemplates.cpp: -------------------------------------------------------------------------------- 1 | // Class Template Example 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | template 8 | class Rectangle { 9 | private: 10 | T length, width; 11 | public: 12 | // default and overloaded constructor 13 | Rectangle(T length=0, T width=0) { 14 | if (length < 0) 15 | length = 0; 16 | if (width < 0) 17 | width = 0; 18 | this->length = length; 19 | this->width = width; 20 | }; 21 | 22 | T getArea() const { 23 | return this->length*this->width; 24 | } 25 | 26 | T getPerimeter() const { 27 | return 2*(this->length + this->width); 28 | } 29 | 30 | // overload + operator 31 | Rectangle operator+(const Rectangle& other) { 32 | Rectangle temp; 33 | temp.length = this->length + other.length; 34 | temp.width = this->width + other.width; 35 | return temp; 36 | } 37 | 38 | // overload [] operator 39 | T operator[](size_t index) { 40 | if (index == 0) 41 | return this->length; 42 | else 43 | return this->width; 44 | } 45 | }; 46 | 47 | int main() { 48 | Rectangle r1(10.5, 5.6); 49 | Rectangle r2(10, 5); 50 | Rectangle R = r1 + r2; 51 | cout << "length = " << R[0] << " width = " << R[1] << endl; 52 | return 0; 53 | } -------------------------------------------------------------------------------- /demo-programs/exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void example1() { 8 | unsigned long long int n; 9 | int *nums; 10 | cout << "Enter how many integers would you like to store? "; 11 | cin >> n; 12 | nums = new int[n]; 13 | if (nums != NULL) 14 | cout << "successfully allocated memory to store " << n << " integers\n"; 15 | } 16 | 17 | void example2() { 18 | vector nums(10); 19 | try { 20 | nums.resize(1000000000000000000); 21 | } 22 | catch(const bad_alloc & e) { 23 | cout << "Exception occured: " << e.what() << endl; 24 | } 25 | cout << "size of nums = " << nums.size() << endl; 26 | } 27 | 28 | void example3() { 29 | int decimalNum; 30 | bool valid = false;; 31 | // User input with validation 32 | do 33 | { 34 | cout << "Enter a number in decimal: "; 35 | try 36 | { 37 | cin >> decimalNum; 38 | if (cin.fail()) 39 | { 40 | throw "Invalid input. Tray again!"; 41 | } 42 | valid = true; 43 | } 44 | catch (const char *error) 45 | { 46 | cin.clear(); // clear the cin failure state 47 | cin.ignore(100, '\n'); // ignore next 100 characters or up to \n char 48 | printf("%s\n", error); 49 | } 50 | } while (!valid); 51 | 52 | cout << "Thank you for entering a number: " << decimalNum << endl; 53 | } 54 | 55 | int main() { 56 | example1(); 57 | example2(); 58 | example3(); 59 | return 0; 60 | } -------------------------------------------------------------------------------- /demo-programs/memory_segments.cpp: -------------------------------------------------------------------------------- 1 | // Program that demonstrates various memory semgments 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int globalNum = 100; //Data segment 8 | static double globalStaticNum = 100.1; //data segment 9 | int globalNum1; //bss segment 10 | 11 | void myFunction() //code segment 12 | { 13 | int a = 10; //stack segment 14 | int nums[3] = {1, 2, 3}; //stack segment 15 | int *p = new int; // p is in stack but point to a address in heap segment 16 | cout << "\nLocal Variables in myFunction:" << endl; 17 | printf("\theap: value of pointer p= %u\n", p); 18 | printf("\tstack: address of a= %u\n", &a); 19 | printf("\tstack: base address of nums= %u\n", nums); 20 | printf("\tstack: address of pointer p= %u\n", &p); 21 | } 22 | 23 | int main() //code segment 24 | { 25 | int a =100; //stack segment 26 | int *p = new int; // Heap segment 27 | printf("Code segment: \n \taddress of main= %u\n", &main); 28 | printf("\taddress of myFunction= %u\n", &myFunction); 29 | printf("Data segment: \n\taddress of globalNum= %u\n", &globalNum); 30 | printf("\taddress of globalStaticNum= %u\n", &globalStaticNum); 31 | printf("bss segment: \n\taddress of globalNum1= %d\n", &globalNum1); 32 | cout << "\nLocal variabiles in main:" << endl; 33 | printf("\theap: value of pointer p= %u\n", p); 34 | printf("\tstack: address of a= %u\n", &a); 35 | printf("\tstack: address of pointer p= %u\n", &p); 36 | myFunction(); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /demo-programs/operator-overloading/ComplexNumber/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/demo-programs/operator-overloading/ComplexNumber/a.out -------------------------------------------------------------------------------- /demo-programs/operator-overloading/ComplexNumber/complex.cpp: -------------------------------------------------------------------------------- 1 | // Implementation of ComplexType class 2 | #include "complex.h" 3 | 4 | // Member functions implementations 5 | ComplexType::ComplexType(double real, double imag) 6 | { 7 | this->setComplex(real, imag); 8 | } 9 | 10 | void ComplexType::setComplex(double real, double imag) 11 | { 12 | this->realPart = real; 13 | this->imaginaryPart = imag; 14 | } 15 | 16 | // overload >> operator 17 | istream& operator>>(istream &is, ComplexType &c) 18 | { 19 | char ch; 20 | // parse complex number format (real, imaginary) 21 | is >> ch >> c.realPart >> ch >> c.imaginaryPart >> ch; 22 | return is; 23 | } 24 | 25 | // overload << operator 26 | ostream& operator<<(ostream &os, const ComplexType &c) 27 | { 28 | // print complex number format (real, imaginary) 29 | os << "(" << c.realPart << ", " << c.imaginaryPart << ")"; 30 | return os; 31 | } 32 | 33 | // overload + operator 34 | ComplexType operator+(const ComplexType &left, const ComplexType &right) 35 | { 36 | ComplexType temp; 37 | temp.realPart = left.realPart + right.realPart; 38 | temp.imaginaryPart = left.imaginaryPart + right.imaginaryPart; 39 | return temp; 40 | } 41 | 42 | // overload - operator 43 | ComplexType operator-(const ComplexType &left, const ComplexType &right) 44 | { 45 | ComplexType temp; 46 | temp.realPart = left.realPart - right.realPart; 47 | temp.imaginaryPart = left.imaginaryPart - right.imaginaryPart; 48 | return temp; 49 | } 50 | 51 | // overload * operator 52 | ComplexType operator*(const ComplexType &left, const ComplexType &right) 53 | { 54 | //(a, b) * (c, d) = (ac-bd, ad+bc) 55 | ComplexType temp; 56 | double ac = left.realPart * right.realPart; 57 | double bd = left.imaginaryPart * right.imaginaryPart; 58 | temp.realPart = ac - bd; 59 | temp.imaginaryPart = (left.realPart*right.imaginaryPart) + (left.imaginaryPart*right.realPart); 60 | return temp; 61 | } 62 | 63 | // overload == operator 64 | bool operator==(const ComplexType &left, const ComplexType &right) 65 | { 66 | return (left.realPart == right.realPart && left.imaginaryPart == right.imaginaryPart); 67 | } 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /demo-programs/operator-overloading/ComplexNumber/complex.h: -------------------------------------------------------------------------------- 1 | /* 2 | A number of the form a + bi, in which i^2 = -1 and a and b are real numbers, 3 | is called a complex number. We call `a` the real part and `b` the imaginary part of a + bi. 4 | Complex numbers can also be represented as ordered pairs (a, b). 5 | Some mathematical operations on complex numbers are defined by the following rules: 6 | (a, b) + (c, d) = (a+c, b+d) 7 | (a, b) - (c, d) = (a-c, b-d) 8 | (a, b) * (c, d) = (ac-bd, ad+bc) 9 | 10 | As C++ doesn't have a built-in type to manipulate complex numbers, let's define complex type 11 | using class to work with complex numbers. 12 | By overloading operators +, *, >>, <<, etc., we can provide aggregate operations on complex numbers 13 | such as x + y and x*y where x and y are complex numbers. 14 | */ 15 | #pragma once 16 | 17 | #include 18 | using namespace std; 19 | 20 | class ComplexType 21 | { 22 | // overload >> operator 23 | friend istream& operator>>(istream &, ComplexType &); 24 | // overload << operator 25 | friend ostream& operator<<(ostream &, const ComplexType &); 26 | // overload + operator 27 | friend ComplexType operator+(const ComplexType &, const ComplexType &); 28 | // overload - operator 29 | friend ComplexType operator-(const ComplexType &, const ComplexType &); 30 | // overload * operator 31 | friend ComplexType operator*(const ComplexType &, const ComplexType &); 32 | // overload = operator 33 | friend bool operator==(const ComplexType &, const ComplexType &); 34 | private: 35 | double realPart; 36 | double imaginaryPart; 37 | public: 38 | ComplexType(double real=0, double imag=0); 39 | // Constructor 40 | // Initializes the complex number according to the parameters 41 | // Postcondition: realPart = real; imaginaryPart = imag; 42 | 43 | void setComplex(double real, double imag); 44 | // Method to set the complex numbers according to the parameters 45 | // Postcondition: realPart =real; imaginaryPart = imag 46 | 47 | }; -------------------------------------------------------------------------------- /demo-programs/operator-overloading/ComplexNumber/main.cpp: -------------------------------------------------------------------------------- 1 | // driver program to test CompleNumber class 2 | #include 3 | #include 4 | #include "complex.h" 5 | 6 | using namespace std; 7 | 8 | void test() { 9 | ComplexType c1(2, 3); 10 | ComplexType c2(5, 4); 11 | ComplexType c3 = c1+c2; 12 | ComplexType ans(7, 7); 13 | assert (c3 == ans ); 14 | cout << "test cases passed...\n"; 15 | } 16 | 17 | int main(int argc, char* argv[]) { 18 | ComplexType c1(2, 3); 19 | ComplexType c2(5, 4); 20 | ComplexType c = c1 + c2; 21 | cout << c1 << " + " << c2 << " = " << c << endl; 22 | ComplexType c4; 23 | ComplexType c5; 24 | cout << "Enter complex number in the form (real, imaginary): "; 25 | cin >> c4; 26 | cout << "Enter another complex number in the form (real, imaginary): "; 27 | cin >> c5; 28 | cout << c4 << " + " << c5 << " = " << c4+c5 << endl; 29 | cout << c4 << " * " << c5 << " = " << c4*c5 << endl; 30 | test(); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /demo-programs/operator-overloading/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/demo-programs/operator-overloading/a.out -------------------------------------------------------------------------------- /demo-programs/recursions/countDown.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | using namespace std; 10 | 11 | void msleep(int milliseconds) 12 | { 13 | #ifdef _WIN32 14 | Sleep(milliseconds); 15 | #else 16 | usleep(static_cast(milliseconds)*1000); //or use nanosleep on platforms where it's needed 17 | #endif 18 | } 19 | 20 | #ifdef _WIN32 21 | #define sysclear() system("cls") 22 | #else 23 | #define sysclear() system("clear") 24 | #endif 25 | 26 | 27 | void countDown(int n) { 28 | // base case 29 | if (n == 0) { 30 | sysclear(); 31 | cout << "#$%#$25354W#$@^%34ADF5436%^#%&@#$#@%$&23$" << endl; 32 | cout << "Blast Off..." << endl; 33 | } 34 | // general case 35 | else { 36 | sysclear(); 37 | cout << n << endl; 38 | msleep(1000); 39 | countDown(n-1); 40 | //.... 41 | } 42 | } 43 | 44 | int main() { 45 | countDown(10); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /pdfs/00-Introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/00-Introduction.pdf -------------------------------------------------------------------------------- /pdfs/ArrayList.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/ArrayList.pdf -------------------------------------------------------------------------------- /pdfs/CS1-Review.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/CS1-Review.pdf -------------------------------------------------------------------------------- /pdfs/Class-OperatorOverloading.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Class-OperatorOverloading.pdf -------------------------------------------------------------------------------- /pdfs/ClassTemplates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/ClassTemplates.pdf -------------------------------------------------------------------------------- /pdfs/DoublyLinkedLists.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/DoublyLinkedLists.pdf -------------------------------------------------------------------------------- /pdfs/Exceptions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Exceptions.pdf -------------------------------------------------------------------------------- /pdfs/FunctionTemplates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/FunctionTemplates.pdf -------------------------------------------------------------------------------- /pdfs/LinkedLists.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/LinkedLists.pdf -------------------------------------------------------------------------------- /pdfs/MemorySegments.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/MemorySegments.pdf -------------------------------------------------------------------------------- /pdfs/OOP-Intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/OOP-Intro.pdf -------------------------------------------------------------------------------- /pdfs/Pointers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Pointers.pdf -------------------------------------------------------------------------------- /pdfs/Queues.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Queues.pdf -------------------------------------------------------------------------------- /pdfs/Recursions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Recursions.pdf -------------------------------------------------------------------------------- /pdfs/SearchAlgorithms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/SearchAlgorithms.pdf -------------------------------------------------------------------------------- /pdfs/Stacks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Stacks.pdf -------------------------------------------------------------------------------- /pdfs/StaticVariables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/StaticVariables.pdf -------------------------------------------------------------------------------- /pdfs/Struct.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/pdfs/Struct.pdf -------------------------------------------------------------------------------- /resources/DataRecords.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/DataRecords.png -------------------------------------------------------------------------------- /resources/DoublyLinkedList1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/DoublyLinkedList1.png -------------------------------------------------------------------------------- /resources/MemorySegments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/MemorySegments.png -------------------------------------------------------------------------------- /resources/OOPCM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/OOPCM.png -------------------------------------------------------------------------------- /resources/betterLinkedList1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/betterLinkedList1.png -------------------------------------------------------------------------------- /resources/betterLinkedList2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/betterLinkedList2.png -------------------------------------------------------------------------------- /resources/growthRates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/growthRates.png -------------------------------------------------------------------------------- /resources/growthRatesZoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/growthRatesZoom.png -------------------------------------------------------------------------------- /resources/growthrates.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/growthrates.gif -------------------------------------------------------------------------------- /resources/linkedlist1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/linkedlist1.png -------------------------------------------------------------------------------- /resources/linkedlist2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/linkedlist2.png -------------------------------------------------------------------------------- /resources/pointers-in-c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/pointers-in-c.jpg -------------------------------------------------------------------------------- /resources/queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/queue.png -------------------------------------------------------------------------------- /resources/seqSearchBestWorstAvg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/seqSearchBestWorstAvg.png -------------------------------------------------------------------------------- /resources/stacks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rambasnet/Data-Structures/1e523b682390365615b83c91e23456fb00cb6f3b/resources/stacks.png --------------------------------------------------------------------------------