Home Wiki Programming & Logic Data Structures for Industrial Applications
Programming & Logic

Data Structures for Industrial Applications

What Are Data Structures and Why Do Engineers Need Them?

Imagine a warehouse with thousands of parts thrown in randomly -- finding a single part would take hours. But if you organize them in numbered shelves by type and size, you find anything in seconds.

A data structure is the same idea applied to computer memory -- a way to organize data so it can be accessed and processed as efficiently as possible. Choosing the right structure is the difference between a monitoring system that responds in milliseconds and one that freezes on every alarm.

Array: Sequential Storage

An array is the simplest data structure -- elements stored contiguously in memory, each accessible by an index starting from zero.

Industrial use case: A circular buffer storing the most recent sensor readings to calculate a moving average.

# Circular buffer for last 10 temperature readings
temp_buffer = [0.0] * 10  # fixed-size array
write_index = 0

def add_reading(value):
    global write_index
    temp_buffer[write_index % 10] = value
    write_index += 1

def moving_average():
    count = min(write_index, 10)
    return sum(temp_buffer[:count]) / count if count > 0 else 0

# Add readings
for temp in [78.5, 79.1, 80.3, 77.8, 81.2]:
    add_reading(temp)

print(f"Moving average: {moving_average():.1f}°C")
Operation Time Complexity
Access by index O(1) -- instant
Search for value O(n) -- linear
Append to end O(1)
Insert at beginning O(n) -- slow

Linked List: Flexible Insertions and Deletions

A linked list is a chain of nodes, each containing data and a pointer to the next node. Nodes do not need contiguous memory -- each can live anywhere in the heap.

Industrial use case: An event log that changes size constantly -- fast insertions and deletions without shifting elements.

class EventNode:
    def __init__(self, timestamp, event_type, message):
        self.timestamp = timestamp
        self.event_type = event_type
        self.message = message
        self.next = None

class EventLog:
    def __init__(self):
        self.head = None
        self.count = 0

    def add_event(self, timestamp, event_type, message):
        new_node = EventNode(timestamp, event_type, message)
        new_node.next = self.head
        self.head = new_node  # newest event at the front
        self.count += 1

    def get_recent(self, n=5):
        events = []
        current = self.head
        while current and len(events) < n:
            events.append(f"[{current.timestamp}] {current.event_type}: {current.message}")
            current = current.next
        return events

# Usage
log = EventLog()
log.add_event("14:30:05", "ALARM", "CNC-01 temperature high")
log.add_event("14:30:12", "ACTION", "Speed reduced")
log.add_event("14:31:00", "INFO", "Temperature normalized")

Array vs Linked List comparison:

Criterion Array Linked List
Access by index O(1) fast O(n) slow
Insert/delete at front O(n) slow O(1) fast
Memory usage Lower Higher (pointers)
Fixed vs dynamic size Usually fixed Easily dynamic

Hash Map: Instant Lookup

Imagine a cabinet with 1,000 drawers, and you have a magic key that tells you exactly which drawer to open. That is a HashMap -- it maps a key to a value and finds any element instantly.

Industrial use case: Mapping a machine ID to its current status -- when an alarm arrives from a specific machine, you retrieve its data immediately.

# Current status of every machine on the floor
machine_status = {
    "CNC-01": {"temp": 78.5, "status": "running", "alarms": 0},
    "CNC-02": {"temp": 91.2, "status": "warning", "alarms": 3},
    "PUMP-05": {"temp": 65.0, "status": "idle", "alarms": 0},
    "COMP-03": {"temp": 82.1, "status": "running", "alarms": 1},
}

# Instant access to a machine's status
machine = "CNC-02"
info = machine_status[machine]  # O(1) - instant
print(f"{machine}: temp {info['temp']}°C - {info['status']}")

# Update status
machine_status["CNC-02"]["alarms"] += 1

# Find all machines in warning state
warnings = {k: v for k, v in machine_status.items() if v["status"] == "warning"}
Operation Time Complexity
Lookup by key O(1) -- instant
Insert O(1)
Delete O(1)
Search by value O(n) -- linear

Queue: First In, First Out

A queue follows the FIFO principle (First In, First Out) -- just like a production order queue: the first order submitted is the first order processed.

Industrial use case: An alarm queue that ensures alerts are handled in the order they arrive, so nothing gets lost.

