35,99 €
Increase your productivity by implementing complex data structures and algorithms using JavaScript
Data structures and algorithms are the fundamental building blocks of computer programming. They are critical to any problem, provide a complete solution, and act like reusable code. Using appropriate data structures and having a good understanding of algorithm analysis are key in JavaScript to solving crises and ensuring your application is less prone to errors.
Do you want to build applications that are high-performing and fast? Are you looking for complete solutions to implement complex data structures and algorithms in a practical way? If either of these questions rings a bell, then this book is for you!
You'll start by building stacks and understanding performance and memory implications. You will learn how to pick the right type of queue for the application. You will then use sets, maps, trees, and graphs to simplify complex applications. You will learn to implement different types of sorting algorithm before gradually calculating and analyzing space and time complexity. Finally, you'll increase the performance of your application using micro optimizations and memory management.
By the end of the book you will have gained the skills and expertise necessary to create and employ various data structures in a way that is demanded by your project or use case.
If you are a JavaScript developer looking for practical examples to implement data structures and algorithms in your web applications, then this book is for you. Familiarity with data structures and algorithms will be helpful to get the most out of this book.
Kashyap Mukkamala has been a JavaScript enthusiast since he first started working with it back in 2011. Apart from his fun side projects using IoT devices (Arduino, LeapMotion, AR Drones) and mobile applications (PhoneGap, Ionic, NativeScript) his corporate experience has been focused around building scalable web SPAs for Fortune 100 companies. Over the past few years, Kashyap has also been a JavaScript instructor for his company and has trained a few hundred students.Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 349
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Kunal ChaudhariAcquisition Editor: Larissa PintoContent Development Editor: Arun NadarTechnical Editor: Leena PatilCopy Editor: Dhanya BaburajProject Coordinator: Sheejal ShahProofreader: Safis EditingIndexers: Aishwarya GangawaneGraphics: Jason MonteiroProduction Coordinator: Deepika Naik
First published: January 2018
Production reference: 1250118
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78839-855-8
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Kashyap Mukkamala has been a JavaScript enthusiast since he first started working with it back in 2011. Apart from his fun side projects using IoT devices (Arduino, LeapMotion, and AR Drones) and mobile applications (PhoneGap, Ionic, and NativeScript), his corporate experience has been focused around building scalable web SPAs for Fortune 100 companies. Over the past few years, Kashyap has also been a JavaScript instructor for his company and has trained a few hundred students.
Todd Zebert is a full stack web developer, currently at Miles. He has been a technical reviewer for a number of books and videos, is a frequent presenter at conferences on JavaScript, Drupal, and related technologies, and has a technology blog on Medium. Todd has a diverse background in technology including infrastructure, network engineering, PM, and IT leadership. He started in web development with the original Mosaic browser. Todd is an entrepreneur and part of the LA startup community. He's a believer in volunteering, open source, Maker/STEM/STEAM, and contributing back.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Building Stacks for Application State Management
Prerequisites
Terminology
API
Don't we have arrays for this?
Creating a stack
Implementing stack methods
Testing the stack
Using the stack
Use cases
Creating an Angular application
Installing Angular CLI
Creating an app using the CLI
Creating a stack
Creating a custom back button for a web application
Setting up the application and its routing
Detecting application state changes
Laying out the UI
Navigating between states
Final application logic
Building part of a basic JavaScript syntax parser and evaluator
Building a basic web worker
Laying out the UI
Basic web worker communication
Enabling web worker communications
Transforming input to machine-understandable expression
Converting infix to postfix expressions
Evaluating postfix expressions
Summary
Creating Queues for In-Order Executions
Types of queue
Implementing APIs
Creating a queue
A simple queue
Testing the queue
Priority Queue
Testing a priority queue
Use cases for queues
Creating a Node.js application
Starting the Node.js server
Creating a chat endpoint
Implementing logging using priority queues
Comparing performance
Running benchmark tests
Summary
Using Sets and Maps for Faster Applications
Exploring the origin of sets and maps
Analyzing set and map types
How weak is WeakMap?
Memory management
API differences
Sets versus WeakSets
Understanding WeakSets
The API difference
Use cases
Creating an Angular application
Creating custom keyboard shortcuts for your application
Creating an Angular application
Creating states with keymap
Activity tracking and analytics for web applications
Creating the Angular application
Performance comparison
Sets and Arrays
Maps and Objects
Summary
Using Trees for Faster Lookup and Modifications
Creating an Angular application
Creating a typeahead lookup
Creating a trie tree
Implementing the add() method
The friends' example
Implementing the search() method
Retaining remainders at nodes
The final form
Creating a credit card approval predictor
ID3 algorithm
Calculating target entropy
Calculating branch entropy
The final information gain per branch
Coding the ID3 algorithm
Generating training dataset
Generating the decision tree
Predicting outcome of sample inputs
Visualization of the tree and output
Summary
Simplify Complex Applications Using Graphs
Types of graphs
Use cases
Creating a Node.js web server
Creating a reference generator for a job portal
Creating a bidirectional graph
Generating a pseudocode for the shortest path generation
Implementing the shortest path generation
Creating a web server
Running the reference generator
Creating a friend recommendation system for social media
Understanding PageRank algorithm
Understanding Personalized PageRank (PPR) Algorithm
Pseudocode for personalized PageRank
Creating a web server
Implementing Personalized PageRank
Results and analysis
Summary
Exploring Types of Algorithms
Creating a Node.js application
Use cases
Using recursion to serialize data
Pseudocode
Serializing data
Using Dijkstra to determine the shortest path
Pseudo code
Implementing Dijkstra's algorithm
Using BFS to determine relationships
Pseudo code
Implementing BFS
Using dynamic programming to build a financial planner
Pseudo code
Implementing the dynamic programming algorithm
Using a greedy algorithm to build a travel itinerary
Understanding spanning trees
Pseudo code
Implementing a minimum spanning tree using a greedy algorithm
Using branch and bound algorithm to create a custom shopping list
Understanding branch and bound algorithm
Implementing branch and bound algorithm
When not to use brute-force algorithm
Brute-force Fibonacci generator
Recursive Fibonacci generator
Memoized Fibonacci generator
Summary
Sorting and Its Applications
Types of sorting algorithms
Use cases of different sorting algorithms
Creating an Express server
Mocking library books data
Insertionsort API
What is Insertionsort
Pseudo code
Implementing Insertionsort API
Mergesort API
What is Mergesort
Pseudo code
Implementing Mergesort API
Quicksort API
What is Quicksort
Pseudo code
Implementing the Quicksort API
Lomuto Partition Scheme
Hoare Partition Scheme
Performance comparison
Summary
Big O Notation, Space, and Time Complexity
Terminology
Asymptotic Notations
Big-O notation
Omega notation
Theta Notation
Recap
Examples of time complexity
Constant time
Logarithmic time
Linear time
Quadratic time
Polynomial time
Polynomial time complexity classes
Recursion and additive complexity
Space complexity and Auxiliary space
Examples of Space complexity
Constant space
Linear space
Summary
Micro-Optimizations and Memory Management
Best practices
Best practices for HTML
Declaring the correct DOCTYPE
Adding the correct meta-information to the page
Dropping unnecessary attributes
Making your app mobile ready
Loading style sheets in the <head>
Avoiding inline styles
Using semantic markup
Using Accessible Rich Internet Applications (ARIA) attributes
Loading scripts at the end
CSS best practices
Avoiding inline styles
Do not use !important
Arranging styles within a class alphabetically
Defining the media queries in an ascending order
Best practices for JavaScript
Avoiding polluting the global scope
Using 'use strict'
Strict checking (== vs ===)
Using ternary operators and Boolean || or &&
Modularization of code
Avoiding pyramid of doom
Keeping DOM access to a minimum
Validating all data
Do not reinvent the wheel
HTML optimizations
DOM structuring
Prefetching and preloading resources
<link rel=prefetch >
<link rel=preload >
Layout and layering of HTML
The HTML layout
HTML layers
CSS optimizations
Coding practices
Using smaller values for common ENUM
Using shorthand properties
Avoiding complex CSS selectors
Understanding the browser
Avoiding repaint and reflow
Critical rendering path (CRP)
JavaScript optimizations
Truthy/falsy comparisons
Looping optimizations
The conditional function call
Image and font optimizations
Garbage collection in JavaScript
Mark and sweep algorithm
Garbage collection and V8
Avoiding memory leaks
Assigning variables to global scope
Removing DOM elements and references
Closures edge case
Summary
What's next?
Other Books You May Enjoy
Leave a review - let other readers know what you think
The main focus of this book is employing data structures and algorithms in real-world web applications using JavaScript.
With JavaScript making its way onto the server side and with Single Page Application (SPA) frameworks taking over the client side, a lot, if not all, of the business logic, is being ported over to the client side. This makes it crucial to employ hand-crafted data structures and algorithms that are tailor-made for a given use case.
For example, when working on data visualizations such as charts, graphs, and 3D or 4D models, there might be tens or even hundreds of thousands of complex objects being served from the server, sometimes in near real time. There are more ways than one in which this data can be handled and that is what we will be exploring, with real-world examples.
This book is for anyone who has an interest in and basic knowledge of HTML, CSS, and JavaScript. We will also be using Node.js, Express, and Angular to create some of the web apps and APIs that leverage our data structures.
Chapter 1, Building Stacks for Application State Management, introduces building and using stacks for things such as a custom back button for an application and a syntax parser and evaluator for an online IDE.
Chapter 2, Creating Queues for In-Order Executions, demonstrates using queues and their variants to create a messaging service capable of handling message failures. Then, we perform a quick comparison of the different types of queues.
Chapter 3, Using Sets and Maps for Faster Applications, use sets, and maps to create keyboard shortcuts to navigate between your application states. Then, we create a custom application tracker for recording the analytics information of a web application. We conclude the chapter with a performance comparison of sets and maps with arrays and objects.
Chapter 4, Using Trees for Faster Lookup and Modifications, leverages tree data structures to form a typeahead component. Then, we create a credit card approval predictor to determine whether or not a credit card application would be accepted based on historical data.
Chapter 5, Simplify Complex Applications Using Graphs, discusses graphs with examples such as creating a reference generator for a job portal and a friend recommendation system on a social media website.
Chapter 6, Exploring Types of Algorithms, explores some of the most important algorithms, such as Dijkstra's, knapsack 1/0, greedy algorithms, and so on.
Chapter 7, Sorting and its Applications, explores merge sort, insertion sort, and quick sort with examples. Then, we run a performance comparison on them.
Chapter 8, Big O notation, Space, and Time Complexity, discusses the notations denoting complexities and then, moves on to discuss what space and time complexities are and how they impact our application.
Chapter 9, Micro-optimizations and Memory Management, explores the best practices for HTML, CSS, JavaScript and then, moves on to discuss some of the internal workings of Google Chrome and how we can leverage it to render our applications better and more quickly.
Basic knowledge of JavaScript, HTML, and CSS
Have Node.js installed (
https://nodejs.org/en/download/
)
Install WebStorm IDE (
https://www.jetbrains.com/webstorm/download
) or similar
A next-generation browser such as Google Chrome (
https://www.google.com/chrome/browser/desktop/
)
Familiarity with Angular 2.0 or greater is a plus but is not required
The screenshots in this book are taken on a macOS. There would be little difference (if any) for users of any other OS. The code samples, however, would run without any discrepancies irrespective of the OS. Anywhere we have
CMD/cmd/command
specified, please use
CTRL/ctrl/control
key on the windows counterpart. If you see
return
, please use
Enter
and if you see the term
terminal/Terminal
please use its equivalent
command prompt
on windows.
In this book, the code base is built incrementally as the topic progresses. So, when you compare the beginning of a code sample with the code base in GitHub, be aware that the GitHub code is the final form of the topic or the example that you are referring to.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Practical-JavaScript-Data-Structures-and-Algorithms. We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here:https://www.packtpub.com/sites/default/files/downloads/HandsOnDataStructuresandAlgorithmswithJavaScript_ColorImages.pdf.
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
Stacks are one of the most common data structures that one can think of. They are ubiquitous in both personal and professional setups. Stacks are a last in first out (LIFO) data structure, that provides some common operations, such as push, pop, peek, clear, and size.
In most object-oriented programming (OOP) languages, you would find the stack data structure built-in. JavaScript, on the other hand, was originally designed for the web; it does not have stacks baked into it, yet. However, don't let that stop you. Creating a stacks using JS is fairly easy, and this is further simplified by the use of the latest version of JavaScript.
In this chapter, our goal is to understand the importance of stack in the new-age web and their role in simplifying ever-evolving applications. Let's explore the following aspects of the stack:
A theoretical understanding of the stack
Its API and implementation
Use cases in real-world web
Before we start building a stack, let's take a look at some of the methods that we want our stack to have so that the behavior matches our requirements. Having to create the API on our own is a blessing in disguise. You never have to rely on someone else's library getting it right or even worry about any missing functionality. You can add what you need and not worry about performance and memory management until you need to.
The following are the requirements for the following chapter:
A basic understanding of JavaScript
A computer with Node.js installed (downloadable from
https://nodejs.org/en/download/
)
The code sample for the code shown in this chapter can be found at https://github.com/NgSculptor/examples.
Throughout the chapter, we will use the following terminology specific to Stacks, so let's get to know more about it:
Top
: Indicates the top of the stack
Base
: Indicates the bottom of the stack
This is the tricky part, as it is very hard to predict ahead of time what kinds of method your application will require. Therefore, it's usually a good idea to start off with whatever is the norm and then make changes as your applications demand. Going by that, you would end up with an API that looks something like this:
Push
: Pushes an item to the top of the stack
Pop
: Removes an item from the top of the stack
Peek
: Shows the last item pushed into the stack
Clear
: Empties the stack
Size
: Gets the current size of the stack
From what we have seen so far, you might wonder why one would need a stack in the first place. It's very similar to an array, and we can perform all of these operations on an array. Then, what is the real purpose of having a stack?
The reasons for preferring a stack over an array are multifold:
Using stacks
gives a more semantic meaning to your application. Consider this analogy where you have a backpack (an array) and wallet (a stack). Can you put money in both the backpack and wallet? Most certainly; however, when you look at a
backpack,
you have no clue as to what you may find inside it, but when you look at a wallet, you have a very good idea that it contains money. What kind of money it holds (that is, the data type), such as Dollars, INR, and Pounds, is, however, still not known (supported, unless you take support from TypeScript).
Native array operations have varying time complexities. Let's take
Array.prototype.splice
and
Array.prototype.push
,
for example. Splice has a worst-case time complexity of O(n), as it has to search through all the index and readjust it when an element is spliced
out of the array.
Push
has a worst case complexity of O(n) when the memory buffer is full but is amortized O(1). Stacks avoid elements being accessed directly and internally rely on a
WeakMap()
, which is memory efficient as you will see shortly.
Now that we know when and why we would want to use a stack, let's move on to implementing one. As discussed in the preceding section, we will use a WeakMap() for our implementation. You can use any native data type for your implementation, but there are certain reasons why WeakMap() would be a strong contender. WeakMap() retains a weak reference to the keys that it holds. This means that once you are no longer referring to that particular key, it gets garbage-collected along with the value. However, WeakMap() come with its own downsides: keys can only be nonprimitives and are not enumerable, that is, you cannot get a list of all the keys, as they are dependent on the garbage collector. However, in our case, we are more concerned with the values that our WeakMap() holds rather than keys and their internal memory management.
Now that we have implemented a Stack class, let's take a look at how we can employ this in some web development challenges.
To explore some practical applications of the stack in web development, we will create an Angular application first and use it as a base application, which we will use for subsequent use cases.
Starting off with the latest version of Angular is pretty straightforward. All you need as a prerequisite is to have Node.js preinstalled in your system. To test whether you have Node.js installed on your machine, go to the Terminal on the Mac or the command prompt on Windows and type the following command:
node -v
That should show you the version of Node.js that is installed. If you have something like the following:
node: command not found
This means that you do not have Node.js installed on your machine.
Once you have Node.js set up on your machine, you get access to npm, also known as the node package manager command-line tool, which can be used to set up global dependencies. Using the npm command, we will install the Angular CLI tool, which provides us with many Angular utility methods, including—but not limited to—creating a new project.
To install the Angular CLI in your Terminal, run the following command:
npm install -g @angular/cli
That should install the Angular CLI globally and give you access to the ng command to create new projects.
To test it, you can run the following command, which should show you a list of features available for use:
ng
Now, let's create the Angular application. We will create a new application for each example for the sake of clarity. You can club them into the same application if you feel comfortable. To create an Angular application using the CLI, run the following command in the Terminal:
ng new <project-name>
Replace project-name with the name of your project; if everything goes well, you should see something similar on your Terminal:
installing ng
create .editorconfig
create README.md
create src/app/app.component.css
create src/app/app.component.html
create src/app/app.component.spec.ts
create src/app/app.component.ts
create src/app/app.module.ts
create src/assets/.gitkeep
create src/environments/environment.prod.ts
create src/environments/environment.ts
create src/favicon.ico
create src/index.html
create src/main.ts
create src/polyfills.ts
create src/styles.css
create src/test.ts
create src/tsconfig.app.json
create src/tsconfig.spec.json
create src/typings.d.ts
create .angular-cli.json
create e2e/app.e2e-spec.ts
create e2e/app.po.ts
create e2e/tsconfig.e2e.json
create .gitignore
create karma.conf.js
create package.json
create protractor.conf.js
create tsconfig.json
create tslint.json
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Project 'project-name' successfully created.
If you run into any issues, ensure that you have angular-cli installed as described earlier.
Before we write any code for this application, let's import the stack that we earlier created into the project. Since this is a helper component, I would like to group it along with other helper methods under the utils directory in the root of the application.
These days, web applications are all about user experience, with flat design and small payloads. Everyone wants their application to be quick and compact. Using the clunky browser back button is slowly becoming a thing of the past. To create a custom Back button for our application, we will need to first create an Angular application from the previously installed ng cli client, as follows:
ng new back-button
To detect a state change, we can, luckily, use the Angular router's change event and take actions based on that. So, import the Router module in your app.component.ts and then use that to detect any state change:
import { Router, NavigationEnd } from '@angular/router';import { Stack } from './utils/stack';......constructor
(
private
stack: Stack,
private
router: Router) { // subscribe to the routers event
this
.router.
events
.
subscribe
((val) => { // determine of router is telling us that it has ended transition
if
(val
instanceof
NavigationEnd) { // state change done, add to stack
this
.stack.
push
(val); } });}
Any action that the user takes that results in a state change is now being saved into our stack, and we can move on to designing our layout and the back button that transitions the states.
We will use angular-material to style the app, as it is quick and reliable. To install angular-material, run the following command:
npm install --save @angular/material @angular/animations @angular/cdk
Once angular-material is saved into the application, we can use the Button component provided to create the UI necessary, which will be fairly straightforward. First, import the MatButtonModule that we want to use for this view and then inject the module as the dependency in your main AppModule.
The final form of app.module.ts would be as follows:
import
{ BrowserModule }
from
'@angular/platform-browser'
;
import
{ NgModule }
from
'@angular/core'
;
import
{ FormsModule }
from
'@angular/forms'
;
import
{ HttpModule }
from
'@angular/http'
;
import
{ BrowserAnimationsModule }
from
'@angular/platform-browser/animations'
;
import
{ MatButtonModule }
from
'@angular/material'
;
import
{ AppComponent }
from
'./app.component'
;
import
{ RouterModule }
from
"@angular/router"
;
import
{
routes
,
navigatableComponents
}
from
"./app.routing"
;
import
{ Stack }
from
"./utils/stack"
;// main angular module@NgModule({
declarations
: [ AppComponent, // our components are imported here in the main module ...
navigatableComponents
],
imports
: [ BrowserModule, FormsModule, HttpModule, // our routes are used here RouterModule.
forRoot
(
routes
), BrowserAnimationsModule,
// material module
MatButtonModule ],
providers
: [ Stack ],
bootstrap
: [AppComponent]})
export class
AppModule { }
We will place four buttons at the top to switch between the four states that we have created and then display these states in the router-outlet directive provided by Angular followed by the back button. After all this is done, we will get the following result:
<
nav
> <
button
mat-button routerLink=
"/about"
routerLinkActive=
"active"
> About </
button
> <
button
mat-button routerLink=
"/dashboard"
routerLinkActive=
"active"
> Dashboard </
button
> <
button
mat-button routerLink=
"/home"
routerLinkActive=
"active"
> Home </
button
> <
button
mat-button routerLink=
"/profile"
routerLinkActive=
"active"
> Profile </
button
></
nav
><
router-outlet
></
router-outlet
><
footer
> <
button
mat-fab (click)=
"
goBack
()"
>Back</
button
></
footer
>
