Planificación de Procesos (C++)
Tags: devops, cpp, algorithms, spanish
Published: 2024-04-22 20:41:38



Se presenta un programa para simular el comportamiento de planificación de procesos, lenguaje de programación c++.

Se trata de una lista enlazada que el usuario construye al inicio del programa, indicando el número de procesos totales a trabajar y posteriormente asignarles un nombre, tiempo de procesamiento y prioridad.

Contiene un menú de 1 a 6 opciones que permite explorar en cada uno de las 4 Planificaciones de procesos: First In First Out, Smaller Job First, Round Robin y Prioridad Dinámica; también una opción para mostrar la información ingresada al inicio del programa y la opción para salir.

El programa está comentado y se ejecuta en Español.

@imnotleo 

*************************

Here we have a program to simulate the behavior of process planning, C++ programming language.

With a linked list that the user builds at the beginning of the program, indicating the number of total processes to work on and subsequently assigning them a name, processing time and priority.

Playing with a menu of 1 to 6 options that allows you to explore each of the 4 Process Plans: First In First Out, Smaller Job First, Round Robin and Dynamic Priority; also an option to show the information entered at the start of the program and the option to exit.

The program is commented and runs in Spanish.

@imnotleo 

*************************

main.cpp

```
/*
AUTOR:    Leobardo Vázquez 
CURSO:    Sistemas Operativos
PROGRAMA: Planificación de Procesos
FECHA:    19 de Abril del 2024
*/

#include <iostream>
#include "so.hpp"

int main(){                                         // main.cpp
    
 int n, op;                                         // n: número de procesos, op: opción ingresada por el usuario.
    cout << "\n\t Planificacion de procesos - Sistemas Operativos"; // Títulos.
    cout << "\n\n\tIngrese el numero total de procesos a trabajar: "; // Solicita cantidad de procesos a trabajar antes de iniciar el programa.
    while (!(cin >> n)) {                           // Se usa un ciclo en caso de que n no sea un número entero.
        cin.clear();                                // Se limpia el espacio del carácter erróneo ingresado por el usuario.
        cin.ignore(100, '\n');                      // Se indica que ignore lo que ingresó el usuario con un límite de 100 carácteres, y un salto de línea.
        system("cls");                              // Se limpia la pantalla.
        cout << "\n\tError: Entrada invalida. \n\tPor favor, ingrese un numero entero para el total de procesos: "; // Se solicita nuevamente un número entero.
    }
    system("cls");                                  // Se limpia la pantalla.
    process so(n);                                  // Se crea lista enlazada llamada 'so' de capacidad n.
    so.addProcess();                                // Se solicita a usuario agregar los n procesos.
    system("cls");                                  // Se limpia la pantalla.
    so.print();                                     // Imprime los procesos guardados en la lista 'so'.
    do {
    so.Menu();                                      // Imprime el menú de opciones a calcular con los procesos de 'so'.
    while (!(cin >> op)) {                          // Se usa un ciclo en caso de que op no sea un número entero.
        cin.clear();                                // Se limpia el espacio del carácter erróneo ingresado por el usuario.
        cin.ignore(100, '\n');                      // Se indica que ignore lo que ingresó el usuario con un límite de 100 carácteres, y un salto de línea.
        system("cls");                              // Se limpia la pantalla.
        cout << "\n\tError: Entrada invalida. \n\tPor favor, ingrese un numero entero para seleccionar proceso.\n\n"; // Se solicita nuevamente un número entero.
        so.Menu();                                  // Imprime el menú de opciones a calcular con los procesos de 'so'.
    }
    system("cls");                                  // Se limpia la pantalla.
    switch(op){                                     // Se usa un switch para navegar en las opciones del 1 al 6.
    case 1:                                         // Caso 1.
    so.FIFO();                                      // FIFO (Primera Entrada, Primera Salida).
    break;
    case 2:                                         // Caso 2.
    so.SJF();                                       // SJF (Tiempo mas corto primero).
    break;
    case 3:                                         // Caso 3.
    so.Prioridad();                                 // Prioridad Dinamica (Prioridad de mayor a menor usando Quantum).
    break;
    case 4:                                         // Caso 4.
    so.RoundRobin();                                // Round Robin (Primera Entrada, Primera salida usando Quantum).
    break;
    case 5:                                         // Caso 5.
    so.print();                                     // Imprime los procesos guardados en la lista 'so'.
    break;
    case 6:                                         // Caso 6.
    cout << "\n\tRecuerda que puedes volver a calcular cuando gustes." << endl; // Mensaje de despedida al salir del programa.
    break;
    default:
    cout << "\n\tIngresa una opcion valida." << endl; // Mensaje de error al ingresar un número entero mayor que 6.
    break;
    }
    } while (op != 6);                              // Se indica la salida del programa al seleccionar la opción 6.

return 0;
}


                                                    //http://dev.to/imnotleo/planificacion-de-procesos-c-3m5k


```

