terça-feira, 26 de dezembro de 2017

Problema da ordenação, busca, remoção e inserção de elementos de um vetor


Compartilhe!

O objetivo deste programa em C abaixo é: dada uma lista inicial de RAs de alunos matriculados em uma turma, realizar as seguintes operações: p - Imprimir; c - Ordenar crescentemente; d - Ordenar decrescentemente; b - Realizar uma busca binária; i - Inserir; e r - Remover.

O identificador b é seguido de um número que será o RA a ser buscado.
O identificador i é seguido de um número que será o RA a ser inserido.
O identificador r é seguido de um número que será o RA a ser removido.

A entrada consiste de um valor inteiro n (número de alunos a serem matriculados inicialmente na turma), uma lista com n inteiros (RA de cada aluno) e uma lista de operações a serem realizadas finalizada pelo caractere s.

Exemplo de entrada e saída:
Entrada:
7
165291 151558 152595 173589 161817 152602 192032
p
c
p
i 182220
p
r 161817
p
b 151558
r 181322
p
s

Saída:
165291 151558 152595 173589 161817 152602 192032
151558 152595 152602 161817 165291 173589 192032
151558 152595 152602 161817 165291 173589 182220 192032
151558 152595 152602 165291 173589 182220 192032
3 1 0
151558 esta na posicao: 0
Aluno nao matriculado na turma!
151558 152595 152602 165291 173589 182220 192032

#include <stdio.h>
#include <string.h>
#define MAX 150

void imprima(int vet[MAX], int tam);
int ordemCrescente(int vet[MAX], int tam);
int ordemDecrescente(int vet[MAX], int tam);
int buscaBinaria(int vet[MAX], int tam, int ra, int cres);
int insira(int vet[MAX], int tam, int ra, int max, int ord, int cres);
int remova(int vet[MAX], int tam, int ra);


int main() {

 char entrada[1100], acao;

 int nAlunos, raAlunos[MAX], res = 0, tam, cres = 0, ordenado = 0, ra, pos, cont, j;

 scanf("%d\n", & nAlunos);//Leia o número de alunos.

 fgets(entrada, 1100, stdin);//Leia os n RAs.
 tam = strlen(entrada);
 cont = 0;

 for (int i = 0; entrada[i] != ' ' && entrada[i] != '\0'; i++) {//Converta entrada em int para colocar os RAs no vetor de inteiros:
  res = 0;
  for (j = i; entrada[j] != ' ' && entrada[j + 1] != '\0'; j++)
  res = res * 10 + (entrada[j] - '0'); //Conversão do char em int a partir da tabela ASCII.
  raAlunos[cont] = res;
  cont++, i = j;
 }
  //Leia a primeira ação, que pode ou não ser seguida por um RA:
 fgets(entrada, 1100, stdin);
 tam = strlen(entrada);
 if (tam == 1) acao = entrada[0];
 else {
  acao = entrada[0];
  res = 0;
  for (int j = 2; j < tam - 1; j++)
  res = res * 10 + (entrada[j] - '0'); //Conversão do char em int a partir da tabela ASCII.
  ra = res;
 }

 while (acao != 's') {//While responsável pelo loop do programa.

  switch (acao) {//Switch para cada ação.
  case 'p':
   imprima(raAlunos, nAlunos);
   break;

  case 'c':
   ordenado = ordemCrescente(raAlunos, nAlunos), cres = 1;
   break;

  case 'd':
   ordenado = ordemDecrescente(raAlunos, nAlunos), cres = 0;
   break;

  case 'b':
   if (ordenado) {
    pos = buscaBinaria(raAlunos, nAlunos, ra, cres);//Armazena a posição do RA ou 0 ou -1.
    printf("\n");
    if (pos > -1) printf("%d esta na posicao: %d\n", ra, pos);//Diz a posição ou informa que não está na lista.
    else printf("%d nao esta na lista!\n", ra);
   } else printf("Vetor nao ordenado!\n");//Se não estiver ordenado, informa que não está ordenado.
   break;

  case 'i':
   res = insira(raAlunos, nAlunos, ra, MAX, ordenado, cres);//Armazena o resultado da operação.
   if (res == 1) nAlunos++;//Se 1: sucesso.
   else if (res == 0) printf("Aluno ja matriculado na turma!\n");//Se 0: aluno já matriculado.
   else printf("Limite de vagas excedido!\n");//Se -1: limite de vagas excedido.
   break;

  case 'r':
   res = remova(raAlunos, nAlunos, ra);//Armazena o resultado da peração.
   if (res == 1) nAlunos--;//A mesma lógica que no caso de inserir RA.
   else if (res == 0) printf("Nao ha alunos cadastrados na turma!\n");
   else printf("Aluno nao matriculado na turma!\n");
   break;

  default:
   printf("Valor invalido\n");

  }
  //Leia a próxima entrada, que pode é uma ação seguida ou não de um RA.
  fgets(entrada, 1100, stdin);
  tam = strlen(entrada);
  if (tam == 1) acao = entrada[0];
  else {
   acao = entrada[0];
   res = 0;
   for (int j = 2; j < tam - 1; j++)
   res = res * 10 + (entrada[j] - '0'); //Conversão do char em int a partir da tabela ASCII.
   ra = res;
  }

 }
 return 0;

}

