⚡ TechVani: AI, Technology, Apps, Coding & Digital World
TechVaniAI • Technology • Apps • Coding • Digital World
HomeAI & TechAppsCodingFree AI ToolsStudent TechSecurityAboutContactPrivacy
TECHVANI // LEARN. BUILD. TEST.

Learn the tech. Build the idea.

Clear study notes, tested lab files and practical guides for coding, AI and digital safety.

Explore Latest →
šŸ¤– AI & TechAI news, tools & guides šŸ“± Apps & ToolsUseful apps & websites šŸ’» CodingProgramming & web development šŸŽ“ Student TechStudy & career technology šŸ” Cyber SecuritySafety & awareness

Latest Posts

Circuit Notebook theme

Exam Notes

šŸ“š BTech CSE Exam Notes

Find Semester 1-8 subjects in one place. Choose a semester and open the notes you need. This is a general study guide, not an official syllabus.

Open Exam Notes →🧪 Open Lab Files →

Exam Numericals & Study Series

Practice CPU scheduling and explore OS and DBMS topics in separate, easy-to-follow parts. New topics will appear in the hub as they are published.

Open Numericals Hub →

Start here and stay in touch

New to TechVani? Start with our free AI tools guide for students. It covers which tools to try and what to check before relying on an answer.

For step-by-step videos, visit SiteSudhar on YouTube.

Join TechVani on WhatsApp

Get new AI tools and coding guides in your WhatsApp Updates tab.

Browse Topics

Popular Posts

TechVani

Data Structures | Semester 3 Core Notes

Semester 3 - Page 1: Data Structures. 36 numbered topics, highlighted invariants, worked traces, answered exam questions, three diagrams and six complete C11 programs. General common-core BTech CSE guide, not an official assessed syllabus or past-paper prediction. Compare your assigned outline.

How to use: learn the contract, trace a small input and justify the cost. Compile each C block separately with gcc -std=c11 -Wall -Wextra -pedantic demo.c -o demo, then run ./demo. Fixed trusted inputs are supplied by main. Dynamic-memory examples check allocation failure. Fixed capacity, recursion depth and index contracts are explicit limits.

Topic map

  1. Data structures and ADTs
  2. Time and space analysis
  3. Worst, average and amortized costs
  4. Arrays and addresses
  5. Matrices and sparse storage
  6. Linear and binary search
  7. Singly linked lists
  8. Doubly and circular lists
  9. Allocation and pointer safety
  10. List reversal
  11. Stack contracts and bounds
  12. Bracket matching
  13. Infix and postfix conversion
  14. Postfix evaluation
  15. Circular queues
  16. Deque and priority queue
  17. Recursion and stack space
  18. Tree terms and height
  19. Binary tree traversals
  20. BST search and insertion
  21. BST deletion
  22. AVL and red-black trees
  23. Binary heaps
  24. B-trees, tries and threading
  25. Hashing and load factor
  26. Collision handling
  27. Elementary sorting and stability
  28. Merge, quick and heap sort
  29. Counting, radix and lower bounds
  30. Graph terms and representation
  31. BFS and shortest paths
  32. DFS and disconnected graphs
  33. DAGs and topological order
  34. Weighted paths and spanning trees
  35. Testing and choosing structures
  36. Practice answers and revision

1. Data structures and ADTs

An ADT defines operations and behavior; a data structure selects storage and algorithms..

Worked example: A stack can use an array or linked nodes while keeping LIFO behavior.
Exam question: Does an ADT specify a language?
Answer: No. It specifies a contract, not a programming language.

2. Time and space analysis

State input size, operation, case and auxiliary storage. O is an upper bound, Omega a lower bound and Theta a tight bound.

Worked example: A full scan is Theta(n); two independent n-iteration nested loops are Theta(n squared).
Exam question: Is O(n) always tight?
Answer: No. A constant-time operation is also O(n); Theta(1) is more informative.

3. Worst, average and amortized costs

Average-case needs an input distribution. Amortized cost bounds a sequence without assuming random inputs.

Worked example: A doubling dynamic array has amortized O(1) append; a resize copies O(n) items.
Exam question: Does amortized mean random-input average?
Answer: No. It bounds total work over a sequence.

4. Arrays and addresses

Contiguous arrays support O(1) indexed access in the usual RAM model. Validate indices in C.

Worked example: Base 1000, element width 4, index 3 gives address 1012.
Exam question: Why is middle insertion O(n)?
Answer: Later elements shift; capacity and allocation are separate costs.

