Buscar

Resumo de Estrutura de Dados 1

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 49 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 49 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 49 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Resumo de Estrutura de Dados 1 
 
 
 
 
O operador Seta (->) existe para acessar os membros da estrutura ou sindicatos por 
meio de ponteiros. 
 
Struct 
Struct diferença de Typedef Struct: Quando usa um nome com struct o padrão de nome 
é menos importante porque ele certamente é um tipo, ele não pode ser usado, e, 
portanto, confundido, com outros identificadores do código. Quando usa um typedef a 
struct não precisa ter nome. Pode ter uma struct anônima sem typedef, mas aí ela não 
poderá ser usada em lugar algum mais na aplicação. 
A função printf possibilita a saída de valores (sejam eles constantes, variáveis ou 
resultado de expressões) segundo um determinado formato. Informalmente, podemos 
dizer 
que a forma da função é: 
printf (formato, lista de constantes/variáveis/expressões...); 
O primeiro parâmetro é uma cadeia de caracteres, em geral delimitada com aspas, que 
especifica o formato de saída das constantes, variáveis e expressões listadas em seguida. 
Para cada valor que se deseja imprimir, deve existir um especificador de formato 
correspondente na cadeia de caracteres formato. Os especificadores de formato variam 
com o tipo do valor e a precisão em que queremos que eles sejam impressos. Estes 
especificadores são precedidos pelo caractere % e podem ser, entre outros: 
 
//%d especifica um int 
//%u especifica um unsigned int 
//%f especifica um double (ou float) 
//%e especifica um double (ou float) no formato científico 
//%g especifica um double (ou float) no formato mais apropriado (%f ou %e) 
//%s especifica uma cadeia de caracteres 
/* 
 
 
/* 
&& operador binário E (AND) 
|| operador binário OU (OR) 
! operador unário de NEGAÇÃO (NOT) 
*/ 
 
/* Scanf 
 
A função scanf permite capturarmos valores fornecidos via teclado pelo usuário do 
programa. Informalmente, podemos dizer que sua forma geral é: 
scanf (formato, lista de endereços das variáveis...); 
O formato deve possuir especificadores de tipos similares aos mostrados para a função 
printf. Para a função scanf, no entanto, existem especificadores diferentes para o tipo 
float e o tipo double: 
 
A principal diferença é que o formato deve ser seguido por uma lista de endereços de 
variáveis (na função printf passamos os valores de constantes, variáveis e expressões). 
Na seção sobre ponteiros, este assunto será tratado em detalhes. Por ora, basta saber 
que, 
para ler um valor e atribuí-lo a uma variável, devemos passar o endereço da variável 
para a 
função scanf. O operador & retorna o endereço de uma variável. Assim, para ler um 
inteiro, devemos ter: 
int n; 
scanf ("%d", &n); 
 
%c especifica um char 
%d especifica um int 
%u especifica um unsigned int 
%f,%e,%g especificam um float 
%lf, %le, %lg especificam um double 
%s especifica uma cadeia de caracteres 
Structs, também conhecidas como Registros, definem tipos de dados que 
agrupam variáveis sob um mesmo tipo de dado. 
A ideia de usar uma struct é permitir que, ao armazenar os dados de uma 
mesma entidade, isto possa ser feito com uma única variável. Por exemplo, 
se for preciso armazenar a altura, o peso e a idade de uma pessoa, pode-se 
criar uma struct chamada Pessoa e agrupar os dados em um único tipo de 
dado, conforme o exemplo a seguir. 
Aos dados agruados em uma struct dá-se o nome de campos(fields). 
typedef struct // Cria uma STRUCT para armazenar os 
dados de uma pessoa 
{ 
 float Peso; // define o campo Peso 
 int Idade; // define o campo Idade 
 float Altura; // define o campo Altura 
} Pessoa; // Define o nome do novo tipo criado 
Após a criação do tipo, é possível declarar variáveis do tipo Pessoa, desta 
forma: 
Pessoa Joao, P1, P2; 
Pessoa Povo[10]; // cria um vetor de 10 pessoas. 
Para acessar os campos de uma struct, usa-se a sintaxe 
NomeDaVariavel.NomeDoCampo, conforme o exemplo a seguir. 
Joao.Idade = 15; 
Joao.Peso = 60.5; 
Joao.Altura = 1.75; 
 
Povo[4].Idade = 23; 
Povo[4].Peso = 75.3; 
Povo[4].Altura = 1.89; 
 
Outra vantagem de utilizar struct é a possibilidade de atribuir os dados de 
uma struct para outra, com apenas um comando de atribuição, como 
neste exemplo: 
 
P2 = Povo [4]; 
 
Passagem de Structs por Parâmetro 
 
Para passar uma struct por valor basta declará-la como um dos 
parâmetros, como no exemplo a seguir 
 
#include <stdio.h> 
 
typedef struct // Cria uma STRUCT para armazenar os 
dados de uma pessoa 
{ 
 float Peso; // define o campo Peso 
 int Idade; // define o campo Idade 
 float Altura; // define o campo Altura 
} Pessoa; // Define o nome do novo tipo criado 
 
void ImprimePessoa(Pessoa P) // declara o parâmetro como 
uma struct 
{ 
 printf("Idade: %d Peso: %f Altura: %f\n", P.Idade, 
P.Peso, P.Altura); 
} 
 
int main() 
{ 
 Pessoa Joao, P2; 
 Pessoa Povo[10]; 
 
 Joao.Idade = 15; 
 Joao.Peso = 60.5; 
 Joao.Altura = 1.75; 
 
 Povo[4].Idade = 23; 
 Povo[4].Peso = 75.3; 
 Povo[4].Altura = 1.89; 
 
 P2 = Povo[4]; 
 P2.Idade++; 
 
 // chama a função que recebe a struct como parâmetro 
 ImprimePessoa(Joao); 
 ImprimePessoa(Povo[4]); 
 ImprimePessoa(P2); 
 return 0; 
} 
 
Alocação Estática 
Na alocação estática de memória, os tipos de dados têm tamanho predefinido. Neste 
caso, o compilador vai alocar de forma automática o espaço de memória necessário. 
Sendo assim, dizemos que a alocação estática é feita em tempo de compilação. Este 
tipo de alocação tende a desperdiçar recursos, já que nem sempre é possível 
determinar previamente qual é o espaço necessário para armazenar as informações. 
Quando não se conhece o espaço total necessário, a tendência é o programador 
exagerar pois é melhor superdimensionar do que faltar espaço. 
Alocação Dinâmica 
Na alocação dinâmica podemos alocar espaços durante a execução de um programa, 
ou seja, a alocação dinâmica é feita em tempo de execução. Isto é bem interessante do 
ponto de vista do programador, pois permite que o espaço em memória seja alocado 
apenas quando necessário. Além disso, a alocação dinâmica permite aumentar ou até 
diminuir a quantidade de memória alocada. 
sizeof 
A função sizeof determina o número de bytes para um determinado tipo de dados. 
É interessante notar que o número de bytes reservados pode variar de acordo com o 
compilador utilizado. 
Exemplo: 
x = sizeof(int); //retorna 4 no gcc 
malloc 
A função malloc aloca um espaço de memória e retorna um ponteiro do tipo void para 
o início do espaço de memória alocado. 
free 
A função free libera o espaço de memória alocado. 
Exemplo: Vetor Dinâmico 
Quando um programador define tipo e o número de elementos um vetor ele está 
utilizando alocação estática. 
Uma alternativa interessante é declarar um vetor como ponteiro, a fim de utilizar 
alocação dinâmica. Para tanto devemos usar a função malloc. Porém, esta função 
necessita saber a quantidade de bytes que devem ser reservados. Para fazer esse cálculo 
usamos o comando sizeof. 
 
#include <stdio.h> 
#include <stdlib.h> //necessário para usar as funções malloc() e free() 
#include <conio.h> 
 
int main(void) 
{ 
 float *v; //definindo o ponteiro v 
 int i, num_componentes; 
 
 printf("Informe o numero de componentes do vetor\n"); 
 scanf("%d", &num_componentes); 
 
 /* ------------- Alocando dinamicamente o espaço necessário ------------- 
 
 1 - Calcular o número de bytes necessários 
 primeiramente multiplicamos o número de componentes do vetor pela 
 quantidade de bytes que é dada pelo comando sizeof, 
 portanto temos: 
 num_componentes * sizeof(float) 
 
 2 - Reservar a quantidade de memória 
 usamos malloc para reservar essa quantidade de memória, 
 então temos: 
 malloc(num_componentes * sizeof(float)) 
 
 3 - Converter o ponteiro para o tipo de dados desejado 
 como a função malloc retorna um ponteiro do tipo void, 
 precisamos converter esse ponteiro para o tipo da nossavariável, no caso f
loat, 
 por isso usamos o comando de conversão explicita: 
 (float *) 
 
 4 - juntando tudo e atribuindo em v temos o comando abaixo: */ 
 
 v = (float *) malloc(num_componentes * sizeof(float)); 
 
 //Armazenando os dados em um vetor 
 for (i = 0; i < num_componentes; i++) 
 { 
 printf("\nDigite o valor para a posicao %d do vetor: ", i+1); 
 scanf("%f",&v[i]); 
 } 
 
 // ------ Percorrendo o vetor e imprimindo os valores ---------- 
 printf("\n*********** Valores do vetor dinamico ************\n\n"); 
 
 for (i = 0;i < num_componentes; i++) 
 { 
 printf("%.2f\n",v[i]); 
 } 
 
 //liberando o espaço de memória alocado 
 free(v); 
 
 getch(); 
 return 0; 
} 
 
