Olá. Essa aqui é a resolução comentada do exercício 1.2.1 a da página 53 do livro Estrutura de dados em C que transcrevo aqui:
A mediana de um vetor de números é o elemento m do vetor, tal que metade dos números restantes no vetor é maior ou igual a m e metade é menor ou igual a m, se o número de elementos no vetor for ímpar. Se o número de elementos for par, a mediana será a média dos dois elementos, m1 e m2, tal que metade dos elementos restantes é maior ou igual a ml e m2, e metade dos elementos é menor ou igual a m1 e m2. Escreva uma função em C que aceite um vetor de números e retorne a mediana dos números no vetor.
Tenenbaum, Langsam e Augesnstein (2013)
Bom, esse aqui está relativamente fácil de resolver e temos dois cenários:
- Antes de tudo, temos de classificar o array em ordem crescente.
- Se a gente tiver um array com um conjunto par de números, basta tirar a média entre os dois elementos do meio do array e teremos a mediana.
- Se a gente tiver um array com um conjunto ímpar de números, basta escolher o elemento central do array.
Antes de continuarmos:
Meu caro. Se esse artigo lhe ajudar e de alguma forma der um adianto para ti, vou ficar muito feliz se você clicar nos links de meus anunciantes e dar uma olhada no que eles tem para te oferecer. Grato :-).
Alguns pontos importantes:
O legal dessa solução é que você pode apagar todo o código principal, deixar os testes unitários e ir implementando as funções no seu estilo, tendo o original para dar uma olhadinha caso queira. Basta remover o código principal, rodar o teste unitário, vai dar erro em tudo e voilá… Hora de sair implementando código e inclusive fazendo melhor que eu :-).
Para simplificar os testes e a execução do programa, eu automatizei a geração dos números aleatórios, o que facilita os testes e não precisamos ficar manualmente inventando valores para testar o programa ou para ver como ele funciona.
A implementação:
Conforme imagem abaixo segue a organização do projeto, começando pela pasta “Source” que contém as pastas “Sources”, “Headers” e “Teste_unitário”.
O programa mesmo são os arquivos main.c, funcoes.c e funcoes.h. Os demais arquivos podem ser removidos, desde que obviamente sejam ajustados os includes.
Caso você queira desenvolver a sua solução, pode apagar o conteúdo de funcoes.c, rodar o teste unitário e sair implementando a solução, no seu estilo, seguindo os testes unitários.
Descrição dos arquivos:
main.c:
Esse arquivo é a entrada do programa. Basicamente esse arquivo faz a impressão da tela e chama as funções:
- Contém a seleção do modo do programa, debug ou normal.
- Contém a seleção do modo de execução: contínuo ou unitário.
- “gera_aleatorio” que gera um array de 10 ou 11 elementos, conforme o caso..
- “classifica” que classifica o array em ordem crescente e calcula o valor da mediana.
- Faz a impressão da saída dos dados.
funcoes.h e funcoes.c:
Esses dois arquivos acomodam a função “gera_aleatorio”, responsável por popular um array de int, de acordo com o valor especificado na variável “tamanho”.
Eles acomodam a função “classifica” que faz a classificação do array que foi gerado anteriormente e calcula a mediana. A função “classifica” utiliza o método quicksort para classificar o array.
A função “qsort”, para funcionar, faz uma chamada à “funcao_compara” que também está nos mesmos aquivos funcoes.h e funcoes.c.
TesteMediana_121a.h e TesteMediana_121a.c:
Esses arquivos acomodam os testes unitário para fazer a asserção das funções do programa e também serve como documentação do software. São 4 funções, sendo duas para gerar o array de números aleatórios e 2 funções para verificar se a mediana está sendo calculada corretamente.
O código:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "Teste_unitario/Teste_Mediana_121a.h"
#include "Teste_unitario/CuTest.h"
#include "funcoes.h"
/*
Exercício 1.2.1 a.
A mediana de um vetor de números é o elemento m do vetor, tal que metade dos
números restantes no vetor é maior ou igual a m e metade é menor ou igual a m,
se o número de elementos no vetor for ímpar. Se o número de elementos for par,
a mediana será a média dos dois elementos, m1 e m2, tal que metade dos
elementos restantes é maior ou igual a ml e m2, e metade dos elementos é
menor ou igual a m1 e m2. Escreva uma função em C que aceite um vetor de
números e retorne a mediana dos números no vetor.
Fonte: Estruturas de Dados Usando C - Tenembaum, pg53.
Autor da solução: Renato de Pierri
nets-nuts.com.br
Para simplificar a solução, ao inves de inserir os valores no array, optei por
gerar automaticamente os valores do array.
*/
//Suite de testes
CuSuite* CuGetSuite();
CuSuite* CuStringGetSuite();
int main()
{
int debug =0;
int continuo = 1;
int mediana_10[10];
int mediana_11[11];
double mediana;
int controle;
do{
if(debug == 0){
printf("Calcula mediana de 10 elementos.\n\n");
printf("Aqui a mediana eh a media entre o quinto e sexto elemento do array.\n");
printf("Gerando um array de 10 elementos inteiros.\n");
gera_aleatorio(mediana_10,10);
printf("Classificando o array de 10 elementos.\n");
mediana = classifica(mediana_10,10);
printf("Imprimindo o array de 10 elementos, classificado.\n");
for(controle = 0;controle<=9;controle++){
printf("%i, ", mediana_10[controle]) ;
}
printf("\n");
printf("A mediana eh: %.01f.\n\n\n",mediana);
printf("Calcula mediana de 11 elementos.\n\n");
printf("Aqui a mediana eh o sexto elemento do array.\n");
printf("Gerando um array de 11 elementos inteiros.\n");
gera_aleatorio(mediana_11,11);
printf("Classificando o array de 11 elementos.\n");
mediana = classifica(mediana_11,11);
printf("Imprimindo o array de 11 elementos, classificado.\n");
for(controle = 0;controle<=10;controle++){
printf("%i, ", mediana_11[controle]) ;
}
printf("\n");
printf("A mediana eh: %.01f.\n\n",mediana);
system("pause");
system("cls");
}else{
RunAllTests();
system("pause");
system("cls");
}
}while(continuo == 1);
return 0;
}
funcoes.h:
#ifndef FUNCOES_H_INCLUDED
#define FUNCOES_H_INCLUDED
void gera_aleatorio(int valores[],int tamanho);
float classifica(int mediana[], int tamanho);
int funcao_compara (const void * a, const void * b);
#endif // FUNCOES_H_INCLUDED
funcoes.c:
#include <stdio.h>
#include <stdlib.h>
#include "Teste_unitario/Teste_Mediana_121a.h"
#include "Teste_unitario/CuTest.h"
#include "funcoes.h"
void gera_aleatorio(int valores[],int tamanho){
int controle;
for(controle = 0;controle<=tamanho;controle++){
valores[controle]=rand() % 100;
}
}
float classifica(int mediana[], int tamanho){
int sup;
int inf;
float med;
qsort(mediana, tamanho, sizeof(int), funcao_compara);
if (tamanho%2==0){
sup = (int)(tamanho/2);
inf = sup - 1;
med = (mediana[sup]+mediana[inf])/2.0f;
}else{
sup = (int)(tamanho/2);
med =(float) mediana[sup];
}
return med;
}
int funcao_compara (const void * v1, const void * v2) {
return ( *(int*)v1 - *(int*)v2 );
}
Teste_Mediana_121a.h:
#ifndef TESTE_MEDIANA_121A_H_INCLUDED
#define TESTE_MEDIANA_121A_H_INCLUDED
#include "CuTest.h"
CuSuite*StrUtilGetSuite();
void RunAllTests(void);
// Testes unitarios
void TesteAleatorio_10(CuTest *tc);
void TesteAleatorio_11(CuTest *tc);
void TesteClassifica_10(CuTest *tc);
void TesteClassifica_11(CuTest *tc);
#endif // TESTE_MEDIANA_121A_H_INCLUDED
Teste_Mediana_121a.c:
#include <stdlib.h>
#include <stdio.h>
#include "Teste_Mediana_121a.h"
#include "CuTest.h"
#include "../funcoes.h"
CuSuite* StrUtilGetSuite();
void RunAllTests(void){
CuString* output = CuStringNew();
CuSuite* suite = CuSuiteNew();
CuSuiteAddSuite(suite, StrUtilGetSuite());
CuSuiteRun(suite);
CuSuiteSummary(suite, output);
CuSuiteDetails(suite, output);
printf ("%s\n\n", output->buffer);
}
void TesteAleatorio_10(CuTest *tc){
CuString* str = CuStringNew();
int valores[10];
size_t nr_elementos;
char resp1[5];
gera_aleatorio(valores,10);
nr_elementos = sizeof(valores)/sizeof(valores[0]);
sprintf(resp1,"%i",(int)nr_elementos);
CuStringAppend(str,resp1);
CuAssertStrEquals(tc, "10", str->buffer);
}
void TesteAleatorio_11(CuTest *tc){
CuString* str = CuStringNew();
int valores[11];
size_t nr_elementos;
char resp1[5];
gera_aleatorio(valores,11);
nr_elementos = sizeof(valores)/sizeof(valores[0]);
sprintf(resp1,"%i",(int)nr_elementos);
CuStringAppend(str,resp1);
CuAssertStrEquals(tc, "11", str->buffer);
}
void TesteClassifica_10(CuTest *tc){
int valores[10] = {91, 27, 27, 42, 45, 81, 91, 4, 36, 61};
float mediana;
mediana = 7.3;
char resp1[5];
CuString* str = CuStringNew();
mediana = classifica(valores,10);
sprintf(resp1,"%.01f",mediana);
CuStringAppend(str,resp1);
CuAssertStrEquals(tc, "43.5", str->buffer);
}
void TesteClassifica_11(CuTest *tc){
int valores[11] = {91, 4, 27, 36, 45, 61, 81, 91, 95, 27, 42};
float mediana;
char resp1[5];
char resp2[5];
CuString* str = CuStringNew();
mediana = classifica(valores,11);
sprintf(resp1,"%.01f",mediana);
sprintf(resp2,"%.01f",(float)valores[5]);
CuStringAppend(str,resp1);
CuAssertStrEquals(tc, resp2, str->buffer);
}
CuSuite*StrUtilGetSuite(){
CuSuite* suite = CuSuiteNew();
SUITE_ADD_TEST(suite,TesteAleatorio_10);
SUITE_ADD_TEST(suite,TesteAleatorio_11);
SUITE_ADD_TEST(suite,TesteClassifica_10);
SUITE_ADD_TEST(suite,TesteClassifica_11);
}
Como sempre, muito obrigado e não esqueça de clicar nos anúncios e ver o que os anunciantes tem de bom para te oferecer.
Publicado em 21/01/2023 por Renato de Pierri.
Bibliografia:
TENENBAUM, Aaron M.; LANGSAM, Yedidyah; AUGESNSTEIN, Moshe J.. Estruturas de Dados Usando C. São Paulo: Pearson, 2013. 884 p. ISBN 13: 978-85-346-0348-5, pg 53.