5. Matrices and sparse storage

For row-major R by C storage, offset(i, j)=i*C+j. Sparse formats store nonzero values and positions.

Worked example: A 3 by 4 array at(2, 1) has offset 9; base 1000, width 4 gives 1036.
Exam question: Is a pointer-to-pointer matrix always contiguous?
Answer: No. Separately allocated rows differ from a contiguous 2 D array.

6. Linear and binary search

Linear search needs no order. Binary search requires sorted data and a shrinking interval. Specify duplicate behavior.

Worked example: For[2, 4, 4, 7, 9], first 4 is index 1; absent 6 gives-1.
Exam question: Can binary search handle unsorted data?
Answer: Not with its usual correctness guarantee.

Binary search and insertion sort

#include <stdio.h>
#include <stddef.h>
int first_match(const int a[], size_t n, int key) {
    size_t lo=0, hi=n;
    while (lo<hi) {
        size_t mid=lo+(hi-lo)/2;
        if (a[mid]<key) lo=mid+1; else hi=mid;
    }
    return lo<n && a[lo]==key ? (int)lo : -1;
}
void insertion_sort(int a[], size_t n) {
    for (size_t i=1; i<n; ++i) {
        int key=a[i]; size_t j=i;
        while (j>0 && a[j-1]>key) {
            a[j]=a[j-1]; --j;
        }
        a[j]=key;
    }
}
int main(void) {
    int a[]={7,4,2,4,9};
    insertion_sort(a,5);
    for (size_t i=0;i<5;++i)
        printf("%d%s",a[i],i==4 ? "\n" : " ");
    printf("first 4: %d; missing 6: %d\n",
           first_match(a,5,4),first_match(a,5,6));
    printf("empty: %d\n",first_match(NULL,0,4));
    return 0;
}

Checked output:

2 4 4 7 9
first 4: 1; missing 6: -1
empty: -1

The search assumes sorted data and a size that fits its int return index. NULL is valid here only with n=0. This is a bounded demonstration, not an arbitrary-size library API.

7. Singly linked lists

Each node stores data and next. Insertion after a known node is O(1); locating it is separate.

Worked example: 4->6->8 becomes 4->5->6->8 by splicing after 4.
Exam question: Can you remove the tail without its predecessor in O(1)?
Answer: Not generally; finding the predecessor needs traversal.
Head: 4Next: 6Next: 8NULL
Links show traversal order, not contiguous memory addresses.

8. Doubly and circular lists

Doubly linked nodes store prev too. Circular lists have no null terminator; stop at the starting node or use a count.

Worked example: Deleting B from A-B-C sets A.next=C and C.prev=A.
Exam question: What if only one link changes?
Answer: Forward and backward traversal disagree and may touch stale memory.

9. Allocation and pointer safety

Check allocation failure, define ownership and free each owned allocation once. Never read freed storage.

Worked example: Save next=current->next before free(current), then advance to next.
Exam question: What is a dangling pointer?
Answer: A pointer to an object whose lifetime ended; clearing one pointer does not repair aliases.

10. List reversal

Maintain prev, current, next. Save the unreversed suffix before changing the current link.

Worked example: 1->2->3 reverses to 3->2->1. Empty and one-node cases remain valid.
Exam question: Why remember next?
Answer: Otherwise changing current.next loses access to the remaining list.

Owned list reversal and cleanup

#include <stdio.h>
#include <stdlib.h>
typedef struct Node { int value; struct Node *next; } Node;
void clear(Node *p) {
    while (p) { Node *next=p->next; free(p); p=next; }
}
int push_front(Node **head,int value) {
    Node *p=malloc(sizeof *p);
    if (!p) return 0;
    p->value=value; p->next=*head; *head=p;
    return 1;
}
Node *reverse(Node *head) {
    Node *prev=NULL;
    while (head) {
        Node *next=head->next;
        head->next=prev; prev=head; head=next;
    }
    return prev;
}
int main(void) {
    Node *head=NULL;
    for (int v=3;v>=1;--v) {
        if (!push_front(&head,v)) {
            clear(head); fputs("allocation failed\n",stderr); return 1;
        }
    }
    head=reverse(head);
    for (Node *p=head;p;p=p->next)
        printf("%d%s",p->value,p->next ? " " : "\n");
    clear(head); head=NULL;
    printf("empty reverse: %s\n",reverse(head)==NULL ? "ok" : "bad");
    return 0;
}