*************************

so.cpp

```
#include "so.hpp"

  process::node::node(string i, int t, int q) {       // Se declara nodo: String para ID y Enteros para tiempo y prioridad. 
      _id = i;
      _time = t;
      _priority = q;
      _next = nullptr;                                // Inicia apuntador next en vacío.
  }

  process::process(int c){                            // Se construye lista enlazada vacía y se especifica su capacidad.

      n = c;
      head = nullptr;
      tail = nullptr;
  }

  process::~process(){                                // Destructor, se encarga de limpiar la memoria al término del programa.

      while(head != nullptr) {                        // Se recorre la lista original completa.
          node *p = head;                             // Se crea apuntador auxiliar en head.
          head = head -> next();                      // head avanza al siguiente nodo.
          delete p;                                   // Se elimina el nodo que apunta el auxiliar.
      }
  }


  void process::print(){                             // Muestra el contenido de la lista Original.

    cout << "\n\t Planificacion de procesos - Sistemas Operativos";
    cout << "\n\n\t Procesos registrados (ID // Tiempo // Prioridad)\n\n" << endl; // Títulos.
    cout << "\t";
      node *p = head;                               // Se crea apuntador para recorrer la lista original. 
      while(p != nullptr){                          // Se recorre la lista mostrando los procesos originales.
      cout << " | " << p -> id() << " " << p -> tme() << " " << p -> prty() << " | "; // Se imprimen los procesos restantes: ID, Tiempo y Prioridad de cada nodo.
      p = p -> next();                              // Se avanza en lo que resta de la lista.
      }
     cout << endl;                                  // Salto de línea.
}



void process::addProcess() {                         // Función para crear y organizar nodos en la lista Original, pidiendo los datos al usuario.

     for(int i = 0; i < n ; i++){                    // Se piden los n datos y se guardan en 3 variables: a, b y c.
        string a;
        int b, c;
        cout << "ID: ";
        cin >> a;                                   // Se guarda el ID.
        cout << "Tiempo: ";
        while (!(cin >> b)) {                       // Se usa un ciclo en caso de que b no sea un número entero.
        cin.clear();                                // Se limpia el espacio del carácter erróneo ingresado por el usuario.
        cin.ignore(100, '\n');                      // Se indica que ignore lo que ingresó el usuario con un límite de 100 carácteres, y un salto de línea.
        cout << "\n\tError: Entrada invalida. \n\tPor favor, ingrese un numero entero para el tiempo del proceso: "; // Se solicita nuevamente un número entero.
    }
        cout << "Prioridad: ";
        while (!(cin >> c)) {                       // Se usa un ciclo en caso de que c no sea un número entero.
        cin.clear();                                // Se limpia el espacio del carácter erróneo ingresado por el usuario.
        cin.ignore(100, '\n');                      // Se indica que ignore lo que ingresó el usuario con un límite de 100 carácteres, y un salto de línea.
        cout << "\n\tError: Entrada invalida. \n\tPor favor, ingrese un numero entero para la prioridad del proceso: "; // Se solicita nuevamente un número entero.
    }
        node *p = new node(a, b, c);                 // Se crea nodo con la información obtenida.
        if (empty()) {                               // Si la lista está vacía, head y tail apuntan al mismo nodo.
            head = p;
            tail = p;
      }else{                                         // Si la lista no está vacía, se forma el nuevo nodo después del último.
            tail -> next(p);
            tail = p;
        }
        s++;
 cout << "\n\tProceso agregado." << endl;            // Confirmación: proceso agregado correctamente.
}
}


void process::Menu() {                               // Se muestra el menú de opciones para seleccionar.

     cout << "\n\t\tMENU DE PROCESOS\n" << endl;
     cout << "\t1. FIFO" << endl;
     cout << "\t2. SJF" << endl;
     cout << "\t3. Prioridad (Dinamica)" << endl;
     cout << "\t4. Round-Robin" << endl;
     cout << "\t5. Ver procesos registrados" << endl;
     cout << "\t6. Salir" << endl;

     cout << "\n\tIngrese su opcion: ";             // Se solicita indicación de usuario.

}



int process::calcQ() {                              // Función para calcular Quantum.

    int x = 0;                                      // Se inicializa contador en 0.
      node *p = head;                               // Se crea nuevo apuntador para recorrer la lista.
      while(p != nullptr) {                         // Se recorre la lista completa.
          x += p -> tme();                          // Se suman los tiempos de todos los nodos.
          p = p -> next();                          // El apuntador avanza al siguiente nodo.
      }
    return x/n;                                     // Se calcula el Quantum dividiendo la suma total entre el número de nodos.
}

  void process::FIFO() {                            // Función para primeras entradas, primeras salidas.

    cout << "\n\t Planificacion de procesos - Sistemas Operativos"; // Títulos.
    cout << "\n\n\t FIFO (Primera Entrada, Primera Salida)\n" << endl;
                                                    // Se genera copia de la lista original para no afectar los datos.
        node *c_head = nullptr;                     // Inicia apuntador copia de head en vacío.
        node *c_tail = nullptr;                     // Inicia apuntador copia de tail en vacío.
      node *p = head;                               // Se crea nuevo apuntador para recorrer la lista original.

        while (p != nullptr) {                      // Se recorre la lista original completa.

            node *r = new node(p -> id(), p -> tme(), p -> prty()); // Se crea nuevo nodo copiando la información de la lista original.
            if (c_head == nullptr) {                // Si la copia de la lista está vacía, head y tail apuntan al mismo nodo.
                c_head = r;
                c_tail = r;
            } else {                                // Si la copia de la lista no está vacía, se forma el nuevo nodo después del último.
                c_tail -> next(r);
                c_tail = r;
            }
            p = p -> next();                        // El apuntador avanza al siguiente nodo.
        }
                                                    // Se calcula FIFO. 
      float tR = 0, tRT = 0;                        // Se declaran contadores flotantes para Tiempo de Respuesta y Tiempo de Respuesta Total.
      cout << "\n\tId //" << " Tiempo de ejecucion //" << " Tiempo de retorno //"<< " Procesos restantes (ID Tiempo)" << endl; // Títulos.
      p = c_head;                                   // Se apunta al head de la copia de la lista.
      while (p != nullptr) {                        // Se recorre la copia de la lista completa

          tR += p -> tme();                         // Se suma el tiempo de respuesta de cada nodo.
          tRT += tR;                                // El tiempo de respuesta se suma al tiempo de respuesta total.
          cout << "\t"<< p -> id() << "\t\t"<< p -> tme()<< "\t\t"<< tR<< "\t\t"; // Se muestra el ID, el tiempo del nodo y el tiempo de respuesta.
          node *t = p -> next();                    // Se genera nuevo nodo para recorrer el restante de la lista y así graficar.
      while(t != nullptr){                          // Se recorre el resto de la lista mostrando los procesos restantes.
      cout << " | " << t -> id() << " " << t -> tme() << " | "; // Se imprimen los procesos restantes: ID y Tiempo de cada nodo.
      t = t -> next();                              // Se avanza en lo que resta de la graficación de la lista.
            }
          cout << endl;                             // Salto de línea.
          p = p -> next();                          // El apuntador avanza al siguiente nodo.
      }
      while (c_head != nullptr) {                   // Se recorre la copia de la lista para eliminarla.
          node *xd = c_head;                        // Se crea apuntador auxiliar en el principio de la copia de la lista (c_head).
          c_head = c_head -> next();                // El c_head avanza al siguiente nodo.
          delete xd;                                // Se elimina el nodo auxiliar, limpiando la memoria.
      }
      cout << "\n\tTiempo promedio: "<< (float)tRT/n<< endl; // Calcula y muestra el tiempo promedio.
  }

  void process::SJF() {                             // Se genera copia de la lista original para no afectar los datos.
        node *c_head = nullptr;                     // Inicia apuntador copia de head en vacío.
        node *c_tail = nullptr;                     // Inicia apuntador copia de tail en vacío.
        node *p = head;                             // Se crea nuevo apuntador para recorrer la lista original.

        while (p != nullptr) {                      // Se recorre la lista original completa.

            node *r = new node(p -> id(), p -> tme(), p -> prty()); // Se crea nuevo nodo copiando la información de la lista original.
            if (c_head == nullptr) {                // Si la copia de la lista está vacía, head y tail apuntan al mismo nodo.
                c_head = r;
                c_tail = r;
            } else {                                // Si la copia de la lista no está vacía, se forma el nuevo nodo después del último.
                c_tail -> next(r);
                c_tail = r;
            }
            p = p -> next();                        // El apuntador avanza al siguiente nodo.
        }
        p = c_head;                                 // Se apunta al head de la copia de la lista.
      while (p != nullptr) {                        // Se usa un ciclo para recorrer la lista organizando tiempo de menor a mayor.
          node *q = p -> next();                    // Se crea un apuntador después del actual para comparar los tiempos entre procesos.
          while (q != nullptr) {                    // Se usa un ciclo para recorrer la lista con el nuevo apuntador.

              if (q -> tme() < p -> tme()) {        // Se compara si el apuntador siguiente es menor que el apuntador actual, se ejecuta el ciclo.

                  string idx = p -> id();           // Se usan auxiliares para guardar la información del apuntador actual e intercambiarla.
                  int tmex = p -> tme();
                  int prtyx = p -> prty();

                  p -> setid(q -> id());            // Se cambia el nodo actual por el nodo siguiente.
                  p -> settme(q -> tme());
                  p -> setprty(q -> prty());

                  q -> setid(idx);                  // Se guardan en el nodo siguiente los datos del nodo actual.
                  q -> settme(tmex);
                  q -> setprty(prtyx);

              }
              q = q -> next();                      // El apuntador siguiente avanza al próximo nodo.
          }
          p = p -> next();                          // El apuntador actual avanza al próximo nodo.
      }

    cout << "\n\t Planificacion de procesos - Sistemas Operativos";
    cout << "\n\n\t SJF (Tiempo mas corto primero)\n" << endl;
    node *z = c_head;                               // Se crea un apuntador para usar la copia de la lista.
      float tR = 0, tRT = 0;                        // Se declaran contadores flotantes para Tiempo de Respuesta y Tiempo de Respuesta Total.
      cout << "\n\tId //" << " Tiempo de ejecucion //" << " Tiempo de retorno //"<< " Procesos restantes (ID Tiempo)" << endl;
      while (z != nullptr) {                        // Se recorre la copia de la lista completa
          tR += z -> tme();                         // Se suma el tiempo de respuesta de cada nodo.
          tRT += tR;                                // El tiempo de respuesta se suma al tiempo de respuesta total.
          cout << "\t"<< z -> id() << "\t\t"<< z -> tme()<< "\t\t"<< tR<< "\t\t"; // Se muestra el ID, el tiempo del nodo y el tiempo de respuesta.
          node *t = z -> next();                    // Se genera nuevo apuntador para recorrer el restante de la lista y así graficar.
      while(t != nullptr){                          // Se recorre el resto de la lista mostrando los procesos restantes.
      cout << " | " << t -> id() << " " << t -> tme() << " | "; // Se muestran los procesos restantes: ID y Tiempo de cada nodo.
      t = t -> next();                              // Se avanza en lo que resta de la graficación de la lista.
            }
          cout << endl;                             // Salto de línea.
          z = z -> next();                          // El apuntador avanza al siguiente nodo.
      }
      while (c_head != nullptr) {                   // Se recorre la copia de la lista para eliminarla.
          node *xd = c_head;                        // Se crea apuntador auxiliar en el principio de la copia de la lista (c_head).
          c_head = c_head -> next();                // El c_head avanza al siguiente nodo.
          delete xd;                                // Se elimina el nodo auxiliar, limpiando la memoria.
      }
      cout << "\n\tTiempo promedio: "<< (float)tRT/n<< endl; // Calcula y muestra el tiempo promedio.
  }

  void process::Prioridad() {                       // Se genera copia de la lista original para no afectar los datos.
      node *c_head = nullptr;                       // Inicia apuntador copia de head en vacío.
        node *c_tail = nullptr;                     // Inicia apuntador copia de tail en vacío.
        node *p = head;                             // Se crea nuevo apuntador para recorrer la lista original.

        while (p != nullptr) {                      // Se recorre la lista original completa.

            node *r = new node(p -> id(), p -> tme(), p -> prty()); // Se crea nuevo nodo copiando la información de la lista original.
            if (c_head == nullptr) {                // Si la lista está vacía, head y tail apuntan al mismo nodo.
                c_head = r;
                c_tail = r;
            } else {                                // Si la lista no está vacía, se forma el nuevo nodo después del último.
                c_tail -> next(r);
                c_tail = r;
            }
            p = p -> next();                        // El apuntador se avanza al siguiente nodo.
        }
        p = c_head;                                 // Se crea un apuntador para organizar la copia de la lista.
      while (p != nullptr) {                        // Se usa un ciclo para recorrer la lista organizando prioridad de mayor a menor.
          node *q = p -> next();                    // Se crea un apuntador después del actual para comparar las prioridades entre procesos.
          while (q != nullptr) {                    // Se usa un ciclo para recorrer la lista con el nuevo apuntador.

              if (q -> prty() > p -> prty()) {      // Se compara si el apuntador siguiente es mayor que el apuntador actual, se ejecuta el ciclo.

                  string idx = p -> id();           // Se usan auxiliares para guardar la información del apuntador actual e intercambiarla.
                  int tmex = p -> tme();
                  int prtyx = p -> prty();

                  p -> setid(q -> id());            // Se cambia el nodo actual por el nodo siguiente.
                  p -> settme(q -> tme());
                  p -> setprty(q -> prty());

                  q -> setid(idx);                  // Se guardan en el nodo siguiente los datos del nodo actual.
                  q -> settme(tmex);
                  q -> setprty(prtyx);

              }
              q = q -> next();                      // El apuntador siguiente avanza al próximo nodo.
          }
          p = p -> next();                          // El apuntador actual avanza al próximo nodo.
      }

    cout << "\n\t Planificacion de procesos - Sistemas Operativos"; // Títulos.
    cout << "\n\n\t Prioridad Dinamica (Prioridad de mayor a menor usando Quantum)\n" << endl;
      node *r = c_head;                             // Se crea un apuntador para usar la copia de la lista.
      float tR = 0, tRT = 0;                        // Se declaran contadores flotantes para Tiempo de Respuesta y Tiempo de Respuesta Total.
      int Q = calcQ();                              // Se guarda el número Quantum en la variable Q.
      cout << "\n\tId //" << " Tiempo de ejecucion //" << " Prioridad //" << " Tiempo de retorno //" << " Procesos restantes (ID Tiempo Prioridad)" << endl;
      while (r != nullptr) {                        // Se recorre la copia de la lista completa

            if (r -> tme() <= Q) {                  // Si el tiempo del proceso es igual o menor al Quantum, se ejecuta el proceso.
          tR += r -> tme();                         // Se suma el tiempo de respuesta de cada nodo.
          tRT += tR;                                // El tiempo de respuesta se suma al tiempo de respuesta total.
          cout << "\t"<< r -> id() << "\t\t"<< r -> tme()<< "\t\t"<< r -> prty()<< "\t\t"<< tR<< "\t\t"; // Se muestra el ID, el tiempo del nodo, su prioridad y el tiempo de respuesta.
          node *t = r -> next();                    // Se genera nuevo apuntador para recorrer el restante de la lista y así graficar.
      while(t != nullptr){                          // Se recorre el resto de la lista mostrando los procesos restantes.
      cout << " | " << t -> id() << " " << t -> tme() << " " << t -> prty() << " | "; // Se muestran los procesos restantes: ID, prioridad y Tiempo.
      t = t -> next();                              // Se avanza en lo que resta de la graficación de la lista.
            }
          cout << endl;                             // Salto de línea.
          r = r -> next();                          // El apuntador avanza al siguiente nodo.
            }else{                                  // Si el tiempo del proceso es mayor al Quantum, se suma Q al tiempo de respuesta acumulado, se le resta 1 en prioridad y Q en tiempo, y se forma despues del ultimo nodo con esa prioridad.
            tR += Q;                                // Se suma el Quantum al tiempo de respuesta.
            cout << "\t"<< r -> id() << " pendiente     "<< r -> tme()<< "\t\t"<< r -> prty()<< "\t\t"<< tR<< "\t\t"; // Se muestra el ID del proceso pendiente, el tiempo del nodo, su prioridad y el tiempo de respuesta acumulado.
            r -> settme(r -> tme() - Q);            // Se le resta el tiempo de Quantum al tiempo de respueta del proceso.
            r -> setprty(r -> prty() - 1);          // Se le resta 1 a la prioridad.
            node *t2 = r;                           // Se genera nuevo apuntador para reubicar el nodo en la lista, al último del nodo con su misma prioridad.
        while (t2->next() != nullptr && t2->next()->prty() >= r->prty()) { // Mientras exista un nodo siguiente y sea mayor o igual que el nodo actual...
            t2 = t2->next();                        // El apuntador avanza al próximo nodo.
        }
        if (t2 != r) {                              // Si el ultimo apuntador no es el nodo actual, se intercambian.
            node *temp = r->next();                 // Se guarda el puntero al siguiente nodo del primer nodo en temp.
            r->next(t2->next());                    // Se establece el siguiente nodo del primer nodo como el siguiente nodo del último nodo (t2->next()).
            t2->next(r);                            // Se establece el siguiente nodo del último nodo como el primer nodo (r).
            r = temp;                               // Se actualiza r para que apunte al segundo nodo de la lista.
        } else {                                    // Si el apuntador buscador es el nodo actual, avanza.
            r = r->next();                          // El apuntador avanza al siguiente nodo.
        }
        node *t = r;                                // Se genera nuevo apuntador para recorrer el restante de la lista y así graficar.
      while(t != nullptr){                          // Se recorre el resto de la lista mostrando los procesos restantes.
      cout << " | " << t -> id() << " " << t -> tme() << " " << t -> prty() << " | "; // Se muestran los procesos restantes: ID, tiempo y prioridad.
      t = t -> next();                              // El apuntador avanza al siguiente nodo.
            }
            cout << endl;                           // Salto de línea.
            }
      }
      while (c_head != nullptr) {                   // Se recorre la copia de la lista para eliminarla.
          node *xd = c_head;                        // Se crea apuntador auxiliar en el principio de la copia de la lista (c_head).
          c_head = c_head -> next();                // El c_head avanza al siguiente nodo.
          delete xd;                                // Se elimina el nodo auxiliar, limpiando la memoria.
      }
      cout << "\n\tTiempo promedio: "<< (float)tRT/n<< endl; // Se calcula tiempo promedio dividiendo el tiempo de respuesta total entre el número de procesos.
      cout << "\n\tQuantum: "<< Q<< endl;           // Se muestra el número Quantum trabajado.
  }

  void process::RoundRobin() {

    cout << "\n\t Planificacion de procesos - Sistemas Operativos"; // Títulos.
    cout << "\n\n\t Round Robin (Primera Entrada, Primera salida usando Quantum)\n" << endl;
                                                    // Se genera copia de la lista original para no afectar los datos.
      node *c_head = nullptr;                       // Inicia apuntador copia de head en vacío.
        node *c_tail = nullptr;                     // Inicia apuntador copia de tail en vacío.
        node *r = head;                             // Se crea nuevo apuntador para recorrer la lista original.

        while (r != nullptr) {                      // Se recorre la lista original completa.

            node *m = new node(r -> id(), r -> tme(), r -> prty()); // Se crea nuevo nodo copiando la información de la lista original.
            if (c_head == nullptr) {                // Si la lista está vacía, head y tail apuntan al mismo nodo.
                c_head = m;
                c_tail = m;
            } else {                                // Si la lista no está vacía, se forma el nuevo nodo después del último.
                c_tail -> next(m);
                c_tail = m;
            }
            r = r -> next();                        // El apuntador se avanza al siguiente nodo.
        }
                                                    // Se calcula Round Robin
      r = c_head;                                   // Se apunta al head de la copia de la lista organizada.
      float tR = 0, tRT = 0;                        // Se declaran contadores flotantes para Tiempo de Respuesta y Tiempo de Respuesta Total.
      int Q = calcQ();                              // Se guarda el número Quantum en la variable Q.
      cout << "\n\tId //" << " Tiempo de ejecucion //" << " Tiempo de retorno //" << " Procesos restantes (ID Tiempo)" << endl; // Títulos.
      while (r != nullptr) {                        // Se recorre la copia de la lista completa.
        if (r -> tme() <= Q) {                      // Si el tiempo del proceso es igual o menor al Quantum, se ejecuta el proceso.
          tR += r -> tme();                         // Se suma el tiempo de respuesta de cada nodo.
          tRT += tR;                                // El tiempo de respuesta se suma al tiempo de respuesta total.
          cout << "\t"<< r -> id() << "\t\t"<< r -> tme()<< "\t\t"<< tR<< "\t\t"; // Se muestra el ID, el tiempo del nodo y el tiempo de respuesta.
          node *t = r -> next();                    // Se genera nuevo apuntador para recorrer el restante de la lista y así graficar.
      while(t != nullptr){                          // Se recorre el resto de la lista mostrando los procesos restantes.
      cout << " | " << t -> id() << " " << t -> tme()  << " | "; // Se muestran los procesos restantes: ID y Tiempo.
      t = t -> next();                              // Se avanza en lo que resta de la graficación de la lista.
            }
          cout << endl;                             // Salto de línea.
          r = r -> next();                          // El apuntador avanza al siguiente nodo.
            }else{                                  // Si el tiempo del proceso es mayor al Quantum, se suma Q al tiempo de respuesta acumulado, se le resta Q al nodo y se forma al último.
            tR += Q;                                // Se suma el Quantum al tiempo de respuesta.
            cout << "\t"<< r -> id() << " pendiente     "<< r -> tme()<< "\t\t"<< tR<< "\t\t"; // Se muestra el ID del proceso pendiente, el tiempo original del nodo y el tiempo de respuesta acumulado.
            r -> settme(r -> tme() - Q);            // Se resta el Quantum al tiempo del proceso.
            node *t2 = r;                           // Se genera nuevo apuntador buscador para reubicar el nodo al final de la lista.
        while (t2->next() != nullptr) {             // Se recorre la lista hasta el final.
            t2 = t2->next();                        // Avanza el apuntador en cada vuelta mientras exista siguiente nodo.
        }       
        if (t2 != r) {                              // Si el ultimo apuntador no es el nodo actual, se intercambian.
            node *temp = r->next();                 // Se guarda el puntero al siguiente nodo del primer nodo en temp.
            r->next(t2->next());                    // Se establece el siguiente nodo del primer nodo como el siguiente nodo del último nodo (t2->next()).
            t2->next(r);                            // Se establece el siguiente nodo del último nodo como el primer nodo (r).
            r = temp;                               // Se actualiza r para que apunte al segundo nodo de la lista.
        }
        node *t = r;                                // Se genera nuevo apuntador para recorrer el restante de la lista y así graficar.
      while(t != nullptr){                          // Se recorre el resto de la lista mostrando los procesos restantes.
      cout << " | " << t -> id() << " " << t -> tme() << " | "; // Se muestran los procesos restantes: ID y tiempo.
      t = t -> next();                              // El apuntador avanza al siguiente nodo.
            }
            cout << endl;                           // Salto de línea.
            }
      }
      while (c_head != nullptr) {                   // Se recorre la copia de la lista para eliminarla.
          node *xd = c_head;                        // Se crea apuntador auxiliar en el principio de la copia de la lista (c_head).
          c_head = c_head -> next();                // El c_head avanza al siguiente nodo.
          delete xd;                                // Se elimina el nodo auxiliar, limpiando la memoria.
      }
      cout << "\n\tTiempo promedio: "<< (float)tRT/n<< endl; // Se calcula tiempo promedio dividiendo el tiempo de respuesta total entre el número de procesos.
      cout << "\n\tQuantum: "<< Q<< endl;           // Se muestra el número Quantum trabajado.
  }

                                                    //http://dev.to/imnotleo/planificacion-de-procesos-c-3m5k

```