from collections import deque

class AlarmQueue:
    def __init__(self, max_size=100):
        self.queue = deque(maxlen=max_size)

    def push_alarm(self, machine_id, severity, message):
        alarm = {
            "machine": machine_id,
            "severity": severity,  # "low", "medium", "high", "critical"
            "message": message,
            "acknowledged": False
        }
        self.queue.append(alarm)

    def process_next(self):
        if self.queue:
            alarm = self.queue.popleft()  # oldest alarm first
            print(f"Processing: [{alarm['severity']}] {alarm['machine']}: {alarm['message']}")
            return alarm
        return None

    def pending_count(self):
        return len(self.queue)

# Usage
alarms = AlarmQueue()
alarms.push_alarm("CNC-01", "high", "Temperature elevated")
alarms.push_alarm("PUMP-05", "critical", "Pressure too low")
alarms.push_alarm("CONV-02", "low", "Belt needs maintenance")

print(f"Pending alarms: {alarms.pending_count()}")
while alarms.pending_count() > 0:
    alarms.process_next()

Stack: Last In, First Out

A stack follows the LIFO principle (Last In, First Out) -- like a stack of plates: the last plate placed on top is the first one you pick up.

Industrial use case: Undo operations in control interfaces, or tracking machine state history.

class MachineStateStack:
    """Track machine state history for undo capability"""
    def __init__(self):
        self.stack = []

    def save_state(self, state_dict):
        self.stack.append(state_dict.copy())

    def undo(self):
        if self.stack:
            return self.stack.pop()  # most recent state
        return None

    def peek(self):
        """View the latest state without removing it"""
        return self.stack[-1] if self.stack else None

# Usage: operator changing CNC settings
history = MachineStateStack()

# Initial state
history.save_state({"speed": 1200, "feed": 0.15, "depth": 2.0})

# Operator changes speed
history.save_state({"speed": 1500, "feed": 0.15, "depth": 2.0})

# Operator changes depth -- bad results!
history.save_state({"speed": 1500, "feed": 0.15, "depth": 3.5})

# Undo last change
previous = history.undo()
print(f"Reverted to: speed={previous['speed']}, depth={previous['depth']}")

Tree: Hierarchical Organization

A tree is a hierarchical structure -- each node has a parent (except the root) and may have children. Ideal for representing hierarchical relationships.

Industrial use case: Factory structure (departments, production lines, machines), or decision trees for fault diagnosis.

class FactoryNode:
    def __init__(self, name, node_type):
        self.name = name
        self.node_type = node_type  # "factory", "department", "line", "machine"
        self.children = []

    def add_child(self, child):
        self.children.append(child)
        return child

    def display(self, indent=0):
        prefix = "  " * indent + ("|- " if indent > 0 else "")
        print(f"{prefix}[{self.node_type}] {self.name}")
        for child in self.children:
            child.display(indent + 1)

# Build factory hierarchy
factory = FactoryNode("Dr.Machine Factory", "factory")

dept_mech = factory.add_child(FactoryNode("Machining Department", "department"))
line_cnc = dept_mech.add_child(FactoryNode("CNC Line", "line"))
line_cnc.add_child(FactoryNode("CNC-01 (Lathe)", "machine"))
line_cnc.add_child(FactoryNode("CNC-02 (Mill)", "machine"))

dept_assembly = factory.add_child(FactoryNode("Assembly Department", "department"))
line_a = dept_assembly.add_child(FactoryNode("Assembly Line A", "line"))
line_a.add_child(FactoryNode("Robotic Welding Station", "machine"))
line_a.add_child(FactoryNode("Visual Inspection Station", "machine"))

factory.display()

When to Use Each Structure

Structure Best Industrial Use Access Complexity
Array Sensor reading buffer O(1) by index
Linked List Dynamic-size event log O(n) search
HashMap Machine ID to status mapping O(1) by key
Queue Alarm or production order queue O(1) enqueue/dequeue
Stack Undo operations O(1) push/pop
Tree Factory hierarchy O(log n) search

Choosing the right data structure is a genuine engineering decision -- it affects system speed, memory consumption, and maintainability. Take the time to understand each structure and you will naturally pick the best fit for every situation.

data-structures array hash-map queue stack tree هياكل البيانات المصفوفة القائمة المتصلة جدول التجزئة الطابور المكدس