Checked output:

3 2 1
empty reverse: ok

11. Stack contracts and bounds

A stack is LIFO. Reject full push and empty pop before accessing the array.

Worked example: Push 2, 5; pop gives 5 then 2; a third pop is underflow.
Exam question: Overflow versus underflow?
Answer: Overflow adds beyond capacity; underflow removes from empty storage.

12. Bracket matching

Push openers; each closer must match the latest opener. Reject leftover openings. The simple model ignores quoted-string syntax.

Worked example: ([{}]) matches; ([)] fails despite equal bracket counts.
Exam question: Why are counts insufficient?
Answer: Nesting order matters.

Bracket stack with bounds

#include <stdio.h>
#include <stddef.h>
#define CAP 64
/* 1 balanced; 0 mismatch; -1 capacity exceeded.
   Other characters ignored; not a source-code parser. */
int balanced(const char *text) {
    char stack[CAP]; size_t count=0;
    for (size_t i=0;text[i]!='\0';++i) {
        char c=text[i];
        if (c=='(' || c=='[' || c=='{') {
            if (count==CAP) return -1;
            stack[count++]=c;
        } else if (c==')' || c==']' || c=='}') {
            if (count==0) return 0;
            char open=stack[--count];
            if ((c==')' && open!='(') ||
                (c==']' && open!='[') ||
                (c=='}' && open!='{')) return 0;
        }
    }
    return count==0;
}
int main(void) {
    const char *tests[]={"([{}])","([)]","", ")","(("};
    for (size_t i=0;i<5;++i)
        printf("\"%s\": %d\n",tests[i],balanced(tests[i]));
    char full[CAP+2];
    for (size_t i=0;i<CAP+1;++i) full[i]='(';
    full[CAP+1]='\0';
    printf("capacity: %d\n",balanced(full));
    return 0;
}

Checked output:

"([{}])": 1
"([)]": 0
"": 1
")": 0
"((": 0
capacity: -1

13. Infix and postfix conversion

Use an operator stack with precedence, associativity and parentheses. Unary operators require an explicit grammar.

Worked example: A+B*C becomes A B C * +; right-associative exponent must not pop equal precedence.
Exam question: Does one comparison handle every operator?
Answer: No. Equal-precedence behavior depends on associativity.

14. Postfix evaluation

Push operands. For binary operations pop right then left. Check arity, division and final stack size.

Worked example: 8 3 - 2 * gives 10.
Exam question: What remains after a valid expression?
Answer: Exactly one result without earlier underflow.

15. Circular queues

FIFO removes the oldest item. Wrap indices modulo capacity; count distinguishes empty from full.

Worked example: Capacity 3: add 10, 20, 30; remove 10; add 40; remove order 20, 30, 40.
Exam question: Why is front==rear ambiguous?
Answer: It can mean empty or full without a separate occupancy convention.

Fixed circular queue

#include <stdio.h>
#include <stddef.h>
#define CAP 3
typedef struct { int data[CAP]; size_t front,count; } Queue;
int enqueue(Queue *q,int value) {
    if (q->count==CAP) return 0;
    q->data[(q->front+q->count)%CAP]=value;
    ++q->count; return 1;
}
int dequeue(Queue *q,int *out) {
    if (q->count==0) return 0;
    *out=q->data[q->front];
    q->front=(q->front+1)%CAP; --q->count;
    return 1;
}
int main(void) {
    Queue q={{0},0,0}; int value=0;
    if (!enqueue(&q,10) || !enqueue(&q,20) || !enqueue(&q,30)) return 1;
    printf("full insert: %d\n",enqueue(&q,99));
    if (dequeue(&q,&value)) printf("first: %d\n",value);
    if (!enqueue(&q,40)) return 1;
    while (dequeue(&q,&value)) printf("next: %d\n",value);
    printf("empty remove: %d\n",dequeue(&q,&value));
    return 0;
}

Checked output:

full insert: 0
first: 10
next: 20
next: 30
next: 40
empty remove: 0

16. Deque and priority queue

Deque supports both ends. Priority queue removes by priority rather than arrival time.

Worked example: Urgent priority 1 can leave before older priority 5.
Exam question: Is a priority queue always FIFO?
Answer: No. Equal-priority order also needs a rule.

17. Recursion and stack space

A recursive algorithm needs progress and a base case. Count recursive frames as auxiliary storage.

Worked example: Recursive list traversal uses O(n) time and O(n) stack space.
Exam question: Is tail-call optimization guaranteed in C?
Answer: No.