*************************


so.hpp

```
#ifndef so_hpp
#define so_hpp

#include <iostream>
#include <assert.h>
using namespace std;

class process {                             // Clase proceso, es el nombre de la lista enlazada con la que trabajamos.

    class node {                            // Clase nodo con atributos ID, Tiempo y Prioridad.

  string _id;
  int _time;
  int _priority;
  node *_next;                              // Se establece un siguiente nodo.

  public:

    node(string i, int t, int q);           // Estructura del nodo.

  string id() const { return _id; }         // Muestra ID.
  int tme() const { return _time; }         // Muestra el Tiempo.
  int prty() const { return _priority; }    // Muestra la Prioridad.
  node *next() const { return _next; }      // Muestra el siguiente nodo.
  
  void setid(string x) { _id = x; }         // Cambia ID.
  void settme(int x) { _time = x; }         // Cambia el Tiempo.
  void setprty(int x) { _priority = x; }    // Cambia la Prioridad.
  void next(node *p) { _next = p; }         // Cambia el siguiente nodo.
  };

  int n;                                    // Capacidad de la lista.
  int s;                                    // Tamaño de la lista.

  node *head;                               // First item in queue.
  node *tail;                               // Last item in queue.

public:
                                            // Constructor y destructor.
    process(int);
   ~process();
                                            // Funciones básicas para conocer la lista enlasada (capacidad, tamaño, si está llena o vacía).
  int capacity() const { return n; }        // Muestra la capacidad de la lista.
  int size() const { return s; }            // Muestra el tamaño de la lista.

  bool full() const { return s==n; }        // Indica si la lista está llena.
  bool empty() const { return s==0; }       // Indica si la lista está vacía.

                                            // Funciones para la ejecución de programa, se desarrollan en so.cpp.
  void print();                             // Imprime los procesos ingresados por el usuario.

  void addProcess();                        // Captura el número de procesos establecidos y los organiza.
  void Menu();                              // Imprime el menú de opciones a calcular con los procesos ingresados.
  int calcQ();                              // Determina el número Quantum.

  void FIFO();                              // FIFO (Primera Entrada, Primera Salida). 
  void SJF();                               // SJF (Tiempo mas corto primero).
  void Prioridad();                         // Prioridad Dinamica (Prioridad de mayor a menor usando Quantum).
  void RoundRobin();                        // Round Robin (Primera Entrada, Primera salida usando Quantum).

};

#endif /* so_hpp                                http://dev.to/imnotleo/planificacion-de-procesos-c-3m5k              */


```