1
Ponteiros em Pascal Variáveis ponteiros são aquelas que guardam o endereço de outra, possibi-litando 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}
2
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.
3
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.
Alocação de memória
→
A B
PtA
S
PtB
PtS
4
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.
Alocação de memória
→
A 2 B
PtA
S
PtB
PtS
5
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.
Alocação de memória
→
A 2 B 3
PtA
S
PtB
PtS
6
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.
Alocação de memória
→
A 2 B 3
PtA
S
PtB
PtS
7
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.
Alocação de memória
→
A 2 B 3
PtA
S
PtB
PtS
8
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.
Alocação de memória
→
A 2 B 3
PtA
S
PtB
PtS
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.
Alocação de memória
→
A 2 B 3
PtA
S 5
PtB
PtS
10
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.
Alocação de memória
A 2 B 3
PtA
S 5
PtB
PtS
5
11
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.
12
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
→ P
13
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
→P
14
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
→
P
Bom Dia!
15
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
→
P
Bom Dia!
Bom Dia!
16
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
P
OBS: a procedure Dispose libera uma variável criada dinamicamente, para que o SO possa reutilizar
o espaço de memória correspondente.
17
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
18
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 } :
Alocação de memória
→
p
q
r
19
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 } :
Alocação de memória
→
p
q
r
20
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 } :
Alocação de memória
→p
q
r
5
21
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 } :
Alocação de memória
→ p
q
r
5
22
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 } :
Alocação de memória
→
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 } :
Alocação de memória
→
p
q
r
5
24
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 } :
Alocação de memória
→
p
q
r
5
5
25
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 } :
Alocação de memória
→
p
q
r
26
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 } :
Alocação de memória
→
p
q
r
ATENÇÃO: observe que a partir de q:=p;, perdeu-se o acesso à variável criada com
new(q)...Portanto, o manuseio de ponteiros
exige cuidado!
27
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
/
28
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.
29
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia Um inteiro seguido de umalista de inteiros...
30
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia
O ponteiro contido noprimeiro nó aponta para a lista formada
pelos demais nós
Um inteiro seguido de umalista de inteiros...
31
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia
OBS: para se ter acesso aos elementos da lista é necessário que haja sempre uma variável apontando para a “cabeça” da
lista...
Um inteiro seguido de umalista de inteiros...
32
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia
...a partir de cada nó, pode-se ter acesso ao seguinte.
Assim, pode-se percorrer a lista toda.
Um inteiro seguido de umalista de inteiros...
33
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia
Quando a lista estiver vazia o ponteiro que deveria apontar o primeiro elemento,
guarda o valor nil ( / ).
Um inteiro seguido de umalista de inteiros...
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
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;
36
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.
37
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;
OBS: no início da execução do programa só há ponteiros (p,q) para nós. Estes poderão,
dinamicamente, ser empregados para se construir uma lista.
38
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Exemplo de uso: criação de uma lista com dois elementos:
p^.Dadoacesso ao
objeto apontado por p
acesso ao campo
específico
39
p^.Proxacesso ao
objeto apontado por p
acesso ao campo
específico
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Exemplo de uso: criação de uma lista com dois elementos:
40
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→
p
q
41
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→
p
q
42
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→ p
q
7
43
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→
p
q
7
44
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→
p
q
7 3
45
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→
p
q
7 3
46
var p,q: tPtNo;begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil;
:
Alocação de memória
→
p
q
7 3 /
47
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Exemplo 2: dada a lista abaixo, inserir um novo nó entre os dois existentes e armazenar nele o valor 2.
p
7 3 /
q
48
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q
49
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q
50
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q
2
51
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q
2
52
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q
2
53
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q /
2
54
: new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; :
Alocação de memória
→
p
7 3 /
q /
2
OBS: por conveniência, representamos esquematicamente os nós lado a lado.
Entretanto, as suas localização no heappodem ser bastante dispersas...
55
Representação esquemática “ideal”
p
7 3 /
q
2
pq
7
2
3/
heap
.
.
....
...
Uma possível disposição física
56
Dúvidas freqüentes:
1) sempre que precisar de um ponteiro, preciso criá-lo, com “new”?
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.
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á.
59
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.
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}
p
7 3 /
q
61
Dúvidas freqüentes:
p
7 3 /
q
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.
62
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
7 3 /
q
63
Dúvidas freqüentes:
2) ao encerrar um módulo, devo desalocar os ponteiros, empregando ”dispose”?
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 automatica-mente.
65
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 automatica-mente.
>> ao se utilizar dispose(r), é o objeto referenciado por r que será excluído. Não o ponteiro em si.
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?
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.
68
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.
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?
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).
71
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.
72
Dúvidas freqüentes:
Atente bem:
Variáveis globais: seu tempo de vida é o intervalo de tempo de execução do programa.
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.
74
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.
75
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
76
Exemplo: inserir elemento V no final
Duas situações a se considerar:
Lista vazia Lista não vazia
p
/
/ p
...
77
: ... ... ...
Alocação de memória
→
p
V
5
Para lista vazia:
78
: ...? ... ...
Alocação de memória
→
p
V
5
Para lista vazia:
criar novo nó
79
: new(p); ... ...
Alocação de memória
→
p
V
5
Para lista vazia:
80
: new(p); ... ...
Alocação de memória
→
p
V
5
Para lista vazia:
81
: new(p); ...? ...
Alocação de memória
→
p
V
5
Para lista vazia:
guardar ovalor de V
82
: new(p); p^.Dado:=V; ...
Alocação de memória
→
p
V
5
Para lista vazia:
83
: new(p); p^.Dado:=V; ...
Alocação de memória
→
p
V
5
5
Para lista vazia:
84
: new(p); p^.Dado:=V; ...?
Alocação de memória
→
p
V
5
5
Para lista vazia:
caracterizarúltimo nó
85
: new(p); p^.Dado:=V; p^.Prox:=nil;
Alocação de memória
→
p
V
5
5
Para lista vazia:
86
: new(p); p^.Dado:=V; p^.Prox:=nil;
Alocação de memória
→
p
V
5
5 /
Para lista vazia:
87
p
4 7 1 /
Para lista não vazia:
88
Para lista não vazia:
p
4 7 1 /
Condição facilitadora:
fazer com que um ponteiro auxiliar aponte para o último nó...
q
89
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ... ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
90
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ... ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
91
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ... ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
92
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ... ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
93
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ... ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
94
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ... ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
95
: q:= p; while q^.Prox <> nil do q:=q^.Prox; ...? ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
criar novo nó
96
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
97
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); ... ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
98
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); ...? ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
guardar ovalor de V
99
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
100
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; ... ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
5
101
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; ...? ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
5
caracterizarúltimo nó
102
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^Prox:=nil; ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
5
103
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; ...
Alocação de memória
→
p
7 3 /
q
2
r
V
5
5 /
104
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; ...?
Alocação de memória
→
p
7 3 /
q
2
r
V
5
5 /ligar nós
105
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;
Alocação de memória
→
p
7 3 /
q
2
r
V
5
5 /
106
: q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;
Alocação de memória
→
p
7 3
q
2
r
V
5
5 /
107
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;
108
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;
observe as semelhanças...
109
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;
observe as semelhanças...
110
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;
observe as semelhanças...
111
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.
112
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;
113
Listas duplamente encadeadas
p
/.../
Nas listas duplamente encadeadas, os nós são ligados, não só aos posteriores, mas também aos anteriores...
114
Listas duplamente encadeadas
p
/.../
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...
115
Listas duplamente encadeadas
p
/.../
não há nóanterior...
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...
116
Listas duplamente encadeadas
p
/.../
não há nóanterior...
não há nóposterior..
.
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...
117
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
/.../
118
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...
119
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;
120
...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;
121
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.
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...
123
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);
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ó,
será necessário um ponteiro auxiliar
apontando para ele.
p
4 7
q
1 /3 8...
125
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
4 7
q
1 /3 8...
...mas isso será
suficiente??
126
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
4 7
q
1 /3 8...
127
Orientações...
Portanto a condição facilitadora pede também
um ponteiro para o nó anterior...
p
4 7
q
1 /3 8...
r
128
Orientações...
Portanto a condição facilitadora pede também
um ponteiro para o nó anterior...
p
4 7
q
1 /3 8...
r
Agora ficou simples...
129
Orientações...
...a identificação da condição facilitadora
permite a divisão do problema em duas
etapas, reduzindo-se a complexidade...
130
Orientações...2 - Primeiramente, procure a solução para o
caso mais geral. Depois considere as situações especiais...
131
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.