Ponteiros em Pascal Variáveis ponteiros são aquelas que guardam o endereço de outra, possibilitando o acesso a seu conteúdo. Declaração em Pascal: var ptint: ^integer; {ponteiro para uma variável inteira } ptreal: ^real; {ponteiro para uma variável real} 1
Operador @ Operador unário que retorna o endereço de uma variável program soma; var S,A,B:integer; PtS,PtA,PtB : ^integer; begin readln(a,b); PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; writeln('resultado: ',PtS^); end. 2
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. A PtA B PtB PtS S 3
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA A 2 B PtB PtS S 4
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB A 2 B 3 PtS S 5
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB A 2 B 3 PtS S 6
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB A 2 B 3 PtS S 7
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB A 2 B 3 PtS S 8
Alocação de memória program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB A 2 B 3 PtS S 5 9
program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. 5 Alocação de memória PtA PtB A 2 B 3 PtS S 5 10
procedure New( ) Cria dinamicamente (em tempo de execução) uma nova variável e faz uma variável ponteiro apontar para ela. type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. 11
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P 12
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P 13
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P Bom Dia! 14
Bom Dia! Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P Bom Dia! 15
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P OBS: a procedure Dispose libera uma variável criada dinamicamente, para que o SO possa reutilizar o espaço de memória correspondente. 16
Um ponteiro recebendo o valor de um outro Um ponteiro recebe o valor de um outro através do comando de atribuição Ex: q:= p; Quando isso acontece, ele passa a apontar para o mesmo objeto que o outro aponta 17
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 18
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 19
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 5 20
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 5 21
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 5 22
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 5 23
var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : 5 Alocação de memória p q r 5 24
Alocação de memória var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 25
Alocação de memória ATENÇÃO: observe que a partir de q:=p;, perdeu-se o acesso à variável criada com var new(q) p,q,r: Portanto, ^integer; o manuseio de ponteiros begin exige cuidado! new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q);{ou p ou r } : p q r 26
Listas lineares Em várias situações em programação temos que lidar com listas de elementos cujo tamanho exato é desconhecido. Estratégias: Empregar um agregado homogêneo (array) superdimensionado. 1 2 3 N-1 N Empregar seqüências de células (nós) que contêm dois elementos: um valor e um ponteiro para o próximo nó. p / 27
Quando adotar uma ou outra solução? Agregado homogêneo: quando pudermos determinar com segurança o tamanho máximo. Listas encadeada: - quando for difícil estimar o tamanho máximo com segurança; e/ou - quando se desejar maior agilidade nas inclusões ou exclusões de novos elementos. 28
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: Lista vazia; Um inteiro seguido de uma lista de inteiros. Lista vazia / p Um inteiro seguido de uma lista de inteiros p 4 7 1 9 / 29
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: O ponteiro contido no Lista vazia; primeiro nó aponta para a lista formada Um inteiro seguido pelos demais uma nóslista de inteiros. Lista vazia / p Um inteiro seguido de uma lista de inteiros p 4 7 1 9 / 30
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: OBS: para se ter acesso aos elementos da Lista lista vazia; é necessário que haja sempre uma variável apontando para a cabeça da Um inteiro seguido lista de uma lista de inteiros. Lista vazia / p Um inteiro seguido de uma lista de inteiros p 4 7 1 9 / 31
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: a partir de cada nó, pode-se ter Lista vazia; acesso ao seguinte. Um Assim, inteiro pode-se seguido percorrer de uma a lista toda. de inteiros. Lista vazia / p Um inteiro seguido de uma lista de inteiros p 4 7 1 9 / 32
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: Quando a lista estiver vazia o ponteiro que Lista vazia; deveria apontar o primeiro elemento, Um inteiro guarda seguido o valor de uma nil ( lista / ). de inteiros. Lista vazia / p Um inteiro seguido de uma lista de inteiros p 4 7 1 9 / 33
Definição (recursiva) de um nó: type tdado = integer; { ou real, char, etc.} tptno = ^tno; tno = record Dado:tDado; Prox :tptno; end; var p,q: tptno; 34
Definição (recursiva) de um nó: type tdado = integer; { ou real, char, etc.} tptno = ^tno; tno = record Dado:tDado; Prox :tptno; end; var p,q: tptno; 35
Semanticamente, uma definição semelhante seria type tdado = integer; { ou real, char, etc.} tno = record Dado:tDado; Prox :^tno; end; var p,q: tptno; Contudo, as regras de Pascal exigem a definição na forma anteriormente exposta. 36
Definição OBS: no início (recursiva) da execução de um do nó: programa só há ponteiros (p,q) para nós. Estes poderão, dinamicamente, ser empregados tdado = integer; { ou real, char, etc.} para se construir uma lista. type tptno = ^tno; tno = record Dado:tDado; Prox :tptno; end; var p,q: tptno; 37
Exemplo de uso: criação de uma lista com dois elementos: var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p^.dado acesso ao acesso ao objeto apontado campo por p específico 38
Exemplo de uso: criação de uma lista com dois elementos: var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p^.prox acesso ao acesso ao objeto apontado campo por p específico 39
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p q 40
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p q 41
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p 7 q 42
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p 7 q 43
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p 7 q 3 44
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p 7 q 3 45
Alocação de memória var p,q: tptno; begin new(p); p^.dado := 7; new(q); q^.dado := 3; p^.prox := q; q^.prox := nil; : p 7 q 3 / 46
Exemplo 2: dada a lista abaixo, inserir um novo nó entre os dois existentes e armazenar nele o valor 2. : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p 7 q 3 / 47
Alocação de memória : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p q 7 3 / 48
Alocação de memória : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p q 7 3 / 49
Alocação de memória : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p 2 q 7 3 / 50
Alocação de memória : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p 2 q 7 3 / 51
Alocação de memória : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p 2 q 7 3 / 52
Alocação de memória : new(q); q^.dado := 2; q^.prox := p^.prox; p^.prox := q; q := nil; : p 2 q / 7 3 / 53
Alocação de memória OBS: por conveniência, representamos : esquematicamente os nós lado a lado. new(q); Entretanto, as suas localização no heap q^.dado podem := 2; ser bastante dispersas q^.prox := p^.prox; p^.prox := q; q := nil; : p q / 7 2 3 / 54
Representação esquemática ideal p q p q 7 2 3 / 3 / 7 2 h e a p Uma possível disposição. física. 55
Dúvidas freqüentes: 1) sempre que precisar de um ponteiro, preciso criá-lo, com new? 56
Dúvidas freqüentes: 1) sempre que precisar de um ponteiro, preciso criá-lo, com new? Não. >> o simples fato de se declarar o ponteiro (variável global, local ou parâmetro) faz com que o sistema aloque memória para ele. 57
Dúvidas freqüentes: 1) sempre que precisar de um ponteiro, preciso criá-lo, com new? Não. >> o simples fato de se declarar o ponteiro (variável global, local ou parâmetro) faz com que o sistema aloque memória para ele. >> new() deve ser usado para criar um objeto (sem identificação) para o qual o ponteiro usado como argumento apontará. 58
Dúvidas freqüentes: 1) sempre que precisar de um ponteiro, preciso criá-lo, com new? Não. >> o simples fato de se declarar o ponteiro (variável global, local ou parâmetro) faz com que o sistema aloque memória para ele. >> new() deve ser usado para criar um objeto (sem identificação) para o qual o ponteiro usado como argumento apontará. >> o tipo do objeto criado dependerá do tipo de ponteiro. 59
Dúvidas freqüentes: Caso seja executado o código abaixo, p. ex new(q); q := p; {apontar para o primeiro elemento da lista} p q 7 3 / 60
Dúvidas freqüentes: Caso seja executado o código abaixo, p. ex new(q); q := p; {apontar para o primeiro elemento da lista} a) criou-se um elemento, fazendo-se q apontar para ele. p q 7 3 / 61
Dúvidas freqüentes: Caso seja executado o código abaixo, p. ex new(q); q := p; {apontar para o primeiro elemento da lista} a) criou-se um elemento, fazendo-se q apontar para ele. b) perdeu-se esse elemento p q 7 3 / 62
Dúvidas freqüentes: 2) ao encerrar um módulo, devo desalocar os ponteiros, empregando dispose? 63
Dúvidas freqüentes: 2) ao encerrar um módulo, devo desalocar os ponteiros, empregando dispose? Não. >> no encerramento do módulo, todas as variáveis locais e parâmetros (inclusive ponteiros) são desalocados automaticamente. 64
Dúvidas freqüentes: 2) ao encerrar um módulo, devo desalocar os ponteiros, empregando dispose? Não. >> no encerramento do módulo, todas as variáveis locais e parâmetros (inclusive ponteiros) são desalocados automaticamente. >> ao se utilizar dispose(r), é o objeto referenciado por r que será excluído. Não o ponteiro em si. 65
Dúvidas freqüentes: 3) quando se cria um objeto (comando new) empregando-se um ponteiro, só se pode empregar aquele ponteiro para desalocar aquele objeto? 66
Dúvidas freqüentes: 3) quando se cria um objeto (comando new) empregando-se um ponteiro, só se pode empregar aquele ponteiro para desalocar aquele objeto? Não. >> o nó não pertence ao ponteiro que foi empregado na sua criação. 67
Dúvidas freqüentes: 3) quando se cria um objeto (comando new) empregando-se um ponteiro, só se pode empregar aquele ponteiro para desalocar aquele objeto? Não. >> o nó não pertence ao ponteiro que foi empregado na sua criação. >> qualquer ponteiro que esteja apontando para certo objeto pode ser usado para a sua desalocação. 68
Dúvidas freqüentes: 4) ao empregar-se uma variável local (ponteiro) para alocar um objeto, esse objeto será também local, desaparecendo portanto após a execução daquele módulo? 69
Dúvidas freqüentes: 4) ao empregar-se uma variável local (ponteiro) para alocar um objeto, esse objeto será também local, desaparecendo portanto após a execução daquele módulo? Não. >> o objeto criado é alocado na área de memória denominada heap (área própria para alocação dinâmica). 70
Dúvidas freqüentes: 4) ao empregar-se uma variável local (ponteiro) para alocar um objeto, esse objeto será também local, desaparecendo portanto após a execução daquele módulo? Não. >> o objeto criado é alocado na área de memória denominada heap (área própria para alocação dinâmica). >> variáveis de heap não são nem globais nem locais. 71
Dúvidas freqüentes: Atente bem: Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa. 72
Dúvidas freqüentes: Atente bem: Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa. Variáveis locais: seu tempo de vida é o intervalo de execução do módulo onde foram declaradas. 73
Dúvidas freqüentes: Atente bem: Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa. Variáveis locais: seu tempo de vida é o intervalo de execução do módulo onde foram declaradas. Variáveis de heap: seu tempo de vida é arbitrário, dependendo de uma criação (new) e da posterior desalocação. 74
Manuseio de listas encadeadas Para tratar de forma genérica todas as possíveis manipulações de uma lista encadeada, é definido um conjunto de rotinas. Exemplos: inserir/excluir um elemento no início inserir /excluir um elemento no final inserir /excluir um elemento na enésima posição calcular a soma dos elementos 75
Exemplo: inserir elemento V no final Duas situações a se considerar: Lista vazia Lista não vazia / p p / 76
Para lista vazia: Alocação de memória : p V 5 77
Para lista vazia: Alocação de memória V : 5? criar novo nó p 78
Para lista vazia: Alocação de memória : new(p); p V 5 79
Para lista vazia: Alocação de memória : new(p); p V 5 80
Para lista vazia: Alocação de memória V : 5 new(p);? guardar o valor de V p 81
Para lista vazia: Alocação de memória : new(p); p^.dado:=v; p V 5 82
Para lista vazia: Alocação de memória : new(p); p^.dado:=v; p V 5 5 83
Para lista vazia: Alocação de memória : new(p); p^.dado:=v;? caracterizar último nó p V 5 5 84
Para lista vazia: Alocação de memória : new(p); p^.dado:=v; p^.prox:=nil; p V 5 5 85
Para lista vazia: Alocação de memória : new(p); p^.dado:=v; p^.prox:=nil; p V 5 5 / 86
Para lista não vazia: p 4 7 1 / 87
Para lista não vazia: p q 4 7 1 / Condição facilitadora: fazer com que um ponteiro auxiliar aponte para o último nó 88
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; p q r V 5 7 2 3 / 89
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; p q r V 5 7 2 3 / 90
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; p q r V 5 7 2 3 / 91
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; p q r V 5 7 2 3 / 92
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; p q r V 5 7 2 3 / 93
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; p q r V 5 7 2 3 / 94
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox;? p q r V 5 criar novo nó 7 2 3 / 95
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); p q r V 5 7 2 3 / 96
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); p q r V 5 7 2 3 / 97
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r);? p q r V 5 guardar o valor de V 7 2 3 / 98
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; p q r V 5 7 2 3 / 99
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; p q r V 5 7 2 3 / 5 100
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v;? p q V 5 r caracterizar último nó 7 2 3 / 5 101
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^prox:=nil; p q r V 5 7 2 3 / 5 102
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; p q r V 5 7 2 3 / 5 / 103
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil;? p q r V 5 ligar nós 7 2 3 / 5 / 104
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; q^.prox:=r; p q r V 5 7 2 3 / 5 / 105
Alocação de memória : q:= p; while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; q^.prox:=r; p q V 5 r 7 2 3 5 / 106
Juntando as duas situações {lista vazia} new(p); p^.dado:=v; p^.prox:=nil; {lista não vazia} while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; q^.prox:=r; 107
Juntando as duas situações {lista vazia} new(p); p^.dado:=v; p^.prox:=nil; observe as semelhanças {lista não vazia} while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; q^.prox:=r; 108
Juntando as duas situações {lista vazia} new(p); p^.dado:=v; p^.prox:=nil; observe as semelhanças {lista não vazia} while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; q^.prox:=r; 109
Juntando as duas situações {lista vazia} new(p); p^.dado:=v; p^.prox:=nil; observe as semelhanças {lista não vazia} while q^.prox <> nil do q:=q^.prox; new(r); r^.dado:=v; r^.prox:=nil; q^.prox:=r; 110
Juntando as duas situações procedure InsereNo(var p: tptno; V : tdado); var q,r: tptno; begin end; Como existe a possibilidade de p mudar seu conteúdo, ele é passado por referência. 111
Juntando as duas situações procedure InsereNo(var p: tptno; V : tdado); var q,r: tptno; begin new(r); r^.dado:=v; r^.prox:=nil; if p = nil then p:= r else begin q:= p; while q^.prox <> nil do q:=q^.prox; q^.prox:=r; end; end; 112
Listas duplamente encadeadas Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores p / / 113
Listas duplamente encadeadas Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2 ponteiros p / / 114
Listas duplamente encadeadas Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2 ponteiros não há nó anterior / p / 115
Listas duplamente encadeadas Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores Portanto, a estrutura do nó deve possuir 2 ponteiros não há nó anterior / p não há nó posterior... / 116
Listas duplamente encadeadas Estrutura: tdado = integer; { ou real, char, etc.} tptno = ^tno; tno = record Esq: tptno Dado: tdado; Dir: tptno; end; var p,q: tptno; p / / 117
Listas duplamente encadeadas Operações: Partindo-se das operações com listas de encadeamento simples, basta fazer alguns ajustes. p é necessário considerar que há dois ponteiros / / 118
Considere a rotina de inserção no final para encadeamento simples: procedure InsereNoFinal(var p:tptno; V: tdado); var q,r: tptno; begin new(r); r^.dado:=v; r^.prox:=nil; if p = nil then p:= r else begin q:= p; while q^.prox <> nil do q:=q^.prox; q^.prox:=r; end; end; 119
ajustes necessários: procedure InsereNoFinal(var p:tptno; V: tdado); var q,r: tptno; begin new(r); r^.dado:=v; r^.dir:=nil; if p = nil then begin p:= r; r^.esq:= nil; end; else begin q:= p; while q^.dir <> nil do q:=q^.dir; q^.dir:=r; r^.esq := q; end; end; 120
Exercícios (encadeamento simples e duplo): Construir módulos que façam as seguintes operações: 1- Inserir no início da lista; 2- Excluir o primeiro elemento; 3- Excluir o último elemento; 4- Inserir na enésima posição; 5- Excluir o enésimo nó; 6- Fornecer o tamanho da lista 7- Fornecer a soma dos elementos da lista. 121
Orientações 1- Sempre pla neje antes de codi fi car. a) faça um esquema visual do problema! -> use lápis e borracha, pois os ponteiros são dinâmicos 122
Orientações 1- Sempre pla neje antes de codi fi car. a) faça um esquema visual do problema! -> use lápis e borracha, pois os ponteiros são dinâmicos b) atenção especial à list a de parâme tros : quais são os parâmetros necessários, seus tipos, mecanismo de passagem (valor ou referência); 123
Orientações c) procure identificar co ndiçõe s fa ci li tadoras para a solução de um problema. Por exemplo, para excluir o enésimo nó, será necessário um ponteiro auxiliar apontando para ele. p q 4 7 3 8 1 / 124
Orientações c) procure identificar co ndiçõe s fa ci li tadoras para a solução de um problema. Por exemplo, para excluir o enésimo nó, mas isso será necessário um ponteiro auxiliar será apontando para ele. suficiente?? p q 4 7 3 8 1 / 125
Orientações Não. No processo de exclusão, p. ex., do nó que guarda o valor 8, será necessário encadear o anterior com o sucessor p q 4 7 3 8 1 / 126
Orientações Portanto a condição facilitadora pede também um ponteiro para o nó anterior p r q 4 7 3 8 1 / 127
Orientações Portanto a condição facilitadora pede também um ponteiro para o nó anterior Agora ficou simples p r q 4 7 3 8 1 / 128
Orientações a identificação da condição facilitadora permite a divisão do problema em duas etapas, reduzindo-se a complexidade 129
Orientações 2 - Primeiramente, procure a solução para o caso mais geral. Depois considere as situações especiais 130
Orientações 2 - Primeiramente, procure a solução para o caso mais geral. Depois considere as situações especiais Ex: Inserir na enésima posição: raciocinar para lista não vazia e inserção no meio da lista. Depois considerar - e se a lista estiver vazia? - e se a posição for a primeira (ou a última)? Quando a solução geral não funcionar para esses casos, inserir o tratamento especial. 131