ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Programming Fundamentals
    CC-112
    Progress0 / 39 topics
    Topics
    1. Introduction to Problem Solving, Algorithms, Programming, and C Language2. Problem Solving, a brief review of Von-Neumann Architecture3. The C Programming Language, Pseudo-code, Concept of Variable4. Data types in Pseudo-code, The C Standard Library and Open Source5. Input/Output, Arithmetic expressions, Assignment statement, Operator precedence6. Concept of Integer division, Flowchart and its notations7. Typical C Program Development Environment, Role of Compiler and Linker8. Test Driving C Application9. Introduction to C Programming: A Simple C Program: Printing Text, Adding Two Integer10. Memory Concepts, Arithmetic in C, Operators11. Decision Making: Equality and Relational Operators12. Structured Program Development: The if, if...else, while Nested Control Statements13. Program Control: for, switch, do...while, break, continue, Logical Operators14. Functions: Modularizing Program in C, Math Library Functions15. Function Definitions and Prototypes, Function-Call Stack and Stack Frames16. Stack rolling and unrolling, Headers, Passing Arguments by Value and by Reference17. Random Number Generation, Scope Rules, Recursion, Recursion vs Iteration18. Arrays: Defining Arrays, Character Arrays, Static and Automatic Local Arrays19. Passing Arrays to Function, Sorting and Searching Arrays20. Multidimensional and Variable Length Arrays21. Pointers: Pointer Definitions and Initialization, Pointer Operators22. Passing Arguments to Function by Reference, Using the const and sizeof Operator23. Pointer Expressions and Arithmetic, Pointers and Arrays, Array of Pointers24. Function Pointers25. Characters and Strings: Strings and Characters, Character Handling Library26. String Functions, Library Functions27. Formatted Input/Output: Streams, Formatted Output with printf, Formatted Input with scanf28. Structures: Defining Structures, Accessing Structure Member, Structures and Functions29. typedef, Unions30. Bit Manipulation and Enumeration: Bitwise Operators, Bit Fields, Enumeration Constants31. File Processing: Files and Streams, Creating, Reading and Writing data to a Sequential and a Random-Access File32. Preprocessor: #include, #define, Conditional Compilation, #error and #pragma33. # and ## Operators, Predefined Symbolic Constants, Assertions34. Other Topics: Variable Length Argument List, Using Command Line Arguments35. Compiling Multiple-Source-File Programs, Program Termination with exit and atexit36. Suffixes for Integer and Floating-Point Literals, Signal Handling37. Dynamic Memory Allocation: calloc and realloc, goto38. Advance Topics: Self-Referential Structures, Linked Lists39. Efficiency of Algorithms, Selection and Insertion Sort
    CC-112›Advance Topics: Self-Referential Structures, Linked Lists
    Programming FundamentalsTopic 38 of 39

    Advance Topics: Self-Referential Structures, Linked Lists

    7 minread
    1,272words
    Intermediatelevel

    Advanced Topics: Self-Referential Structures, Linked Lists

    In advanced C programming, two important concepts often discussed are self-referential structures and linked lists. These are fundamental topics in data structure design, offering powerful ways to organize and manage data in a dynamic and flexible manner.


    1. Self-Referential Structures

    A self-referential structure in C is a structure that contains a pointer to an instance of the same structure type. This allows for the creation of recursive data structures, like linked lists, trees, and graphs. The key feature of a self-referential structure is that it "refers to itself" through pointers.

    Definition of a Self-Referential Structure

    In C, a structure is defined using the struct keyword, and a self-referential structure typically has a pointer to itself (or another instance of the same structure).

    Example: Definition of a Self-Referential Structure
    #include <stdio.h>
    #include <stdlib.h>
    
    // Definition of a self-referential structure
    struct Node {
        int data;
        struct Node* next;  // Pointer to the next Node, making it self-referential
    };
    
    int main() {
        // Create a self-referential structure (linked list node)
        struct Node* head = (struct Node*)malloc(sizeof(struct Node));
        head->data = 10;
        head->next = NULL;
    
        printf("Data: %d\n", head->data);  // Output: Data: 10
    
        free(head);  // Free the allocated memory
        return 0;
    }
    

    Explanation:

    • The Node structure has an int field (data) and a pointer (next) to another Node. This makes it self-referential because the next pointer points to another instance of the same structure.
    • This design enables us to create dynamic data structures where each element (node) can point to the next, such as in linked lists.

    2. Linked Lists

    A linked list is a linear data structure where each element (called a node) contains two parts:

    1. Data: The actual data stored in the node.
    2. Next: A pointer to the next node in the sequence (or NULL if it’s the last node).

    Linked lists are dynamic in nature, meaning that their size can grow or shrink at runtime, unlike arrays that have a fixed size.

    Types of Linked Lists:

    • Singly Linked List: Each node points only to the next node.
    • Doubly Linked List: Each node contains two pointers: one pointing to the next node and one pointing to the previous node.
    • Circular Linked List: The last node’s next pointer points back to the first node, forming a loop.

    Singly Linked List

    A singly linked list is a simple form of linked list where each node contains data and a pointer to the next node in the list.

    Structure of a Singly Linked List Node:
    struct Node {
        int data;        // Data of the node
        struct Node* next;  // Pointer to the next node
    };
    
    Example: Implementing a Simple Singly Linked List
    #include <stdio.h>
    #include <stdlib.h>
    
    // Definition of the Node structure (self-referential structure)
    struct Node {
        int data;
        struct Node* next;
    };
    
    // Function to print the linked list
    void printList(struct Node* head) {
        struct Node* temp = head;
        while (temp != NULL) {
            printf("%d -> ", temp->data);
            temp = temp->next;
        }
        printf("NULL\n");
    }
    
    int main() {
        // Allocate memory for 3 nodes
        struct Node* head = (struct Node*)malloc(sizeof(struct Node));
        struct Node* second = (struct Node*)malloc(sizeof(struct Node));
        struct Node* third = (struct Node*)malloc(sizeof(struct Node));
    
        // Initialize data
        head->data = 10;
        head->next = second;
    
        second->data = 20;
        second->next = third;
    
        third->data = 30;
        third->next = NULL;  // Last node's next is NULL
    
        // Print the linked list
        printList(head);
    
        // Free the memory
        free(head);
        free(second);
        free(third);
    
        return 0;
    }
    

    Explanation:

    • Three nodes are created dynamically using malloc(), with each node containing an integer (data) and a pointer (next).
    • The first node (head) points to the second node, and the second node points to the third. The last node points to NULL, indicating the end of the list.
    • The printList() function traverses the list, printing each node’s data until it reaches NULL.
    Output:
    10 -> 20 -> 30 -> NULL
    

    Operations on Singly Linked Lists:

    • Insertion: Adding a new node at the beginning, middle, or end of the list.
    • Deletion: Removing a node from the beginning, middle, or end.
    • Traversal: Going through each node of the list to access data or perform operations.
    • Searching: Finding a specific value within the list.
    • Reversal: Reversing the order of the nodes in the list.
    Example: Inserting a New Node at the Beginning
    void insertAtBeginning(struct Node** head, int new_data) {
        struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
        new_node->data = new_data;
        new_node->next = *head;  // Make next of new node point to the old head
        *head = new_node;        // Move the head pointer to the new node
    }
    
    int main() {
        struct Node* head = NULL;
        insertAtBeginning(&head, 10);
        insertAtBeginning(&head, 20);
        insertAtBeginning(&head, 30);
    
        printList(head);  // Output: 30 -> 20 -> 10 -> NULL
    
        // Free the memory
        free(head);
    
        return 0;
    }
    

    3. Doubly Linked List

    In a doubly linked list, each node has two pointers:

    • next: A pointer to the next node.
    • prev: A pointer to the previous node.

    This structure allows for traversal in both directions: forward and backward.

    Structure of a Doubly Linked List Node:
    struct Node {
        int data;
        struct Node* next;
        struct Node* prev;
    };
    
    Advantages of Doubly Linked Lists:
    • Bidirectional Traversal: Can be traversed both forward and backward.
    • Efficient Insertion/Deletion: Insertion or deletion of a node can be done efficiently from both ends of the list or from the middle, as you can directly access the previous node.

    4. Circular Linked List

    In a circular linked list, the last node points back to the first node, forming a loop. It can be either singly or doubly circular.

    • Singly Circular Linked List: The next pointer of the last node points to the first node.
    • Doubly Circular Linked List: Both next and prev pointers form a circle.
    Advantages of Circular Linked Lists:
    • Continuous Traversal: You can keep traversing the list infinitely without needing to check for a NULL at the end.
    • Efficient Circular Queue Implementation: Useful for circular buffers or queues.

    Summary of Key Points

    Concept Description Advantages/Use Cases
    Self-Referential Structure A structure that contains a pointer to itself, enabling recursive data structures (like linked lists). Used to create dynamic data structures like linked lists, trees, etc.
    Singly Linked List A linked list where each node points to the next node. Dynamic memory allocation, simple to implement.
    Doubly Linked List A linked list where each node points to both the next and previous nodes. Bidirectional traversal, efficient insertions and deletions from both ends.
    Circular Linked List A linked list where the last node points back to the first node. Continuous traversal, used for circular buffers or queues.

    Conclusion

    Self-referential structures, like linked lists, are essential in dynamic memory management and allow you to create complex data structures in C. Linked lists, whether singly, doubly, or circular, provide flexibility in how data can be organized, accessed, and manipulated. These structures are foundational in understanding more advanced algorithms and data structures, such as trees, graphs, and dynamic memory management techniques.

    Previous topic 37
    Dynamic Memory Allocation: calloc and realloc, goto
    Next topic 39
    Efficiency of Algorithms, Selection and Insertion Sort

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time7 min
      Word count1,272
      Code examples0
      DifficultyIntermediate