Exemplo de execução de alocação dinâmica de memória em C 
Alocação Dinâmica de Matriz em C 
Para o exemplo a seguir vamos fazer a leitura dos valores da matriz usando um arquivo 
texto, portanto será necessário criar o arquivo denominado ArqMatrizes.txt com os 
valores conforme a figura a seguir: 
 
Esse arquivo é composto pelas dimensões das matrizes: 3 6, ou seja, 3 linhas e 6 colunas, 
e também pelos valores das duas matrizes com dimensão 3 x 6. 
No código a seguir vamos alocar dinamicamente duas matrizes 3 X 6 e fazer a leitura dos 
valores do arquivo texto. 
Em seguida vamos alocar dinamicamente uma terceira matriz que vai conter a soma dos 
valores das outras duas matrizes. 
#include <stdio.h> 
#include <stdlib.h> //necessário para usar as funções malloc() e free() 
#include <stdlib.h> 
 
http://linguagemc.com.br/wp-content/uploads/2012/09/ArqMatrizes.png
int main(void) 
{ 
 int i,j,n_linhas,n_colunas; 
 
 //matrizes dinâmicas de duas dimensões portanto vamos necessitar um ponteir
o para a linha 
 //e outro ponteiro apontando para coluna 
 
 int **matriz1,**matriz2,**matriz_soma; 
 FILE *ptrArq; 
 
 //Abrindo o arquivo 
 ptrArq = fopen("ArqMatrizes.txt", "r"); 
 
 //Verificando se a abertura do arquivo foi bem sucedida 
 if (ptrArq == NULL) 
 { 
 printf("Erro ao abrir o arquivo!\n"); 
 printf("Saindo do programa...\n"); 
 system("pause"); 
 exit(1);//abortando o programa 
 } 
 
 // Leitura das dimensões da matriz a partir dos valores do arquivo 
 fscanf(ptrArq,"%d %d",&n_linhas,&n_colunas); 
 
 // Alocar a memória necessária para as matrizes 
 //----------------- Alocando a matriz1 --------------- 
 
 // alocar a quantidade de linhas 
 matriz1 = (int **)calloc(n_linhas,sizeof(int *)); 
 for (i = 0; i < n_linhas; i++) 
 { 
 // alocar a quantidade de colunas de cada linha 
 matriz1[i] = (int *)calloc(n_colunas,sizeof(int)); 
 } 
 
 //----------------- Alocando a matriz2 --------------- 
 matriz2 = (int **)calloc(n_linhas,sizeof(int *)); 
 
 for (i = 0; i < n_linhas; i++) 
 { 
 matriz2[i] = (int *)calloc(n_colunas,sizeof(int)); 
 } 
 
 
 // ------- Ler os valores para as matrizes a partir do arquivo texto ------ 
 for (i = 0; i < n_linhas; i++) 
 { 
 for (j = 0; j < n_colunas; j++) 
 { 
 fscanf(ptrArq,"%d",&matriz1[i][j]);//ler um inteiro do arquivo e armaze
nar na matriz1 
 } 
 } 
 
 
 for (i = 0; i < n_linhas; i++) 
 { 
 for (j = 0; j < n_colunas; j++) 
 { 
 fscanf(ptrArq,"%d",&matriz2[i][j]);//ler um inteiro do arquivo e armaze
nar na matriz2 
 } 
 } 
 
 fclose(ptrArq);//Fechar o arquivo 
 
 // --------------- Mostrar as matrizes lidas --------------------- 
 printf("Matrizes lidas do arquivo:\n"); 
 for (i = 0; i < n_linhas; i++) 
 { 
 for (j = 0; j < n_colunas; j++) 
 { 
 printf("%2d ",matriz1[i][j]); 
 } 
 
 printf(" "); //Espaçamento entre as duas matrizes 
 
 for (j = 0; j < n_colunas; j++) 
 { 
 printf("%2d ",matriz2[i][j]); 
 } 
 printf("\n"); 
 } 
 
 // Alocar memoria para matriz soma 
 matriz_soma = (int **)calloc(n_linhas,sizeof(int *)); 
 
 for (i = 0; i < n_linhas; i++) 
 { 
 matriz_soma[i] = (int *)calloc(n_colunas,sizeof(int)); 
 } 
 
 
 // Calcular matriz soma 
 for (i = 0; i < n_linhas; i++) 
 { 
 for (j = 0; j < n_colunas; j++) 
 { 
 matriz_soma[i][j] = matriz1[i][j] + matriz2[i][j]; 
 } 
 } 
 
 // Mostrar matriz soma 
 printf("\nMatriz soma:\n"); 
 for (i = 0; i < n_linhas; i++) 
 { 
 for (j = 0; j < n_colunas; j++) 
 { 
 printf("%3d ",matriz_soma[i][j]); 
 } 
 printf("\n"); 
 } 
 
 //liberando a memória da matriz1 
 //para matrizes a liberação da memória ocorre na ordem inversa da alocação 
 for (i=0; i < n_linhas; i++) 
 { 
 free (matriz1[i]) ; 
 } 
 free (matriz1) ; 
 
 //liberando a memória da matriz2 
 for (i=0; i < n_linhas; i++) 
 free (matriz2[i]) ; 
 free (matriz2) ; 
 
 //liberando a memória da matriz_soma 
 for (i=0; i < n_linhas; i++) 
 free (matriz_soma[i]) ; 
 free (matriz_soma); 
 
 printf("\n"); 
 system("pause"); 
 return 0; 
} 
Uma aplicação de Struct: as listas simplesmente encadeadas 
Várias estruturas de dados complexas podem ser criadas utilizando simultaneamente 
Struct e ponteiros. Uma destas estruturas é a lista encadeada. Uma lista encadeada é 
uma sequência de Struct, que são os nós da lista, ligados entre si através de ponteiros. 
Esta sequência pode ser acessada através de um ponteiro para o primeiro nó, que é a 
cabeça da lista. Cada nó contém um ponteiro que aponta para a Struct que é a sua 
sucessora na lista. O ponteiro da última Struct da lista aponta para NULL, indicando que 
se chegou ao final da lista. Esta estrutura de dados é criada dinamicamente na memória 
(utiliza-se malloc () e free ()), de modo que se torna simples introduzir nós nela, retirar 
nós, ordenar os nós, etc. Não vamos entrar em detalhes sobre todos os algoritmos que 
poder amos criar em uma lista encadeada, pois isto geralmente e feito em cursos de 
algoritmos e estruturas de dados, não se incluindo no escopo deste curso. Aqui, veremos 
somente formas de se criar uma lista encadeada em C e também maneiras simples de 
percorrer esta lista. 
Supondo que queiramos criar uma lista encadeada para armazenar os produtos 
disponíveis em uma loja. Poder amos criar um n desta lista usando a seguinte Struct: 
struct Produto { 
 int codigo; /* Codigo do produto */ 
 double preco; /* Preco do produto */ 
 struct Produto *proximo; /* Proximo elemento 
da lista encadeada de Produtos */ 
}; 
Note que esta Struct possui, além dos campos de dados código e preço, um campo 
adicional que é um ponteiro para uma Struct do tipo Produto. É este campo que ser 
utilizado para apontar para o próximo nó da lista encadeada. O programa a seguir faz 
uso desta Struct, através de um novo tipo criado por um Typedef, para criar uma lista 
de produtos de uma loja: 
#include <stdio.h> 
#include <stdlib.h> 
 