18. Tree terms and height

Use height in edges: leaf 0, empty tree-1. A nonempty tree with n nodes has n-1 edges.

Worked example: Root with two leaves:3 nodes, 2 edges, height 1.
Exam question: Why state the height convention?
Answer: Some courses count nodes instead; formulas differ by one.

19. Binary tree traversals

At most two children. Preorder root-left-right; inorder left-root-right; postorder left-right-root; level order uses a queue.

Worked example: Root 8, left 3 with right 6, right 10: preorder 8, 3, 6, 10; inorder 3, 6, 8, 10; postorder 6, 3, 10, 8.
Exam question: Does inorder sort any binary tree?
Answer: Only if the BST ordering property holds.
83106Inorder: 3, 6, 8, 10
BST: 6 is right of 3, but in the left subtree of 8.

20. BST search and insertion

Smaller keys go left and larger keys right under a stated duplicate rule. Cost is O(h), not always O(log n).

Worked example: Insert 8, 3, 10, 6 gives sorted inorder 3, 6, 8, 10; sorted input can make a plain BST a chain.
Exam question: How are duplicates handled here?
Answer: The C demo ignores them; other APIs may keep counts.

21. BST deletion

Leaf: remove its link. One child: splice it in. Two children: use successor or predecessor, then delete that replacement node.

Worked example: Delete 8 using successor 10: root 10, left 3 with right 6; inorder 3, 6, 10.
Exam question: Is copying a key sufficient for record trees?
Answer: Move the associated record consistently with its ownership rule.

BST insert, delete and cleanup

#include <stdio.h>
#include <stdlib.h>
typedef struct Node { int key; struct Node *left,*right; } Node;
void clear(Node *p) {
    if (!p) return;
    clear(p->left); clear(p->right); free(p);
}
int insert(Node **root,int key) {
    if (!*root) {
        Node *p=malloc(sizeof *p);
        if (!p) return 0;
        *p=(Node){key,NULL,NULL}; *root=p; return 1;
    }
    if (key<(*root)->key) return insert(&(*root)->left,key);
    if (key>(*root)->key) return insert(&(*root)->right,key);
    return 1; /* duplicates ignored */
}
Node *erase(Node *p,int key) {
    if (!p) return NULL;
    if (key<p->key) p->left=erase(p->left,key);
    else if (key>p->key) p->right=erase(p->right,key);
    else {
        if (!p->left || !p->right) {
            Node *child=p->left ? p->left : p->right;
            free(p); return child;
        }
        Node *s=p->right;
        while (s->left) s=s->left;
        p->key=s->key; p->right=erase(p->right,s->key);
    }
    return p;
}
void inorder(const Node *p) {
    if (!p) return;
    inorder(p->left); printf("%d ",p->key); inorder(p->right);
}
int main(void) {
    Node *root=NULL; int keys[]={8,3,10,6,6};
    for (size_t i=0;i<5;++i) {
        if (!insert(&root,keys[i])) {
            clear(root); fputs("allocation failed\n",stderr); return 1;
        }
    }
    printf("before: "); inorder(root); putchar('\n');
    root=erase(root,8); root=erase(root,99);
    printf("after: "); inorder(root); putchar('\n');
    clear(root); return 0;
}

Checked output:

before: 3 6 8 10 
after: 3 6 10 

22. AVL and red-black trees

AVL keeps child-height difference at most one. Rotations keep inorder order. Red-black color rules keep logarithmic height.

Worked example: Insert 30, 20, 10 into AVL: right rotation gives root 20, children 10, 30.
Exam question: Is every BST balanced?
Answer: No. A plain BST does not repair imbalance.

23. Binary heaps

A min-heap is complete and each parent is no greater than its children. Zero-based children 2 i+1, 2 i+2; parent(i-1)/2 for i>0.

Worked example: [2, 5, 3, 9, 7] is a min-heap, not a sorted array.
Exam question: Operation costs?
Answer: Peek O(1), insert/extract O(log n), bottom-up build O(n).

24. B-trees, tries and threading

B-trees use multi-key nodes with occupancy bounds. Tries follow key symbols. Threaded-tree links may store inorder neighbors and need tags.

Worked example: cat and car share trie prefix ca, then branch.
Exam question: Can a thread be treated as a child?
Answer: No. Its tag distinguishes traversal links from children.

25. Hashing and load factor

