diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..0214585 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..9bfc240 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,35 @@ +## Description ## +(Brief description on what this PR is about) + +## If it is solving an issue, mention the issue number + +## Language ## +(enter x where it is correct for you) +- [] C +- [] C++ +- [] Java +- [] Python + +## Language - Branch mapping +| Lang | The branch to which you are making the PR| +| ----------- | ----------- | +| C | C | +| C++ | master | +| Java | Java | +| Python | Python | + +## Does your PR satisfy this mapping? +- [] Yes +- [] No + +## Checklist ## +### Essentials ### +- [ ] Changes are complete (i.e. I finished coding on this PR) +- [ ] Code is well-documented + +### Changes ### +- [ ] Feature1 +- [ ] Feature2 + +## Comments ## +- Interesting edge cases to note here diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16e356d..4a495b7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,16 @@ -# How to Collaborate: +# Contributions + +## Making a PR ## + +Make sure that you fill out the relevant details in the PR. + +## Guidelines for Merging + +The PR which will be having the specific file name as given in the issue, the one whose commit descriptions are relevant, and the code is readable, would be merged. + +For docs, make sure that you use markdown syntax. Checkout these links: [Markdown Guide](https://www.markdownguide.org/), [Markdown Cheat-Sheet](https://www.markdownguide.org/cheat-sheet/). + +## How to Collaborate: 1. Fork the repository to your own GitHub account. @@ -21,9 +33,6 @@ $ git add ``` 5. Commit you changes with a commit message containing your name, file(s) worked upon, changes added. -``` -$ git commit -m "Name| files| Changes" -``` 6. Push changes to your forked repository ``` @@ -31,7 +40,7 @@ $ git push -u origin branchname ``` 7. Create a pull request to the upstream repository. -# Synchronize forked repository with Upstream repository +## Synchronize forked repository with Upstream repository 1. Create upstream as our repository ``` diff --git a/Graph Theory/A Star/A_Star.cpp b/Graph Theory/A Star/A_Star.cpp new file mode 100644 index 0000000..c6ed5a3 --- /dev/null +++ b/Graph Theory/A Star/A_Star.cpp @@ -0,0 +1,663 @@ +// A C++ Program to implement A* Search Algorithm +#include +using namespace std; + +#define ROW 9 +#define COL 10 + +// Creating a shortcut for int, int pair type +typedef pair Pair; + +// Creating a shortcut for pair> type +typedef pair> pPair; + +// A structure to hold the neccesary parameters +struct cell +{ + // Row and Column index of its parent + // Note that 0 <= i <= ROW-1 & 0 <= j <= COL-1 + int parent_i, parent_j; + // f = g + h + double f, g, h; +}; + +// A Utility Function to check whether given cell (row, col) +// is a valid cell or not. +bool isValid(int row, int col) +{ + // Returns true if row number and column number + // is in range + return (row >= 0) && (row < ROW) && + (col >= 0) && (col < COL); +} + +// A Utility Function to check whether the given cell is +// blocked or not +bool isUnBlocked(int grid[][COL], int row, int col) +{ + // Returns true if the cell is not blocked else false + if (grid[row][col] == 1) + return (true); + else + return (false); +} + +// A Utility Function to check whether destination cell has +// been reached or not +bool isDestination(int row, int col, Pair dest) +{ + if (row == dest.first && col == dest.second) + return (true); + else + return (false); +} + +// A Utility Function to calculate the 'h' heuristics. +double calculateHValue(int row, int col, Pair dest) +{ + // Return using the distance formula + return ((double)sqrt ((row-dest.first)*(row-dest.first) + + (col-dest.second)*(col-dest.second))); +} + +// A Utility Function to trace the path from the source +// to destination +void tracePath(cell cellDetails[][COL], Pair dest) +{ + printf ("\nThe Path is "); + int row = dest.first; + int col = dest.second; + + stack Path; + + while (!(cellDetails[row][col].parent_i == row + && cellDetails[row][col].parent_j == col )) + { + Path.push (make_pair (row, col)); + int temp_row = cellDetails[row][col].parent_i; + int temp_col = cellDetails[row][col].parent_j; + row = temp_row; + col = temp_col; + } + + Path.push (make_pair (row, col)); + while (!Path.empty()) + { + pair p = Path.top(); + Path.pop(); + printf("-> (%d,%d) ",p.first,p.second); + } + + return; +} + +// A Function to find the shortest path between +// a given source cell to a destination cell according +// to A* Search Algorithm +void aStarSearch(int grid[][COL], Pair src, Pair dest) +{ + // If the source is out of range + if (isValid (src.first, src.second) == false) + { + printf ("Source is invalid\n"); + return; + } + + // If the destination is out of range + if (isValid (dest.first, dest.second) == false) + { + printf ("Destination is invalid\n"); + return; + } + + // Either the source or the destination is blocked + if (isUnBlocked(grid, src.first, src.second) == false || + isUnBlocked(grid, dest.first, dest.second) == false) + { + printf ("Source or the destination is blocked\n"); + return; + } + + // If the destination cell is the same as source cell + if (isDestination(src.first, src.second, dest) == true) + { + printf ("We are already at the destination\n"); + return; + } + + // Create a closed list and initialise it to false which means + // that no cell has been included yet + // This closed list is implemented as a boolean 2D array + bool closedList[ROW][COL]; + memset(closedList, false, sizeof (closedList)); + + // Declare a 2D array of structure to hold the details + //of that cell + cell cellDetails[ROW][COL]; + + int i, j; + + for (i=0; i> + where f = g + h, + and i, j are the row and column index of that cell + Note that 0 <= i <= ROW-1 & 0 <= j <= COL-1 + This open list is implenented as a set of pair of pair.*/ + set openList; + + // Put the starting cell on the open list and set its + // 'f' as 0 + openList.insert(make_pair (0.0, make_pair (i, j))); + + // We set this boolean value as false as initially + // the destination is not reached. + bool foundDest = false; + + while (!openList.empty()) + { + pPair p = *openList.begin(); + + // Remove this vertex from the open list + openList.erase(openList.begin()); + + // Add this vertex to the closed list + i = p.second.first; + j = p.second.second; + closedList[i][j] = true; + + /* + Generating all the 8 successor of this cell + + N.W N N.E + \ | / + \ | / + W----Cell----E + / | \ + / | \ + S.W S S.E + + Cell-->Popped Cell (i, j) + N --> North (i-1, j) + S --> South (i+1, j) + E --> East (i, j+1) + W --> West (i, j-1) + N.E--> North-East (i-1, j+1) + N.W--> North-West (i-1, j-1) + S.E--> South-East (i+1, j+1) + S.W--> South-West (i+1, j-1)*/ + + // To store the 'g', 'h' and 'f' of the 8 successors + double gNew, hNew, fNew; + + //----------- 1st Successor (North) ------------ + + // Only process this cell if this is a valid one + if (isValid(i-1, j) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i-1, j, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i-1][j].parent_i = i; + cellDetails[i-1][j].parent_j = j; + printf ("The destination cell is found\n"); + tracePath (cellDetails, dest); + foundDest = true; + return; + } + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i-1][j] == false && + isUnBlocked(grid, i-1, j) == true) + { + gNew = cellDetails[i][j].g + 1.0; + hNew = calculateHValue (i-1, j, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i-1][j].f == FLT_MAX || + cellDetails[i-1][j].f > fNew) + { + openList.insert( make_pair(fNew, + make_pair(i-1, j))); + + // Update the details of this cell + cellDetails[i-1][j].f = fNew; + cellDetails[i-1][j].g = gNew; + cellDetails[i-1][j].h = hNew; + cellDetails[i-1][j].parent_i = i; + cellDetails[i-1][j].parent_j = j; + } + } + } + + //----------- 2nd Successor (South) ------------ + + // Only process this cell if this is a valid one + if (isValid(i+1, j) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i+1, j, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i+1][j].parent_i = i; + cellDetails[i+1][j].parent_j = j; + printf("The destination cell is found\n"); + tracePath(cellDetails, dest); + foundDest = true; + return; + } + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i+1][j] == false && + isUnBlocked(grid, i+1, j) == true) + { + gNew = cellDetails[i][j].g + 1.0; + hNew = calculateHValue(i+1, j, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i+1][j].f == FLT_MAX || + cellDetails[i+1][j].f > fNew) + { + openList.insert( make_pair (fNew, make_pair (i+1, j))); + // Update the details of this cell + cellDetails[i+1][j].f = fNew; + cellDetails[i+1][j].g = gNew; + cellDetails[i+1][j].h = hNew; + cellDetails[i+1][j].parent_i = i; + cellDetails[i+1][j].parent_j = j; + } + } + } + + //----------- 3rd Successor (East) ------------ + + // Only process this cell if this is a valid one + if (isValid (i, j+1) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i, j+1, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i][j+1].parent_i = i; + cellDetails[i][j+1].parent_j = j; + printf("The destination cell is found\n"); + tracePath(cellDetails, dest); + foundDest = true; + return; + } + + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i][j+1] == false && + isUnBlocked (grid, i, j+1) == true) + { + gNew = cellDetails[i][j].g + 1.0; + hNew = calculateHValue (i, j+1, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i][j+1].f == FLT_MAX || + cellDetails[i][j+1].f > fNew) + { + openList.insert( make_pair(fNew, + make_pair (i, j+1))); + + // Update the details of this cell + cellDetails[i][j+1].f = fNew; + cellDetails[i][j+1].g = gNew; + cellDetails[i][j+1].h = hNew; + cellDetails[i][j+1].parent_i = i; + cellDetails[i][j+1].parent_j = j; + } + } + } + + //----------- 4th Successor (West) ------------ + + // Only process this cell if this is a valid one + if (isValid(i, j-1) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i, j-1, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i][j-1].parent_i = i; + cellDetails[i][j-1].parent_j = j; + printf("The destination cell is found\n"); + tracePath(cellDetails, dest); + foundDest = true; + return; + } + + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i][j-1] == false && + isUnBlocked(grid, i, j-1) == true) + { + gNew = cellDetails[i][j].g + 1.0; + hNew = calculateHValue(i, j-1, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i][j-1].f == FLT_MAX || + cellDetails[i][j-1].f > fNew) + { + openList.insert( make_pair (fNew, + make_pair (i, j-1))); + + // Update the details of this cell + cellDetails[i][j-1].f = fNew; + cellDetails[i][j-1].g = gNew; + cellDetails[i][j-1].h = hNew; + cellDetails[i][j-1].parent_i = i; + cellDetails[i][j-1].parent_j = j; + } + } + } + + //----------- 5th Successor (North-East) ------------ + + // Only process this cell if this is a valid one + if (isValid(i-1, j+1) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i-1, j+1, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i-1][j+1].parent_i = i; + cellDetails[i-1][j+1].parent_j = j; + printf ("The destination cell is found\n"); + tracePath (cellDetails, dest); + foundDest = true; + return; + } + + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i-1][j+1] == false && + isUnBlocked(grid, i-1, j+1) == true) + { + gNew = cellDetails[i][j].g + 1.414; + hNew = calculateHValue(i-1, j+1, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i-1][j+1].f == FLT_MAX || + cellDetails[i-1][j+1].f > fNew) + { + openList.insert( make_pair (fNew, + make_pair(i-1, j+1))); + + // Update the details of this cell + cellDetails[i-1][j+1].f = fNew; + cellDetails[i-1][j+1].g = gNew; + cellDetails[i-1][j+1].h = hNew; + cellDetails[i-1][j+1].parent_i = i; + cellDetails[i-1][j+1].parent_j = j; + } + } + } + + //----------- 6th Successor (North-West) ------------ + + // Only process this cell if this is a valid one + if (isValid (i-1, j-1) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination (i-1, j-1, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i-1][j-1].parent_i = i; + cellDetails[i-1][j-1].parent_j = j; + printf ("The destination cell is found\n"); + tracePath (cellDetails, dest); + foundDest = true; + return; + } + + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i-1][j-1] == false && + isUnBlocked(grid, i-1, j-1) == true) + { + gNew = cellDetails[i][j].g + 1.414; + hNew = calculateHValue(i-1, j-1, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i-1][j-1].f == FLT_MAX || + cellDetails[i-1][j-1].f > fNew) + { + openList.insert( make_pair (fNew, make_pair (i-1, j-1))); + // Update the details of this cell + cellDetails[i-1][j-1].f = fNew; + cellDetails[i-1][j-1].g = gNew; + cellDetails[i-1][j-1].h = hNew; + cellDetails[i-1][j-1].parent_i = i; + cellDetails[i-1][j-1].parent_j = j; + } + } + } + + //----------- 7th Successor (South-East) ------------ + + // Only process this cell if this is a valid one + if (isValid(i+1, j+1) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i+1, j+1, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i+1][j+1].parent_i = i; + cellDetails[i+1][j+1].parent_j = j; + printf ("The destination cell is found\n"); + tracePath (cellDetails, dest); + foundDest = true; + return; + } + + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i+1][j+1] == false && + isUnBlocked(grid, i+1, j+1) == true) + { + gNew = cellDetails[i][j].g + 1.414; + hNew = calculateHValue(i+1, j+1, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i+1][j+1].f == FLT_MAX || + cellDetails[i+1][j+1].f > fNew) + { + openList.insert(make_pair(fNew, + make_pair (i+1, j+1))); + + // Update the details of this cell + cellDetails[i+1][j+1].f = fNew; + cellDetails[i+1][j+1].g = gNew; + cellDetails[i+1][j+1].h = hNew; + cellDetails[i+1][j+1].parent_i = i; + cellDetails[i+1][j+1].parent_j = j; + } + } + } + + //----------- 8th Successor (South-West) ------------ + + // Only process this cell if this is a valid one + if (isValid (i+1, j-1) == true) + { + // If the destination cell is the same as the + // current successor + if (isDestination(i+1, j-1, dest) == true) + { + // Set the Parent of the destination cell + cellDetails[i+1][j-1].parent_i = i; + cellDetails[i+1][j-1].parent_j = j; + printf("The destination cell is found\n"); + tracePath(cellDetails, dest); + foundDest = true; + return; + } + + // If the successor is already on the closed + // list or if it is blocked, then ignore it. + // Else do the following + else if (closedList[i+1][j-1] == false && + isUnBlocked(grid, i+1, j-1) == true) + { + gNew = cellDetails[i][j].g + 1.414; + hNew = calculateHValue(i+1, j-1, dest); + fNew = gNew + hNew; + + // If it isn’t on the open list, add it to + // the open list. Make the current square + // the parent of this square. Record the + // f, g, and h costs of the square cell + // OR + // If it is on the open list already, check + // to see if this path to that square is better, + // using 'f' cost as the measure. + if (cellDetails[i+1][j-1].f == FLT_MAX || + cellDetails[i+1][j-1].f > fNew) + { + openList.insert(make_pair(fNew, + make_pair(i+1, j-1))); + + // Update the details of this cell + cellDetails[i+1][j-1].f = fNew; + cellDetails[i+1][j-1].g = gNew; + cellDetails[i+1][j-1].h = hNew; + cellDetails[i+1][j-1].parent_i = i; + cellDetails[i+1][j-1].parent_j = j; + } + } + } + } + + // When the destination cell is not found and the open + // list is empty, then we conclude that we failed to + // reach the destiantion cell. This may happen when the + // there is no way to destination cell (due to blockages) + if (foundDest == false) + printf("Failed to find the Destination Cell\n"); + + return; +} + + +// Driver program to test above function +int main() +{ + /* Description of the Grid- + 1--> The cell is not blocked + 0--> The cell is blocked */ + int grid[ROW][COL] = + { + { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 1, 1, 0, 1, 1, 1, 0, 1, 1 }, + { 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 }, + { 0, 0, 1, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 }, + { 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 } + }; + + // Source is the left-most bottom-most corner + Pair src = make_pair(8, 0); + + // Destination is the left-most top-most corner + Pair dest = make_pair(0, 0); + + aStarSearch(grid, src, dest); + + return(0); +} diff --git a/Graph Theory/A Star/README.md b/Graph Theory/A Star/README.md index e69de29..ad0250b 100644 --- a/Graph Theory/A Star/README.md +++ b/Graph Theory/A Star/README.md @@ -0,0 +1,65 @@ +# A* algorithm + +## What is A* Search Algorithm? +A* Search algorithm is one of the best and popular technique used in path-finding and graph traversals. + +## Why A* Search Algorithm ? # +Informally speaking, A* Search algorithms, unlike other traversal techniques, it has “brains”. What it means is that it is really a smart algorithm which separates it from the other conventional algorithms. This fact is cleared in detail in below sections. +And it is also worth mentioning that many games and web-based maps use this algorithm to find the shortest path very efficiently (approximation). + +### Explanation:- ## +Consider a square grid having many obstacles and we are given a starting cell and a target cell. We want to reach the target cell (if possible) from the starting cell as quickly as possible. Here A* Search Algorithm comes to the rescue. + +What A* Search Algorithm does is that at each step it picks the node according to a value-‘f’ which is a parameter equal to the sum of two other parameters – ‘g’ and ‘h’. At each step it picks the node/cell having the lowest ‘f’, and process that node/cell. + +We define ‘g’ and ‘h’ as simply as possible below + +g = the movement cost to move from the starting point to a given square on the grid, following the path generated to get there. +h = the estimated movement cost to move from that given square on the grid to the final destination. This is often referred to as the heuristic, which is nothing but a kind of smart guess. We really don’t know the actual distance until we find the path, because all sorts of things can be in the way (walls, water, etc.). There can be many ways to calculate this ‘h’ which are discussed in the later sections. + + +## Algorithm +We create two lists – Open List and Closed List (just like Dijkstra Algorithm) + +``` +A* Search Algorithm +1. Initialize the open list +2. Initialize the closed list + put the starting node on the open + list (you can leave its f at zero) + +3. while the open list is not empty + a) find the node with the least f on + the open list, call it "q" + + b) pop q off the open list + + c) generate q's 8 successors and set their + parents to q + + d) for each successor + + i) if successor is the goal, stop search + successor.g = q.g + distance between + successor and q + successor.h = distance from goal to + successor (This can be done using many + ways, we will discuss three heuristics- + Manhattan, Diagonal and Euclidean + Heuristics) + + successor.f = successor.g + successor.h + + ii) if a node with the same position as + successor is in the OPEN list which has a + lower f than successor, skip this successor + + iii) if a node with the same position as + successor is in the CLOSED list which has + a lower f than successor, skip this successor + otherwise, add the node to the open list + end (for loop) + + e) push q on the closed list + end (while loop +``` diff --git a/Graph Theory/Bellman Ford/bellmanford.cpp b/Graph Theory/Bellman Ford/bellmanford.cpp new file mode 100644 index 0000000..d7c97a1 --- /dev/null +++ b/Graph Theory/Bellman Ford/bellmanford.cpp @@ -0,0 +1,54 @@ +#include +#include +using namespace std; + +vector bellman_ford(int n, int src,vector > edges){ +// Create vector + vector dist(V+1, INT_MAX); + dist[src]=0; +//relax all edges v-1 times +for( int i=0; i>n>>m; + + +//Edge list +vector > edges; // (a,b,3) (c,d,5)....... + for(int i=0; i>u>>v>>wt; + edges.push_back({u,v,wt}); + } + //bellman ford + vector distances = bellman_ford(n,1,edges); + for(int i=1; i<=n; i++){ + cout<<"Node "< +#include +using namespace std; +vector getPath(int **adjmatrix,int v,int v1,int v2,bool *visited) +{ + if(v1==v2) + { vector v; + v.push_back(v1); + return v; + } + //Explore paths from all unvisited neighbours of v1 + + for(int vertex=0;vertex pathfromneigh= getPath(adjmatrix,v,vertex,v2,visited); + if(pathfromneigh.size() > 0){ + pathfromneigh.push_back(v1); + return pathfromneigh;} + } + } + vector path; + return path; +} + +vector getPath(int **adjmatrix,int v,int v1,int v2) +{ + bool *visited=new bool[v](); + visited[v1]=true; + return getPath(adjmatrix,v,v1,v2,visited); +} +int main() { + int V, E; + cin >> V >> E; + + int **adjmatrix=new int*[V]; + + for(int i=0;i>v1>>v2; + adjmatrix[v1][v2]=1; + adjmatrix[v2][v1]=1; + } + //find path from vi to v2 + int v1,v2; + cin>>v1>>v2; + + vector path=getPath(adjmatrix,V,v1,v2); + int i=0; + while(i +using namespace std; + + + +/* Function to do DFS of graph +* g[]: array of vectors to represent graph +* vis[]: array to keep track of visited vertex +*/ +void dfs(int s, vector g[], bool vis[]) +{ + + //Mark current node as visited + vis[s]=true; + cout<>T; + while(T--) + { + //N is no of nodes + //E is no of edges + int N, E; + cin>>N>>E; + + //Create vector to store graph + vector g[N]; + bool vis[N]; + + //memset is used to mark all nodes unvisited initially (It initialises all the values of vis[]=false) + memset(vis, false, sizeof(vis)); + + for(int i=0;i>u>>v; + g[u].push_back(v); + g[v].push_back(u); + } + + //Call DFS with starting node 0 and graph g + dfs(0,g,vis); + + cout< +using namespace std; + +//if verices adjacent is already visited and present in dfs recursion call stack it means there is a cycle in +//case of a directed graph +void DFS(int V, vector adj[], vector &visited, int src, bool *flag, +vector &stk){ + visited[src] = true; + stk[src] = true; + for(int x:adj[src]){ + if(visited[x]==false){ + DFS(V,adj,visited,x,flag,stk); + } + else{ + if(stk[x]==true){ + *flag = true; + } + + } + } + stk[src] = false; +} + +bool directedGraphCycle(int V, vector adj[]) +{ + vector visited(V,false); + vector rec_stack(V,false); + bool flag = false; + for(int i=0;i>t; + while(t--){ + //v is number of vertices and e is number of edges; + int v,e; + cin>>v>>e; + //Create an adjacency list of v vertices + vector adj_list[v]; + for(int i=0;i>u>>v; + } + cout< +#include +using namespace std; + +template + +class Graph +{ + unordered_map > >m; +public: + void addEdge(T u,T v,int dist,bool bidir=true) + { + m[u].push_back(make_pair(v,dist)); + if(bidir) + { + m[v].push_back(make_pair(u,dist)); + } + } + void printAdj() + { + for(auto j:m){ + cout<"; + for(auto l:j.second){ + cout<<"("<dist; + //set all the distance to infinity + for(auto j:m){ + dist[j.first]=INT_MAX; + } + //make a set to find a out node with minimum distance + set>s; + dist[src]=0; + s.insert(make_pair(0,src)); + while(!s.empty()){ + //find the pair at front + auto p=*(s.begin()); + T node=p.second; + int nodeDist=p.first; + s.erase(s.begin()); + //iterate over neighbours/children of the current node + for(auto childPair:m[node]){ + if(nodeDist+childPair.secondg; + //number of edges + int n; + cin>>n; + //u and v are the vertex and there is an edge connecting them whose weight/distance is dist + int u,v,dist; + + for(int i=0;i>u>>v>>dist; + g.addEdge(u,v,dist); + } + //print adjacency list + g.printAdj(); + //source from which we want to find distances to all other nodes + int src; + cin>>src; + g.dijsktraSSSP(src); + + return 0; +} diff --git a/Graph Theory/Dijkstra Algorithm/README.md b/Graph Theory/Dijkstra Algorithm/README.md index e69de29..40d901d 100644 --- a/Graph Theory/Dijkstra Algorithm/README.md +++ b/Graph Theory/Dijkstra Algorithm/README.md @@ -0,0 +1,42 @@ +# Dijkstra Algorithm + +You are given a directed or undirected weighted graph with n vertices and m edges. The weights of all edges are non-negative. You are also given a starting vertex s. This article discusses finding the lengths of the shortest paths from a starting vertex s to all other vertices, and output the shortest paths themselves. +This problem is also called **single-source shortest paths problem**. + +## Algorithm +Let's create an array d[] where for each vertex v we store the current length of the shortest path from s to v in d[v]. Initially d[s]=0, and for all other vertices this length equals infinity. In the implementation a sufficiently large number (which is guaranteed to be greater than any possible path length) is chosen as infinity. + +``` +d[v]=∞, v≠s +``` +In addition, we maintain a Boolean array u[] which stores for each vertex v whether it's marked. Initially all vertices are unmarked: +``` +u[v]=false +``` +The Dijkstra's algorithm runs for n iterations. At each iteration a vertex v is chosen as unmarked vertex which has the least value d[v]: + +Evidently, in the first iteration the starting vertex s will be selected. + +The selected vertex v is marked. Next, from vertex v relaxations are performed: all edges of the form (v,to) are considered, and for each vertex to the algorithm tries to improve the value d[to]. If the length of the current edge equals len, the code for relaxation is: +``` +d[to]=min(d[to],d[v]+len) +``` +After all such edges are considered, the current iteration ends. Finally, after n iterations, all vertices will be marked, and the algorithm terminates. We claim that the found values d[v] are the lengths of shortest paths from s to all vertices v. + +Note that if some vertices are unreachable from the starting vertex s, the values d[v] for them will remain infinite. Obviously, the last few iterations of the algorithm will choose those vertices, but no useful work will be done for them. Therefore, the algorithm can be stopped as soon as the selected vertex has infinite distance to it. + +**Restoring Shortest Paths** + +Usually one needs to know not only the lengths of shortest paths but also the shortest paths themselves. Let's see how to maintain sufficient information to restore the shortest path from s to any vertex. We'll maintain an array of predecessors p[] in which for each vertex v≠s p[v] is the penultimate vertex in the shortest path from s to v. Here we use the fact that if we take the shortest path to some vertex v and remove v from this path, we'll get a path ending in at vertex p[v], and this path will be the shortest for the vertex p[v]. This array of predecessors can be used to restore the shortest path to any vertex: starting with v, repeatedly take the predecessor of the current vertex until we reach the starting vertex s to get the required shortest path with vertices listed in reverse order. So, the shortest path P to the vertex v is equal to: + +``` +P=(s,…,p[p[p[v]]],p[p[v]],p[v],v) +``` +Building this array of predecessors is very simple: for each successful relaxation, i.e. when for some selected vertex v, there is an improvement in the distance to some vertex to, we update the predecessor vertex for to with vertex v: + +``` +p[to]=v +``` +**Time Complexity of Dijkstra Algorithm** + +Time complexity of Dijkstra's Algorithm changes with the method of implementation of the priority queue. Using Min Heap time complexity of O(V + E log V) can be acheived. Using array implementation of priority queue time complexity of O(V^2) can be acheived. Most efficient implemenatation of priority queue in terms of time complexity is using Fibonacci Heap which yeilds results in O(E + V log V). diff --git a/Graph Theory/Kruskals MST/Kruskal_MST.cpp b/Graph Theory/Kruskals MST/Kruskal_MST.cpp new file mode 100644 index 0000000..88a2259 --- /dev/null +++ b/Graph Theory/Kruskals MST/Kruskal_MST.cpp @@ -0,0 +1,191 @@ +// C++ program for Kruskal's algorithm to find Minimum Spanning Tree +// of a given connected, undirected and weighted graph +#include +using namespace std; + +// a structure to represent a weighted edge in graph +class Edge +{ + public: + int src, dest, weight; +}; + +// a structure to represent a connected, undirected +// and weighted graph +class Graph +{ + public: + // V-> Number of vertices, E-> Number of edges + int V, E; + + // graph is represented as an array of edges. + // Since the graph is undirected, the edge + // from src to dest is also edge from dest + // to src. Both are counted as 1 edge here. + Edge* edge; +}; + +// Creates a graph with V vertices and E edges +Graph* createGraph(int V, int E) +{ + Graph* graph = new Graph; + graph->V = V; + graph->E = E; + + graph->edge = new Edge[E]; + + return graph; +} + +// A structure to represent a subset for union-find +class subset +{ + public: + int parent; + int rank; +}; + +// A utility function to find set of an element i +// (uses path compression technique) +int find(subset subsets[], int i) +{ + // find root and make root as parent of i + // (path compression) + if (subsets[i].parent != i) + subsets[i].parent = find(subsets, subsets[i].parent); + + return subsets[i].parent; +} + +// A function that does union of two sets of x and y +// (uses union by rank) +void Union(subset subsets[], int x, int y) +{ + int xroot = find(subsets, x); + int yroot = find(subsets, y); + + // Attach smaller rank tree under root of high + // rank tree (Union by Rank) + if (subsets[xroot].rank < subsets[yroot].rank) + subsets[xroot].parent = yroot; + else if (subsets[xroot].rank > subsets[yroot].rank) + subsets[yroot].parent = xroot; + + // If ranks are same, then make one as root and + // increment its rank by one + else + { + subsets[yroot].parent = xroot; + subsets[xroot].rank++; + } +} + +// Compare two edges according to their weights. +// Used in qsort() for sorting an array of edges +int myComp(const void* a, const void* b) +{ + Edge* a1 = (Edge*)a; + Edge* b1 = (Edge*)b; + return a1->weight > b1->weight; +} + +// The main function to construct MST using Kruskal's algorithm +void KruskalMST(Graph* graph) +{ + int V = graph->V; + Edge result[V]; // Tnis will store the resultant MST + int e = 0; // An index variable, used for result[] + int i = 0; // An index variable, used for sorted edges + + // Step 1: Sort all the edges in non-decreasing + // order of their weight. If we are not allowed to + // change the given graph, we can create a copy of + // array of edges + qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp); + + // Allocate memory for creating V ssubsets + subset *subsets = new subset[( V * sizeof(subset) )]; + + // Create V subsets with single elements + for (int v = 0; v < V; ++v) + { + subsets[v].parent = v; + subsets[v].rank = 0; + } + + // Number of edges to be taken is equal to V-1 + while (e < V - 1 && i < graph->E) + { + // Step 2: Pick the smallest edge. And increment + // the index for next iteration + Edge next_edge = graph->edge[i++]; + + int x = find(subsets, next_edge.src); + int y = find(subsets, next_edge.dest); + + // If including this edge does't cause cycle, + // include it in result and increment the index + // of result for next edge + if (x != y) + { + result[e++] = next_edge; + Union(subsets, x, y); + } + // Else discard the next_edge + } + + // print the contents of result[] to display the + // built MST + cout<<"Following are the edges in the constructed MST\n"; + for (i = 0; i < e; ++i) + cout<edge[0].src = 0; + graph->edge[0].dest = 1; + graph->edge[0].weight = 10; + + // add edge 0-2 + graph->edge[1].src = 0; + graph->edge[1].dest = 2; + graph->edge[1].weight = 6; + + // add edge 0-3 + graph->edge[2].src = 0; + graph->edge[2].dest = 3; + graph->edge[2].weight = 5; + + // add edge 1-3 + graph->edge[3].src = 1; + graph->edge[3].dest = 3; + graph->edge[3].weight = 15; + + // add edge 2-3 + graph->edge[4].src = 2; + graph->edge[4].dest = 3; + graph->edge[4].weight = 4; + + KruskalMST(graph); + + return 0; +} + +// This code is contributed by rathbhupendra diff --git a/Graph Theory/Kruskals MST/README.md b/Graph Theory/Kruskals MST/README.md new file mode 100644 index 0000000..a82d6b2 --- /dev/null +++ b/Graph Theory/Kruskals MST/README.md @@ -0,0 +1 @@ +# Kruskal’s Minimum Spanning Tree \ No newline at end of file diff --git a/Graph Theory/Prims MST/README.md b/Graph Theory/Prims MST/README.md new file mode 100644 index 0000000..e6db5a7 --- /dev/null +++ b/Graph Theory/Prims MST/README.md @@ -0,0 +1 @@ +# Prim’s Minimum Spanning Tree (MST) \ No newline at end of file diff --git a/Graph Theory/Prims MST/code.cpp b/Graph Theory/Prims MST/code.cpp new file mode 100644 index 0000000..47fc76d --- /dev/null +++ b/Graph Theory/Prims MST/code.cpp @@ -0,0 +1,103 @@ +#include +using namespace std; + +// Number of vertices in the graph +#define V 5 + +// A utility function to find the vertex with +// minimum key value, from the set of vertices +// not yet included in MST +int minKey(int key[], bool mstSet[]) +{ + // Initialize min value + int min = INT_MAX, min_index; + + for (int v = 0; v < V; v++) + if (mstSet[v] == false && key[v] < min) + min = key[v], min_index = v; + + return min_index; +} + +// A utility function to print the +// constructed MST stored in parent[] +void printMST(int parent[], int graph[V][V]) +{ + cout<<"Edge \tWeight\n"; + for (int i = 1; i < V; i++) + cout< + +// Utility function to find minimum of two elements +int min(int x, int y) { return (x<=y)? x : y; } + +/* Returns index of x if present, else returns -1 */ +int fibonacciSearch(int arr[], int x, int n) +{ + /* Initialize fibonacci numbers */ + int fibMMm2 = 0; // (m-2)'th Fibonacci No. + int fibMMm1 = 1; // (m-1)'th Fibonacci No. + int fibM = fibMMm2 + fibMMm1; // m'th Fibonacci + + /* fibM is going to store the smallest Fibonacci + Number greater than or equal to n */ + while (fibM < n) + { + fibMMm2 = fibMMm1; + fibMMm1 = fibM; + fibM = fibMMm2 + fibMMm1; + } + + // Marks the eliminated range from front + int offset = -1; + + /* while there are elements to be inspected. Note that + we compare arr[fibMm2] with x. When fibM becomes 1, + fibMm2 becomes 0 */ + while (fibM > 1) + { + // Check if fibMm2 is a valid location + int i = min(offset+fibMMm2, n-1); + + /* If x is greater than the value at index fibMm2, + cut the subarray array from offset to i */ + if (arr[i] < x) + { + fibM = fibMMm1; + fibMMm1 = fibMMm2; + fibMMm2 = fibM - fibMMm1; + offset = i; + } + + /* If x is greater than the value at index fibMm2, + cut the subarray after i+1 */ + else if (arr[i] > x) + { + fibM = fibMMm2; + fibMMm1 = fibMMm1 - fibMMm2; + fibMMm2 = fibM - fibMMm1; + } + + /* element found. return index */ + else return i; + } + + /* comparing the last element with x */ + if(fibMMm1 && arr[offset+1]==x)return offset+1; + + /*element not found. return -1 */ + return -1; +} + +/* driver function */ +int main(void) +{ + int arr[] = {10, 22, 35, 40, 45, 50, 80, 82, + 85, 90, 100}; + int n = sizeof(arr)/sizeof(arr[0]); + int x = 85; + printf("Found at index: %d", + fibonacciSearch(arr, x, n)); + return 0; +} +Upda diff --git a/Searching/Linear Search/README.md b/Searching/Linear Search/README.md index e69de29..d759029 100644 --- a/Searching/Linear Search/README.md +++ b/Searching/Linear Search/README.md @@ -0,0 +1,43 @@ +# **Linear Search** + +Linear search is a very simple search algorithm. In this type of search, a sequential search is made over all items one by one. Every item is checked and if a match is found then that particular item is returned, otherwise the search continues till the end of the data collection. This algorithm works on Linear Data structures such as Arrays. + + +## _EXAMPLE for linear search_ + +For example: We are searching for number **_33_** in the given array. We will begin searching number **_33_** from starting of the given array till end. And As soon as we find first number **_33_** in array we stop searching further in the array. + +![Gif](https://www.tutorialspoint.com/data_structures_algorithms/images/linear_search.gif) + + +# **Simple algorithm for linear search** + +Linear Search ( Array A, Value x) + +**Step 1**: Set i to 1 + +**Step 2**: if i > n then go to step 7 + +**Step 3**: if A[i] = x then go to step 6 + +**Step 4**: Set i to i + 1 + +**Step 5**: Go to Step 2 + +**Step 6**: Print Element x Found at index i and go to step 8 + +**Step 7**: Print element not found + +**Step 8**: Exit + + + +# **Pseudo code for Linear search** + + procedure linear_search (list, value) + for each item in the list + if match item == value + return the item's location + end if + end for + end procedure diff --git a/Searching/Linear Search/linear_search_array_approach.cpp b/Searching/Linear Search/linear_search_array_approach.cpp new file mode 100644 index 0000000..ab94bd0 --- /dev/null +++ b/Searching/Linear Search/linear_search_array_approach.cpp @@ -0,0 +1,30 @@ +#include +using namespace std; + +int search(int arr[], int n, int x) +{ + int i; + for (i = 0; i < n; i++){ + if (arr[i] == x){ + return i; + } + } + return -1; +} + +int main(void) +{ + int n; //number of elements in array + cin >> n; + int arr[n]; + //storing the elements in array + for(int i = 0 ; i> arr[i]; + } + int x; //element to be searched + cin >> x; + int result = search(arr, n, x); + (result == -1)? cout << "Element is not present in array" + : cout << "Element is present at index " << result; + return 0; +} diff --git a/Searching/Linear Search/linear_search.cpp b/Searching/Linear Search/linear_search_vector_approach.cpp similarity index 69% rename from Searching/Linear Search/linear_search.cpp rename to Searching/Linear Search/linear_search_vector_approach.cpp index ba93d76..503ccb2 100644 --- a/Searching/Linear Search/linear_search.cpp +++ b/Searching/Linear Search/linear_search_vector_approach.cpp @@ -18,17 +18,17 @@ int main() vector arr; int n; int x; - cout<<"Enter the number of elements in input : "; - cin>>n; - for(int i=0;i> n; + for(int i = 0; i < n ; i++) { - cout<<"Enter the input value of element "<>p; + cin >> p; arr.push_back(p); } - cout<<"Enter the value to be searched: "; - cin>>x; + cout << "Enter the value to be searched: "; + cin >> x; int index = search(arr, n, x); if (index == -1) cout << "Element is not present in the array"; @@ -36,4 +36,4 @@ int main() cout << "Element found at position " << index; return 0; -} \ No newline at end of file +} diff --git a/Searching/Linear Search/test b/Searching/Linear Search/test deleted file mode 100644 index 9daeafb..0000000 --- a/Searching/Linear Search/test +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/Sorting/Bucket Sort/bucketsort.cpp b/Sorting/Bucket Sort/bucketsort.cpp new file mode 100644 index 0000000..e3d9324 --- /dev/null +++ b/Sorting/Bucket Sort/bucketsort.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +using namespace std; +void display(float *array, int size) { + for(int i = 0; i bucket[size]; + for(int i = 0; i> n; + float arr[n]; //create an array with given number of elements + cout << "Enter elements:" << endl; + for(int i = 0; i> arr[i]; + } + cout << "Array before Sorting: "; + display(arr, n); + bucketSort(arr, n); + cout << "Array after Sorting: "; + display(arr, n); +} +