//Minhas funções:
int remova(int vet[MAX], int tam, int ra) {

 if (tam == 0) return 0;//Caso não haja o que remover.

 for (int i = 0; i < tam; i++)//Busca linear do RA no vetor.
 if (vet[i] == ra) {//Ao encontrar, o remove "trazendo" o próximo valor para o atual.

  for (int j = i; j < tam - 1; j++)
  vet[j] = vet[j + 1];
  return 1;
 }

 return -1;
}


int insira(int vet[MAX], int tam, int ra, int max, int ord, int cres) {

 int aux, prox, encontrou = 0;

 if (tam >= max) return -1;//Se o vetor estiver com seu tamanho máximo.

 for (int i = 0; i < tam; i++)//Busca linear do RA no vetor.
 if (vet[i] == ra) encontrou = 1;

 if (encontrou) return 0;//Se já houver esse RA no vetor.

 if (!ord) {//Se vetor não estiver ordenado, sua posição será a última.
  vet[tam] = ra;
  return 1;
 }

 if (cres) {//Se for crescente:

  for (int i = 0; i < tam; i++)
  if (vet[i] > ra) {

   prox = ra;
   for (int j = i; j < tam + 1; j++) {

    aux = vet[j];
    vet[j] = prox;
    prox = aux;

   }
   return 1;
  }

 } else {//Caso decrescente:

  for (int i = 0; i < tam; i++)
  if (vet[i] < ra) {

   prox = ra;
   for (int j = i; j < tam + 1; j++) {

    aux = vet[j];
    vet[j] = prox;
    prox = aux;

   }

   return 1;
  }
 }

 //Caso esteja ordenado no entanto sem alunos (não entraria nos for):
 vet[tam] = ra;
 return 1;
}


int buscaBinaria(int vet[MAX], int tam, int ra, int cres) {

 int inicio = 0, pos;
 //Se crescente:
 if (cres) while (inicio < tam) { //tam também significa "fim"
  
  pos = (inicio + tam - 1) / 2;
  printf("%d ", pos);
  if (vet[pos] == ra) return pos;//Vai reduzindo a "área" da procura:
  if (vet[pos] < ra) inicio = pos + 1;
  else tam = pos;

 } else while (inicio < tam) {//A mesma ideia mas altera-se a condição do último if.

  pos = (inicio + tam - 1) / 2;
  printf("%d ", pos);
  if (vet[pos] == ra) return pos;
  if (vet[pos] > ra) inicio = pos + 1;
  else tam = pos;

 }

 return -1;
}


int ordemDecrescente(int vet[MAX], int tam) {

 int aux;

 for (int i = 0; i < tam - 1; i++)//Repita tam-1 vezes:
 for (int j = 0; j < tam - 1; j++)//Vá até o final do vetor comparando pares.
 if (vet[j] < vet[j + 1]) {

  aux = vet[j];
  vet[j] = vet[j + 1];
  vet[j + 1] = aux;

 }

 return 1;
}

//A mesma ideia da função anterior:
int ordemCrescente(int vet[MAX], int tam) {

 int aux;

 for (int i = 0; i < tam - 1; i++)
 for (int j = 0; j < tam - 1; j++)
 if (vet[j] > vet[j + 1]) {
  aux = vet[j];
  vet[j] = vet[j + 1];
  vet[j + 1] = aux;

 }

 return 1;
}


void imprima(int vet[MAX], int tam) {
 if(tam>0){//Imprima vetor se não for vazio:
  for (int i = 0; i < tam; i++)
  printf("%d ", vet[i]);
  printf("\n");
 }
}