/* Estrutura que ser usada para criar os nós da lista */ 
 
typedef struct tipo_produto { 
 int codigo; /* Codigo do produto */ 
 double preco; /* Preco do produto */ 
 struct tipo_produto *proximo; /* Proximo elemento da lista 
encadeada de Produtos */ 
} TProduto; 
 
/* Prototipos das funcoes para inserir e listar produtos */ 
 
void inserir(TProduto **cabeca); 
void listar (TProduto *cabeca); 
 
int main() 
{ 
 TProduto *cabeca = NULL; /* Ponteiro para a cabeca da 
lista */ 
 TProduto *noatual; /* Ponteiro a ser usado para 
percorrer a lista no momento de desalocar seus elementos*/ 
 char q; /* Caractere para receber a 
opcao do usuario */ 
 do { 
 printf("\n\nOpcoes: \nI -> para inserir novo produto;\nL 
-> para listar os produtos; \nS -> para sair \n:"); 
 scanf("%c", &q); /* Le a opcaodo usuario */ 
 switch(q) { 
 case 'i': case 'I': inserir(&cabeca); break; 
 case 'l': case 'L': listar(cabeca); break; 
 case 's': case 'S': break; 
 default: printf("\n\n Opcao nao válida"); 
 } 
 fflush(stdin); /* Limpa o buffer de entrada */ 
 } while ((q != 's') && (q != 'S') ); 
 
/* Desaloca a memória alocada para os elementos da lista */ 
 
 noatual = cabeca; 
 while (noatual != NULL) 
 { 
 cabeca = noatual->proximo; 
 free(noatual); 
 noatual = cabeca; 
 } 
} 
/* Lista todos os elementos presentes na lista encadeada */ 
 
void listar (TProduto *noatual) 
{ 
 int i=0; 
 while( noatual != NULL) /* Enquanto nao chega no fim da 
lista */ 
 { 
 i++; 
 printf("\n\nProduto número %d\nCodigo: %d 
\nPreco:R$%.2lf", i, noatual->codigo, noatual->preco); 
 noatual = noatual->proximo; /* Faz noatual apontar 
para o proximo no */ 
 } 
} 
/* Funcao para inserir um novo no, ao final da lista */ 
 
void inserir (TProduto **cabeca) 
{ 
 TProduto *noatual, *novono; 
 int cod; 
 double preco; 
 printf("\n Codigo do novo produto: "); 
 scanf("%d", &cod); 
 printf("\n Preco do produto:R$"); 
 scanf("%lf", &preco); 
 if (*cabeca == NULL) /* Se ainda nao existe nenhum produto 
na lista */ 
 { 
/* cria o no cabeca */ 
 *cabeca = (TProduto *) malloc(sizeof(TProduto)); 
 (*cabeca)->codigo = cod; 
 (*cabeca)->preco = preco; 
 (*cabeca)->proximo = NULL; 
 } 
 else 
 { 
/* Se ja existem elementos na lista, deve percorre-la até' o seu 
final e inserir o novo elemento */ 
 noatual = *cabeca; 
 while(noatual->proximo != NULL) 
 noatual = noatual->proximo; /* Ao final do while, 
noatual aponta para o ultimo no */ 
 novono = (TProduto *) malloc(sizeof(TProduto));/* Aloca 
memória para o novo no */ 
 novono->codigo = cod; 
 novono->preco = preco; 
 novono->proximo = NULL; 
 noatual->proximo = novono; /* Faz o ultimo no apontar 
para o novo no */ 
 } 
} 
 
 
É interessante notar que, no programa anterior não existe limite para o número de 
produtos que se vai armazenar na lista. Toda vez que for necessário criar um novo 
produto, memória para ele será alocada e ele será criado no final da lista. Note que a 
função inserir recebe o endereço do ponteiro cabeça da lista. Qual a razão disto? A razão 
é que o endereço para o qual a cabeça da lista aponta poderá ser modificado caso se 
esteja inserindo o primeiro elemento na lista. Tente entender todos os passos deste 
programa, pois ele possui várias das características presentes em programas que 
manipulam listas encadeadas. Também é importante notar que várias outras estruturas 
de dados complexas podem ser criadas com Struct contendo ponteiros que apontam 
para outras Struct. 
Recursividade em C 
Em uma função recursiva, a cada chamada é criada na memória uma nova ocorrência 
da função com comandos e variáveis “isolados” das ocorrências anteriores. 
A função é executada até que todas as ocorrências tenham sido resolvidas. 
Porém um problema que surge ao usar a recursividade é como fazê-la parar. Caso o 
programador não tenha cuidado é fácil cair num loop infinito recursivo o qual pode 
inclusive esgotar a memória… 
Toda recursividade é composta por um caso base e pelas chamadas recursivas,. 
Caso base: é o caso mais simples. É usada uma condição em que se resolve o problema 
com facilidade. 
Chamadas Recursivas: procuram simplificar o problema de tal forma que convergem 
para o caso base. 
Vantagens da recursividade 
• Torna a escrita do código mais simples e elegante, tornando-o fácil de entender 
e de manter. 
Desvantagens da recursividade 
• Quando o loop recursivo é muito grande é consumida muita memória nas 
chamadas a diversos níveis de recursão, pois cada chamada recursiva aloca 
memória para os parâmetros, variáveis locais e de controle. 
• Em muitos casos uma solução iterativa gasta menos memória, e torna-se mais 
eficiente em termos de performance do que usar recursão. 
Exemplo clássico de recursividade: fatorial 
//Cálculo de fatorial com função recursiva 
#include <stdio.h> 
#include <conio.h> 
 
//protótipo da função fatorial 
double fatorial(int n); 
 
int main(void) 
{ 
 int numero; 
 double f; 
 
 printf("Digite o numero que deseja calcular o fatorial: "); 
 scanf("%d",&numero); 
 
 //chamada da função fatorial 
 f = fatorial(numero); 
 
 printf("Fatorial de %d = %.0lf",numero,f); 
 
 getch(); 
 return 0; 
} 
 
//Função recursiva que calcula o fatorial 
//de um numero inteiro n 
double fatorial(int n) 
{ 
 
 double vfat; 
 
 if ( n <= 1 ) 
 //Caso base: fatorial de n <= 1 retorna 1 
 return (1); 
 else 
 { 
 //Chamada recursiva 
 vfat = n * fatorial(n - 1); 
 return (vfat); 
 } 
} 
 
 
 
 
Tela de Execução 
 
Tela de execução clássico de recursividade fatorial 
Explicação do código 
No programa acima, se o número n for menor ou igual a 1 o valor 1 será retornado e a 
função encerrada, sem necessidade de chamadas recursivas. Caso contrário dá-se 
início a chamadas recursivas até cair no caso mais simples que é resolvido e assim, as 
chamadas retornam valores de forma a solucionar o cálculo. 
Veja a figura a seguir que representa as chamadas recursivas para o cálculo de 5! 
 
Cálculo recursivo 5! 
 
http://linguagemc.com.br/wp-content/uploads/2012/06/teladeexecucaoclassicoderecursividade.png
http://linguagemc.com.br/wp-content/uploads/2012/06/calculorecursivo53.png
 Lista Circular 
/* 
 Estrutura nó 
*/ 
typedef struct no{ 
 int valor; 
 struct no *proximo; 
}No; 
 
// estrutura lista 
typedef struct{ 
 No *inicio; 
 No *fim; 
 int tam; 
}Lista; 
 
 
/* 
 procedimento para inserir no início 
*/ 
void inserir_no_inicio(Lista *lista, int num){ 
 No *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 // o próximo aponta para o início da lista 
 novo->proximo = lista->inicio; 
 // novo se torna o início da lista 
 lista->inicio = novo; 
 // se fim for nulo (lista vazia), fim aponta para 
novo nó 
 if(lista->fim == NULL) 
 lista->fim = novo; 
 // fim aponta para início 
 lista->fim->proximo = lista->inicio; 
 lista->tam++; 
 
 
 
 
 
 
 
 
 
 
typedef struct no{ 
 int valor; 
 struct no *proximo; 
}No; 
 
typedef struct{ 
 No *inicio; 
 No *fim; 
 int tam; 
}Lista; 
 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
 
void criar_lista(Lista *lista){ 
 lista->inicio = NULL; 
 lista->fim = NULL; 
 lista->tam = 0; 
} 
 
// procedimento para inserir no início 
void inserir_no_inicio(Lista *lista, int num){ 
 No *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 novo->proximo = lista->inicio; 
 lista->inicio = novo; 
 if(lista->fim == NULL) 
 lista->fim = novo; 
 lista->fim->proximo = lista->inicio; 
 lista->tam++; 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
 
// procedimento para inserir no fim 
void inserir_no_fim(Lista *lista, int num){ 
 No *aux, *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 
 // é o primeiro? 
 if(lista->inicio == NULL){ 
 lista->inicio = novo; 
 lista->fim = novo; 
 lista->fim->proximo = lista->inicio; 
 } 
 else{ 
 lista->fim->proximo = novo; 
 lista->fim = novo; 
 // as duas linhas a seguir são sinônimas. Escolha a que 
achar mais fácil compreender 
 //lista->fim->proximo = lista->inicio;novo->proximo = lista->inicio; 
 } 
 lista->tam++; 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
// procedimento para inserir ordenado 
void inserir_ordenado(Lista *lista, int num){ 
 No *aux, *novo = malloc(sizeof(No)); 
 if(novo){ 
 novo->valor = num; 
 if(lista->inicio == NULL){ 
 inserir_no_inicio(lista, num); 
 } 
 else if(novo->valor < lista->inicio->valor){ 
 inserir_no_inicio(lista, num); 
 } 
 else{ 
 aux = lista->inicio; 
 while(aux->proximo != lista->inicio && novo->valor > aux-
>proximo->valor) 
 aux = aux->proximo; 
 if(aux->proximo == lista->inicio) 
 inserir_no_fim(lista, num); 
 else{ 
 novo->proximo = aux->proximo; 
 aux->proximo = novo; 
 lista->tam++; 
 } 
 } 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
// função para remover um nó 
No* remover(Lista *lista, int num){ 
 No *aux, *remover = NULL; 
 
 if(lista->inicio){ 
 if(lista->inicio == lista->fim && lista->inicio->valor == num){ 
 remover = lista->inicio; 
 lista->inicio = NULL; 
 lista->fim = NULL; 
 lista->tam--; 
 } 
 else if(lista->inicio->valor == num){ 
 remover = lista->inicio; 
 lista->inicio = remover->proximo; 
 lista->fim->proximo = lista->inicio; 
 lista->tam--; 
 } 
 else{ 
 aux = lista->inicio; 
 while(aux->proximo != lista->inicio && aux->proximo->valor 
!= num) 
 aux = aux->proximo; 
 if(aux->proximo->valor == num){ 
 if(lista->fim == aux->proximo){ 
 remover = aux->proximo; 
 aux->proximo = remover->proximo; 
 lista->fim = aux; 
 } 
 else{ 
 remover = aux->proximo; 
 aux->proximo = remover->proximo; 
 } 
 lista->tam--; 
 } 
 } 
 } 
 
 return remover; 
} 
// função para buscar um valor 
No* buscar(Lista *lista, int num){ 
 No *aux = lista->inicio; 
 
 if(aux){ 
 do{ 
 if(aux->valor == num) 
 return aux; 
 aux = aux->proximo; 
 }while(aux != lista->inicio); 
 } 
 return NULL; 
} 
// procedimento para imprimir a lista circular 
void imprimir(Lista lista){ 
 No *no = lista.inicio; 
 printf("\n\tLista tam %d: ", lista.tam); 
 if(no){ 
 do{ 
 printf("%d ", no->valor); 
 no = no->proximo; 
 }while(no != lista.inicio); 
 printf("\nInicio: %d\n", no->valor); 
 } 
 printf("\n\n"); 
} 
 
int main(){ 
 
 int opcao, valor, anterior; 
 //No *lista = NULL; 
 Lista lista; 
 No *removido; 
 
 criar_lista(&lista); 
 
 do{ 
 printf("\n\t0 - Sair\n\t1 - InserirI\n\t2 - inserirF\n\t3 - 
InserirO\n\t4 - Remover\n\t5 - Imprimir\n\t6 - Buscar\n"); 
 scanf("%d", &opcao); 
 
 switch(opcao){ 
 case 1: 
 printf("Digite um valor: "); 
 scanf("%d", &valor); 
 inserir_no_inicio(&lista, valor); 
 break; 
 case 2: 
 printf("Digite um valor: "); 
 scanf("%d", &valor); 
 inserir_no_fim(&lista, valor); 
 break; 
 case 3: 
 printf("Digite um valor: "); 
 scanf("%d", &valor); 
 inserir_ordenado(&lista, valor); 
 break; 
 case 4: 
 printf("Digite um valor a ser removido: "); 
 scanf("%d", &valor); 
 removido = remover(&lista, valor); 
 if(removido){ 
 printf("Elemento removido: %d\n", removido->valor); 
 free(removido); 
 } 
 else 
 printf("elemento inesistente!\n"); 
 break; 
 case 5: 
 imprimir(lista); 
 break; 
 case 6: 
 printf("Digite um valor a ser buscado: "); 
 scanf("%d", &valor); 
 removido = buscar(&lista, valor); 
 if(removido) 
 printf("Valor encontrado: %d\n", removido->valor); 
 else 
 printf("Valor nao encontrado!\n"); 
 break; 
 default: 
 if(opcao != 0) 
 printf("Opcao invalida!\n"); 
 } 
 
 }while(opcao != 0); 
 
 return 0; 
} 
 
 
Lista duplamente encadeada 
 
 
 
 
 
/* 
 Estrutura nó para a lista duplamente encadeada 
*/ 
typedef struct no{ 
 int valor; 
 struct no *proximo; 
 struct no *anterior; 
}No; 
 
 
 
 
 
/* 
 procedimento para inserir um novo nó no início da lista 
*/ 
void inserir_no_inicio(No **lista, int num){ 
 No *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 // próximo do novo nó aponta para o início da lista 
 novo->proximo = *lista; 
 // o anterior é nulo pois é o primeiro nó 
 novo->anterior = NULL; 
 // se a lista não estiver vazia, o anterior do primeiro nó 
aponta para o novo nó 
 if(*lista) 
 (*lista)->anterior = novo; 
 // o novo nó passa a ser o início da lista (o primeiro nó da 
lista) 
 *lista = novo; 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
typedef struct no{ 
 int valor; 
 struct no *proximo; 
 struct no *anterior; 
}No; 
 
// procedimento para inserir no início 
void inserir_no_inicio(No **lista, int num){ 
 No *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 novo->proximo = *lista; 
 novo->anterior = NULL; 
 if(*lista) 
 (*lista)->anterior = novo; 
 *lista = novo; 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
 
// procedimento para inserir no fim 
void inserir_no_fim(No **lista, int num){ 
 No *aux, *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 novo->proximo = NULL; 
 
 // é o primeiro? 
 if(*lista == NULL){ 
 *lista = novo; 
 novo->anterior = NULL; 
 } 
 else{ 
 aux = *lista; 
 while(aux->proximo) 
 aux = aux->proximo; 
 aux->proximo = novo; 
 novo->anterior = aux; 
 } 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
// procedimento para inserir no meio 
void inserir_no_meio(No **lista, int num, int ant){ 
 No *aux, *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 // é o primeiro? 
 if(*lista == NULL){ 
 novo->proximo = NULL; 
 novo->anterior = NULL; 
 *lista = novo; 
 } 
 else{ 
 aux = *lista; 
 while(aux->valor != ant && aux->proximo) 
 aux = aux->proximo; 
 novo->proximo = aux->proximo; 
 if(aux->proximo) 
 aux->proximo->anterior = novo; 
 novo->anterior = aux; 
 aux->proximo = novo; 
 } 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
 
void inserir_ordenado(No **lista, int num){ 
 No *aux, *novo = malloc(sizeof(No)); 
 
 if(novo){ 
 novo->valor = num; 
 // a lista está vazia? 
 if(*lista == NULL){ 
 novo->proximo = NULL; 
 novo->anterior = NULL; 
 *lista = novo; 
 } // é o menor? 
 else if(novo->valor < (*lista)->valor){novo->proximo = *lista; 
 (*lista)->anterior = novo; 
 *lista = novo; 
 } 
 else{ 
 aux = *lista; 
 while(aux->proximo && novo->valor > aux->proximo->valor) 
 aux = aux->proximo; 
 novo->proximo = aux->proximo; 
 if(aux->proximo) 
 aux->proximo->anterior = novo; 
 novo->anterior = aux; 
 aux->proximo = novo; 
 } 
 } 
 else 
 printf("Erro ao alocar memoria!\n"); 
} 
 
No* remover(No **lista, int num){ 
 No *aux, *remover = NULL; 
 
 if(*lista){ 
 if((*lista)->valor == num){ 
 remover = *lista; 
 *lista = remover->proximo; 
 if(*lista) 
 (*lista)->anterior = NULL; 
 } 
 else{ 
 aux = *lista; 
 while(aux->proximo && aux->proximo->valor != num) 
 aux = aux->proximo; 
 if(aux->proximo){ 
 remover = aux->proximo; 
 aux->proximo = remover->proximo; 
 if(aux->proximo) 
 aux->proximo->anterior = aux; 
 } 
 } 
 } 
 return remover; 
} 
 
No* buscar(No **lista, int num){ 
 No *aux, *no = NULL; 
 
 aux = *lista; 
 while(aux && aux->valor != num) 
 aux = aux->proximo; 
 if(aux) 
 no = aux; 
 return no; 
} 
 
void imprimir(No *no){ 
 printf("\n\tLista: "); 
 while(no){ 
 printf("%d ", no->valor); 
 no = no->proximo; 
 } 
 printf("\n\n"); 
} 
// retorna ponteiro para o último nó da lista 
No* ultimo(No **lista){ 
 No *aux = *lista; 
 while(aux->proximo) 
 aux = aux->proximo; 
 return aux; 
} 
 
// imprime a lista do fim para o início 
// recebe um ponteiro para o último nó da lista 
void imprimirContrario(No *no){ 
 printf("\n\tLista: "); 
 while(no){ 
 printf("%d ", no->valor); 
 no = no->anterior; 
 } 
 printf("\n\n"); 
} 
 
int main(){ 
 
 int opcao, valor, anterior; 
 No *removido, *lista = NULL; 
 
 do{ 
 printf("\n\t0 - Sair\n\t1 - InserirI\n\t2 - inserirF\n\t3 - 
InserirM\n\t4 - InserirO\n\t5 - Remover\n\t6 - Imprimir\n\t7 - 
Buscar\n\t8 - ImprimirC\n"); 
 scanf("%d", &opcao); 
 
 switch(opcao){ 
 case 1: 
 printf("Digite um valor: "); 
 scanf("%d", &valor); 
 inserir_no_inicio(&lista, valor); 
 break; 
 case 2: 
 printf("Digite um valor: "); 
 scanf("%d", &valor); 
 inserir_no_fim(&lista, valor); 
 break; 
 case 3: 
 printf("Digite um valor e o valor de referencia: "); 
 scanf("%d%d", &valor, &anterior); 
 inserir_no_meio(&lista, valor, anterior); 
 break; 
 case 4: 
 printf("Digite um valor: "); 
 scanf("%d", &valor); 
 inserir_ordenado(&lista, valor); 
 break; 
 case 5: 
 printf("Digite um valor a ser removido: "); 
 scanf("%d", &valor); 
 removido = remover(&lista, valor); 
 if(removido){ 
 printf("Elemento a ser removido: %d\n", removido-
>valor); 
 free(removido); 
 } 
 else 
 printf("Elemento inexistente!\n"); 
 break; 
 case 6: 
 imprimir(lista); 
 break; 
 case 7: 
 printf("Digite um valor a ser buscado: "); 
 scanf("%d", &valor); 
 removido = buscar(&lista, valor); 
 if(removido) 
 printf("Elemento encontrado: %d\n", removido->valor); 
 else 
 printf("Elemento nao encontrado!\n"); 
 break; 
 case 8: 
 imprimirContrario(ultimo(&lista)); 
 break; 
 default: 
 if(opcao != 0) 
 printf("Opcao invalida!\n"); 
 } 
 
 }while(opcao != 0); 
 
 return 0; 
} 
 
 
Pilha 
#include <iostream> 
#define tamanho 5 
using namespace std; 
 
//define a estrutura que será a pilha 
//a estrutura armazena a indicação do topo da pilha e um vetor 
com os itens (valores) da pilha 
typedef struct{ 
 int topo = 0; 
 int item [tamanho] ; 
} PILHA; 
 
//retorna se a pilha está vazia ou não 
bool pilhaVazia(PILHA p){ 
 if(p.topo == 0) { 
 return true; 
 } else { 
 return false; 
 } 
} 
 
//retorna se a pilha está cheia ou não 
bool pilhaCheia(PILHA p) { 
 int tam = sizeof(p.item)/sizeof(int); //determina o 
tamanho do vetor 
 
 if (p.topo < tam) { 
 return false; 
 } else { 
 return true; 
 } 
} 
 
//adiciona valor na pilha 
void empilha(PILHA &p, int x){ 
 p.item[p.topo++]=x; 
} 
 
//remove valor da pilha 
int desempilha(PILHA &p){ 
 return (p.item[--p.topo]) ; 
} 
 
//mostra os valores armazenados na pilha 
void mostraPilha(PILHA p) { 
 cout << "Valores da pilha: "; 
 for (int i = 0; i < p.topo; i++) { 
 cout << p.item[i] << " "; 
 } 
 cout << "\n"; 
} 
 
//Código para testar a implementação. 
int main(){ 
 PILHA s; //criar a pilha 
 
 //Verificar que a pilha está vazia 
 if(pilhaVazia(s)) { 
 cout<<"A pilha está vazia."<<endl; 
 } else { 
 cout<<"A pilha não está vazia."<<endl; 
 } 
 
 //Empilha valor e verifica se a pilha está vazia 
 empilha(s,10); 
 if(pilhaVazia(s)) { 
 cout<<"A pilha está vazia."<<endl; 
 } else { 
 cout<<"A pilha não está vazia."<<endl; 
 } 
 
 //Empilhar 3 elementos 
 empilha(s,20); 
 empilha(s,30); 
 empilha(s,40); 
 
 //Mostra os valores da pilha 
 mostraPilha(s); 
 
 //Verifica que a pilha está cheia 
 if(pilhaCheia(s)) { 
 cout<<"A pilha está cheia."<<endl; 
 } else { 
 cout<<"A pilha não está cheia."<<endl; 
 } 
 
 //Empilha valor e verifica se a pilha está cheia 
 empilha(s,50); 
 mostraPilha(s); 
 if(pilhaCheia(s)) { 
 cout<<"A pilha está cheia."<<endl; 
 } else { 
 cout<<"A pilha não está cheia."<<endl; 
 } 
 
 //Desempilha e mostrar o valor desempilhado 
 cout<<"Valor desempilhado: "<< desempilha(s) <<endl; 
 
 mostraPilha(s); 
 
 return 0; 
} 
 
Filas: 
Listas, pilhas e filas são estruturas de dados, que nos permitem organizar e interagir com nossos dados 
e organizá-los de diferentes formas. Em C++ existem bibliotecas que nos permitem implementar esses 
tipos de estruturas, o que torna nosso trabalho mais simples do que se tivéssemos de criá-las 
manualmente. 
 Primeiro vamos falar sobre pilhas: 
#include <stack> 
#include <iostream> 
 
using namespace std; 
 
int main(){ 
 stack<int> pilha; 
 for(int i=0;i<10;i++){ 
 pilha.push(i); 
 } 
 cout << pilha.top() << endl; 
 pilha.pop(); 
 cout << pilha.top() << endl; 
 for(int i=0;i<9;i++){ 
 pilha.pop(); 
 if(pilha.empty()){ 
 cout << "Fiquei vazia na iteração: " << i+1 << endl; 
 } 
} 
 
 
 A biblioteca para se usar pilha em c++ é a "stack". Logo após declararmos nossa "stack", indicando 
qual tipo de dado colocaremos nela, com o nome pilha, temos um for e uma função chamada push 
(). A função push é a função que nos permite empilhar os nossos objetos em nossa pilha. Caso não 
saibam, uma pilha funciona seguindo o padrão FILO (First in Last out), que significa que o primeiro 
elemento a entrar é o último a sair, como se os elementos realmente estivessem empilhados um em 
cima do outro. 
 Logo a seguir temos a função top (), que nos retorna o elemento do topo sem removê-lo. Já a função 
pop () remove o elemento no topo da lista, porém não retorna o seu valor. Na primeira vez que 
printamos no console o top (), teremos o valor 9. Depoisde darmos o pop e printarmos o top de novo, 
teremos o valor 8. No último for temos a função empty (), que retornará true caso a pilha esteja vazia. 
Ou seja, só entraremos naquele if na última iteração e o print que aparecerá será "Fiquei vazia na 
iteração 8". 
 Em seguida temos filas. Filas seguem o padrão FIFO (First In First Out), ou seja, o primeiro a chegar 
é o primeiro a sair. 
include <iostream> 
#include <queue> 
 
using namespace std; 
 
int main(){ 
 queue<int> fila; 
 for(int i=0;i<10;i++){ 
 fila.push(i); 
 } 
 cout << fila.front() << endl; 
 cout << fila.pop() << endl; 
 cout << fila.front() << endl; 
 
 for(int i=0;i<9;i++){ 
 fila.pop(); 
 if(fila.empty()){ 
 cout << "Vazio na iteração " << i+1 << endl; 
 } 
 } 
} 
 
 
 Como podemos ver em fila temos funções semelhantes às de pilha. As diferenças são poucas, 
como o include, que deixa de ser "stack" para "queue" e ao invés de top () em fila temos front 
(). A principal diferença é que na pilha ao usarmos top () veríamos o último elemento que foi 
adicionado a pilha (no exemplo acima o 9), já na fila ao usarmos front () vemos o primeiro 
elemento (Nesse caso o 0) e ao usarmos pop () o nosso próximo elemento será o inteiro de 
valor 1. 
 Já a lista é, de certa forma, uma estrutura mais completa, porque podemos utilizá-la de 
diversas formas, incluindo no estilo de pilha e fila. Em uma lista podemos adicionar um 
elemento tanto no início quanto no fim da lista, assim como podemos escolher se vamos retirar 
o elemento do início ou do fim também! Porém em uma lista podemos inserir os elementos 
onde queremos assim como remover o elemento que quisermos. Vamos ver: 
#include <iostream> 
#include <list> 
 
using namespace std; 
 
int main(){ 
 list<int> lista; 
 list<int>::iterator it; 
 for(int i=0;i<5;i++){ 
 lista.push_back(i); 
 } 
 for(int i=5;i<10;i++){ 
 lista.push_front(i); 
 } 
 // Conteudo da lista: 9 8 7 6 5 0 1 2 3 4 
 cout << lista.front() << endl; 
 //printa 9 na tela 
 cout << lista.back() << endl; 
 // printa 4 na tela 
 cout << lista.size() << endl; 
 //printa o tamanho da lista na tela, que é igual a 10 
 
 for(it = lista.begin(); it!=lista.end();it++){ 
 //printa os numeros pares começando do inicio da lista 
 if(*it %2 == 0){ 
 cout << *it << endl; 
 } 
 } 
 it--; 
 // adiciona dois 11 antes do 4 na lista 
 lista.insert(it,2,11); 
 for(it = lista.begin(); it!=lista.end();it++){ 
 //printa os numeros pares 
 cout << *it << " "; 
 } 
 cout << endl; 
 it--;//retira o 4 da lista 
lista.erase(it);// printa o 3 que agora é o novo ultimo elemento da listacout << 
lista.back() << endl; 
 // limpa a lista inteira 
 lista.clear(); 
 // printará 0 pois a lista está vazia 
 cout << lista.size() << endl; 
} 
 
 
Primeiro vamos começar com os comandos pusb_back () e push_front (). Eles respectivamente 
adicionam o elemento passado no final da lista e no início da lista (nos comentários temos os 
resultados dos prints). Em seguida checamos qual o nosso primeiro elemento e qual o nosso último 
respectivamente. Depois temos a função size () (que também existe para filas e pilhas) que nos retorna 
o tamanho da nossa lista. Agora temos a grande diferença de lista para os demais, em listas podemos 
iterar entre todos os elementos, assim como fazemos em um vetor. Porém para isso precisamos de um 
iterador, o nosso iterator it que nada mais é do que um ponteiro que aponta para elementos de listas 
que tenham o tipo int como dado. 
 os comandos begin() e end() retornam respectivamente um ponteiro para o início e para o fim da 
lista, a diferença é que o ponteiro do begin aponta realmente para o primeiro elemento da lista 
enquanto o end aponta para depois do último elemento. Depois que pritamos todos os numeros 
pares, usamos o it-- para voltarmos a apontar para o último elemento e usamos a função insert(). Essa 
função nos permite inserir elementos na posição anterior a que nosso iterador está apontando. O 
segundo parâmetro é opcional e serve para dizermos quantas cópias daquele elemento queremos 
inserir (O default é 1). Em seguida temos o erase(), que apaga o elemento que nosso iterador está 
apontando. Por fim temos a função clear(), que limpa nossa lista inteira!

Continue navegando

Outros materiais