Keys map to buckets; equal keys must hash consistently. Load factor alpha=n/m. Expected constant lookup needs hashing and load assumptions.

Worked example: 12 and 17 both map to 2 under modulo 5;4 keys/5 buckets givesalpha 0.8.
Exam question: Does a collision mean equality?
Answer: No. Compare actual keys.

26. Collision handling

Chaining stores bucket collections. Open addressing probes within the table. Deletion usually needs tombstones or a supported repair.

Worked example: Linear probing mod 5 for 12, 17, 22 uses 2, 3, 4. Deleting 12 cannot make search stop prematurely at 2.
Exam question: Worst-case lookup?
Answer: O(n) when collisions or probing require many inspections.

27. Elementary sorting and stability

Stable sorting preserves equal-key order. In-place usually means constant auxiliary storage, with call-stack treatment stated separately.

Worked example: Insert 3 into[2, 5, 8]: shift 8 and 5, then store 3 to get[2, 3, 5, 8].
Exam question: Is ordinary selection sort stable?
Answer: No. Swap-based selection is generally unstable; strict-shift insertion is stable.

28. Merge, quick and heap sort

Merge sort has O(n log n) worst time and typical array buffer O(n). Quicksort expected O(n log n) needs pivot/input assumptions; worst O(n squared). Heap sort worst O(n log n).

Worked example: Merge[1, 4] and[2, 3] into[1, 2, 3, 4]; left-on-tie merging preserves stability.
Exam question: Is quicksort always O(n log n)?
Answer: No. Repeated n-1 sized partitions give quadratic work.

29. Counting, radix and lower bounds

Counting sort costs O(n+k) for bounded integer range k. Radix uses stable digit passes. Comparison sorting has worst-case Omega(n log n) comparison lower bound.

Worked example: Count[2, 0, 2, 1] over 0..2 as[1, 1, 2], rebuild[0, 1, 2, 2].
Exam question: Why is counting faster than the comparison lower bound?
Answer: It uses values as indices rather than only comparisons.

30. Graph terms and representation

State directedness, weights and loop/parallel-edge rules. Matrix space O(V squared); adjacency lists O(V+E). Undirected edges appear twice in lists.

Worked example: A-B, A-C, B-D, C-D:4 vertices, 4 edges, 8 neighbor entries.
Exam question: Matrix edge-test cost?
Answer: O(1), but scanning neighbors costs O(V).

31. BFS and shortest paths

Use a queue and mark on discovery. Layers find shortest paths by edge count in unweighted graphs. Adjacency-list traversal O(V+E).

Worked example: Alphabetical neighbors: visitA, B, C, D; shortest A-B-D has 2 edges.
Exam question: Does BFS minimize arbitrary weighted cost?
Answer: No. Its guarantee applies to unweighted or equal-weight edges.
Layer 0: ALayer 1: B, CLayer 2: DE unreachable from A
BFS layers for the sample graph; E is a separate component.

BFS path and DFS forest

#include <stdio.h>
#define N 5
/* A-B,A-C,B-D,C-D; E isolated. Matrix representation. */
const int edge[N][N]={
    {0,1,1,0,0},{1,0,0,1,0},{1,0,0,1,0},
    {0,1,1,0,0},{0,0,0,0,0}
};
void bfs(int start,int dist[],int parent[]) {
    int queue[N],front=0,back=0;
    for (int i=0;i<N;++i) { dist[i]=-1; parent[i]=-1; }
    dist[start]=0; queue[back++]=start;
    while (front<back) {
        int u=queue[front++]; printf("%c ",'A'+u);
        for (int v=0;v<N;++v) {
            if (edge[u][v] && dist[v]==-1) {
                dist[v]=dist[u]+1; parent[v]=u;
                queue[back++]=v; /* marked before enqueue */
            }
        }
    }
}
void dfs(int u,int seen[]) {
    seen[u]=1; printf("%c ",'A'+u);
    for (int v=0;v<N;++v) if (edge[u][v] && !seen[v]) dfs(v,seen);
}
void print_path(int v,const int parent[]) {
    if (parent[v]!=-1) print_path(parent[v],parent);
    printf("%c ",'A'+v);
}
int main(void) {
    int dist[N],parent[N],seen[N]={0};
    printf("BFS: "); bfs(0,dist,parent); putchar('\n');
    printf("A to D: "); print_path(3,parent); putchar('\n');
    printf("distance D: %d; E: %d\n",dist[3],dist[4]);
    printf("DFS forest: ");
    for (int u=0;u<N;++u) if (!seen[u]) dfs(u,seen);
    putchar('\n'); return 0;
}

