Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

Mastering Sorting, Stacks, Queues, HashTables, BSTs, and Graph Traversal: A Comprehensive CSCI 251 Study Guide

Learn how to implement Insert Sort, Select Sort, Quick Sort, Merge Sort, stacks, queues, hash tables, binary search trees, and BFS/DFS in Java with this detailed tutorial covering projects one through five.

CSCI 251 project solutions sorting algorithms Java insert sort select sort quick sort merge sort stack queue implementation Java palindrome checker stack queue hash table Java generic binary search tree Java BFS DFS graph traversal Java adjacency matrix graph Java recursive sorting Java data structures project help Java sorting tutorial BST traversal recursive hash table linear probing graph BFS DFS implementation CSCI 251 study guide

Introduction to CSCI 251 Projects

Welcome to this comprehensive study guide for CSCI 251 projects one through five. In this tutorial, you will learn how to implement fundamental data structures and algorithms in Java, including sorting algorithms, stacks, queues, hash tables, binary search trees, and graph traversals. These projects are designed to reinforce key concepts from your textbook and prepare you for real-world programming challenges. Let's dive into each project step by step.

Project One: Sorting Algorithms

The first project requires you to implement four classic sorting algorithms: Insert Sort, Select Sort, Quick Sort, and Merge Sort. You will create a class called MySort.java with the specified public methods. These algorithms are essential for organizing data efficiently, whether you're sorting a leaderboard for a gaming tournament or arranging student grades.

Insert Sort

Insert Sort builds the final sorted array one element at a time. It is efficient for small datasets and works like sorting a hand of playing cards. Here's a simple implementation:

public static void insertSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

Select Sort

Select Sort repeatedly finds the minimum element from the unsorted part and puts it at the beginning. It's simple but not suitable for large datasets.

public static void selectSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIdx = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[minIdx]) {
                minIdx = j;
            }
        }
        int temp = arr[minIdx];
        arr[minIdx] = arr[i];
        arr[i] = temp;
    }
}

Quick Sort

Quick Sort is a divide-and-conquer algorithm that picks a pivot and partitions the array. It's widely used in practice, similar to how social media algorithms quickly rank trending posts. Implement the recursive version with a pivot method:

private static int pivot(int[] arr, int begin, int end) {
    int pivotVal = arr[begin];
    int left = begin + 1;
    int right = end;
    while (true) {
        while (left <= right && arr[left] <= pivotVal) left++;
        while (left <= right && arr[right] >= pivotVal) right--;
        if (left > right) break;
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }
    arr[begin] = arr[right];
    arr[right] = pivotVal;
    return right;
}

private static void quickSortRecursive(int[] arr, int begin, int end) {
    if (begin < end) {
        int pivotIdx = pivot(arr, begin, end);
        quickSortRecursive(arr, begin, pivotIdx - 1);
        quickSortRecursive(arr, pivotIdx + 1, end);
    }
}

public static void quickSort(int[] arr) {
    quickSortRecursive(arr, 0, arr.length - 1);
}

Merge Sort

Merge Sort also uses divide-and-conquer and guarantees O(n log n) performance. It's like merging two sorted playlists into one. Implement the merge and recursive methods:

private static void merge(int[] arr, int start, int middle, int end) {
    int n1 = middle - start + 1;
    int n2 = end - middle;
    int[] left = new int[n1];
    int[] right = new int[n2];
    for (int i = 0; i < n1; i++) left[i] = arr[start + i];
    for (int j = 0; j < n2; j++) right[j] = arr[middle + 1 + j];
    int i = 0, j = 0, k = start;
    while (i < n1 && j < n2) {
        if (left[i] <= right[j]) {
            arr[k] = left[i];
            i++;
        } else {
            arr[k] = right[j];
            j++;
        }
        k++;
    }
    while (i < n1) { arr[k] = left[i]; i++; k++; }
    while (j < n2) { arr[k] = right[j]; j++; k++; }
}

private static void mergeSortRecursive(int[] arr, int begin, int end) {
    if (begin < end) {
        int middle = (begin + end) / 2;
        mergeSortRecursive(arr, begin, middle);
        mergeSortRecursive(arr, middle + 1, end);
        merge(arr, begin, middle, end);
    }
}

public static void mergeSort(int[] arr) {
    mergeSortRecursive(arr, 0, arr.length - 1);
}

Project Two: Stacks and Queues

This project reinforces knowledge of stack (LIFO) and queue (FIFO) data structures using ArrayList. You will implement a palindrome checker, which is useful in DNA sequence analysis or text processing apps.

Stack Implementation

Use an ArrayList to create a stack with push, pop, peek, and isEmpty methods.

Queue Implementation

Similarly, implement a queue with enqueue, dequeue, and isEmpty.

Palindrome Checker

To check if a string is a palindrome, push each character onto a stack and enqueue into a queue. Then compare pop and dequeue results.

Project Three: Hash Table

Hash tables are fundamental for fast data retrieval, like caching in web apps or indexing in databases. You will implement MyHashEntry and MyHashTable as generic types.

MyHashEntry

Each entry holds a key-value pair and a boolean flag to mark deletion.

MyHashTable

Implement linear probing for collision resolution. Include methods like put, get, remove, and rehash. Remember that the table size should be a prime number for better distribution.

Project Four: Binary Search Tree

BSTs are used in decision trees, file systems, and AI search algorithms. You will implement TreeNode and BinarySearchTree with recursive traversals.

Insert and Search

Recursively insert nodes and search for values. The toString method uses a recursive node traversal to produce a parenthesized representation.

public String toString() {
    return "(" + nodeTraversal(root) + ")";
}
private String nodeTraversal(TreeNode node) {
    if (node == null) return "--";
    return node.getData() + "(" + nodeTraversal(node.getLeft()) + "," + nodeTraversal(node.getRight()) + ")";
}

Project Five: Graph Traversal

Graphs are everywhere: social networks, GPS navigation, and recommendation systems. You will implement BFS and DFS on a directed weighted graph using an adjacency matrix.

Breadth-First Search (BFS)

Use a queue to explore neighbors level by level, like finding the shortest path in a game map.

Depth-First Search (DFS)

Use a stack (or recursion) to go deep first, useful for maze solving or topological sorting.

Conclusion

By completing these projects, you will gain hands-on experience with core CS concepts that are essential for technical interviews and real-world software development. Practice by running the provided JAR files to verify your implementations. Good luck with your assignments!