Checked output:

BFS: A B C D 
A to D: A B D 
distance D: 2; E: -1
DFS forest: A B D C E 

Representation caveat: this small runnable example uses an adjacency matrix and scans every possible neighbor, so its traversal is O(V squared), not the O(V+E) adjacency-list bound. Helper functions assume a valid vertex 0..N-1. Call print_path only for a reachable target, otherwise it would print that target alone rather than indicate no path.

32. DFS and disconnected graphs

Use recursion or a stack with visited state. Restart from unvisited vertices to cover every component.

Worked example: Alphabetical recursive DFS visitsA, B, D, C; isolatedE needs another start.
Exam question: Why can a traversal loop forever?
Answer: Without visited state, a cycle can revisit vertices indefinitely.

33. DAGs and topological order

A directed acyclic graph admits an order where every edge goes forward. Kahn removes zero-indegree vertices; fewer than V removals signals a cycle.

Worked example: A->B, A->C, B->D, C->D permitsA, B, C, D or A, C, B, D.
Exam question: Is the order unique?
Answer: Not generally; multiple ready vertices permit alternatives.

34. Weighted paths and spanning trees

Usual Dijkstra needs nonnegative weights. Bellman-Ford allows negative edges and detects reachable negative cycles. Prim/Kruskal solve connected undirected weighted MST.

Worked example: AB=1, AC=4, BC=2: MST usesAB, BC, total 3. ShortestA-to-C also costs 3 here, but tasks differ.
Exam question: Disconnected graph?
Answer: There is no all-vertex spanning tree; compute a minimum spanning forest.

35. Testing and choosing structures

Choose by operations, ordering, capacity and memory. Test invariants and boundary cases. Assertions are test checks, not production validation.

Worked example: Test empty, single, duplicates, full, missing, sorted/reverse input, cycles and disconnected vertices.
Exam question: How should you explain a bug?
Answer: Broken invariant, smallest failing input, expected/actual result and checked fix.

36. Practice answers and revision

State contracts and case qualifiers before quoting complexity. Use a small trace instead of slogans.

Worked example: Push 2, 5 then pop twice leaves empty; sample BST inorder 3, 6, 8, 10; modulo 5 collision bucket 2; shortest sample path 2 edges.
Exam question: Does this certify the full assessed syllabus?
Answer: No. Compare this common-core guide against your course outline and extra topics.

Operation-cost reference

OperationCostCondition
Array indexO(1)Middle insert/delete O(n)
Dynamic array appendAmortized O(1)Individual resize O(n)
Known-node singly spliceO(1)Finding node/predecessor may be O(n)
Fixed stack / circular queueO(1)Check capacity and empty state
BST search/insert/deleteO(h)Balanced O(log n); chain O(n)
Hash lookupExpected O(1)Hash/load assumptions; worst O(n)
Heap insert/extractO(log n)Peek O(1); build O(n)
BFS / DFS adjacency listsO(V+E)Full traversal; auxiliary O(V)
BFS / DFS matrixO(V squared)All possible neighbors scanned

Sorting entries refer to the stated standard variants; k is key-range size. Quicksort expected time needs pivot/input assumptions. Stability belongs to an implementation, not the name alone.

Sorting reference

SortBestWorstAuxiliary spaceStable?
Bubble, early-stopO(n)O(n squared)O(1)Yes, strict swap
Selection, ordinaryO(n squared)O(n squared)O(1)No
InsertionO(n)O(n squared)O(1)Yes, strict shift
Merge, arrayO(n log n)O(n log n)O(n)Yes, left on ties
Quick, ordinaryO(n log n) balancedO(n squared)O(log n) typical stack; O(n) worstNo
HeapO(n log n) boundO(n log n)O(1) iterativeNo
CountingO(n+k)O(n+k)O(n+k) stable versionYes, stable variant

Revision checklist

  1. Trace mutations without losing links.
  2. State ordering, duplicate and capacity contracts.
  3. Separate amortized, expected and worst-case costs.
  4. Explain BST deletion and rotations with small traces.
  5. Trace expression operand order, queue wrap and graph visited state.
  6. Keep actual test evidence, including failed results.

Practice resources

Use the Data Structures Lab File, Lab Files index and Online Compiler: choose C.

Sources

Textbook references support definitions and cost qualifiers. Explanations, fixed examples and six programs are original teaching material.

Comments