回 帖 发 新 帖 刷新版面

主题:[讨论]链表怎么用

[color=FF0000][/color][size=1][/size]
呆呆的初行者请教了

   我说这链表怎么用啊?
不要笑话啊,欢迎回贴

回复列表 (共4个回复)

沙发

加分哦!
1、定义指针类型
  在Turbo Pascal中,指针变量中存放的某个存储单元的地址,即指针变量指向某个存储单元。一个指针变量仅能指向某一种类型的存储单元,这种数据类型是在指针类型的定义中确定的,称为指针的基类型。指针类型定义如下:
   类型名=^基类型名;
例如:type q=^integer;
   var a,b,c:q;
  说明q是一指向整型存储单元的指针类型,其中"^"为指针符。a,b,c均定义为指针变量,分别可以指向一个整型存储单元。
  指针也可直接定义为:
    var a,b,c:^integer;
  同时,指针也可以指向结构类型的存储单元:记录类型、数组或字符串等。
例如:type person=record
        name:string[10];
        sex:(male,female);
        age:20..70
      end;
   var pt:^person;
  pt为指向记录类型person的指针变量。
2、动态变量
  引用一个指针指向的动态存储单元即动态变量的形式如下:
    指针变量名^
例如:p^、q^、r^
以下语句把整数5存放到p所指向的动态变量p^ 中去:
p^:=5;
以下语句把p所指向的p^中的值赋给整型变量i:
i:=p^;
如果指针变量p并未指向任何存储单元,则可用下列赋值语句:
p:=nil;
其中nil是Turbo Pascal保留字,表示“空” 
3、对动态变量的操作
  在Turob Pascal程序中,动态变量不能由var直接定义而是通过调用标准过程new建立的。过程形式为:
    new(指针变量名);
  如果有下列变量定义语句:
   var p:^integer;
  仅仅说明了p是一个指向整型变量单元的指针变量,但这个整型单元并不存在,在指针变量p中还没有具体的地址值。在程序中必须通过过程调用语句:new(p);才在内存中分配了一个整型变量单元,并把这个单元的地址放在变量p中,一个指针变量只能存放一个地址。在同一时间内一个指针只能指向一个变量单元。当程序再次执行new(p)时,又在内存中新建立了一个整型变量单元,并把新单元的地址存放在p中,从而丢失了旧的变量单元的地址。
  为了节省内存空间,对于一些已经不使用的现有动态变量,应该使用标准过程dispose予以释放。过程形式为:dispose(指针变量名);为new(指针变量名)的逆过程,其作用是释放由指针变量所指向的动态变量的存储单元。例如在用了new(p)后在调用dispose(p),则指针p所指向的动态变量被撤销,内存空间还给系统,这时 p的值为 nil。

4、例题
例1:输入两个数,要求先打印大数后打印小数的方式输出,用动态变量做。
type
   intptr=^integer;
var
   p1,p2: intptr;

procedure swap(var q1,q2: intptr);
var p:intptr;
begin
   p:=q1;q1:=q2;q2:=p;
end;

begin
   new(p1);new(p2);
   writeln('input 2 data: ');readln(p1^,p2^);
   if p1^<p2^ then swap(p1, p2);
   writeln('output 2 data: ',p1^:4,p2^:4);
end.

例2、指向字符串的指针:P103
例3、指向数组的指针:pointer.pas
例4、指针综合举例:pointer1.pas

5、链表与指针

链表是动态数据结构的一种基本形式。如果我们把指针所指的一个存贮单元叫做结点,那么链表就是把若干个结点链成了一串。我们把链表叫做动态数据结构,是因为链表中的结点可增可减,可多可少,可在中间任意一个位置插入和删除。
下面就是一个链表:
 
每个链表有两个域,一个是数据域,一个是指向下一个结点的指针域。最后一个结点的指针域为NIL,NIL表示空指针。
┌──┬──┐
│data│next│
└──┴──┘
       data域--存放结点值的数据域
       next域--存放结点的直接后继的地址的指针域
注意:
     ①链表通过每个结点的指针域,将线性表的n个结点按其逻辑顺序链接在一起的。
     ②每个结点只有一个指针域的链表称为单链表。
【例】线性表(bat,cat,eat,fat,hat,jat,lat,mat)的单链表示如示意图
 
存储方式:
 

要定义一个链表,每个结点要定义成记录类型,而且其中有一个域为指针。
TYPE
   POINT=^PP;
   PP=RECORD
       DATA:STRING[5];
       LINK:POINT;
       END;
VAR  P1:POINT;
在这个定义中,定义了一个指针变量P1。每个结点有两个域,一个是数据域,一个是指针域,数据域是字符串类型的。这种定义中,指针中有记录,记录中有指针,形成一种类似与递归形式的定义。
下面来看一下如何定义下图的链表:
 
   有:P1,P2,P3,P4属于POINT类型。
(1)建立第一个结点
NEW(P1);
P1^.DATA:=D1;
 (2) 建立第二个结点,并把它接在P1的后面
     NEW(P2);
     P2^.DATA:=D2;
     P1^.LINK:=P2;
 (3) 建立第三个结点,并把它接在P2的后面.
     NEW(P3);
     P3^.DATA:=D3;
     P2^.LINK:=P3;
(4) 建立最后一个结点,并把它接在P3的后面.
NEW(P4);
P4^.DATA:=D4;
P4^.LINK:=NIL;
P3^.LINK:=P4;
  
例1 建立一个有10个结点的链表,最后输出该链表。
            分析:本程序设有三个指针,P2指向正在操作的结点,P1指向P2前一个结点,K一直指向第一个结点。
type
   point=^pp;
   pp=record
         data:string[5];
         link:point;
      end;

var
   p1,p2,k:point;
   i:integer;

begin
   {产生新结点P1,作为链表的头}
   new(p1);
   writeln('input data');
   readln(p1^.data);
   {指针K指向链表头}
   k:=p1;
   {用循环产生9个新结点,每个结点都接在上一个结点之后}
   for i:=1 to 9 do begin
      new(p2);
      writeln('input data');
      readln(p2^.data);
      p1^.link:=p2;
      p1:=p2;
      end;
   {给最后一个结点的LINK域赋空值NIL}
   p2^.link:=nil;
   {从链表头开始依次输出链表中的DATA域}
   while k^.link<>nil do begin
      write(k^.data,'->');
      k:=k^.link;
      end;
   writeln(k^.data);
end.
在本程序里,输出链表的过程就是一个链表的遍历。给出一个链表的头结点,依次输出后面每一个结点的内容,指针依次向后走的语句用k:=k^.link  来实现。

板凳

加分哦!
例2 读入一批数据,遇负数时停止,将读入的正数组成先进先出的链表并输出。
分析:首先应定义指针类型,结点类型和指针变量,读入第一个值,建立首结点,读入第二个值,判断它是否大于零,若是,建立新结点。
{建立先进先出链表}
type
   point=^node;
   node=record
           data:real;
           link:point
        end;

var
   head,last,next:point;
   x:real;
begin
   {读入第一个值,建立首结点}
   read(x);
   new(head);
   head^.data:=x;
   last:=head;
   {读入第二个值}
   read(x);
   while x>=0 do begin
      {建立新结点}
      new(next);
      next^.data:=x;  {链接到表尾}
      last^.link:=next; {指针下移}
      last:=next;      {读入下一个值}
      read(x);
      end;
   writeln;          {表尾指针域置NIL}
   last^.link:=NIL;  {输出链表}
   next:=head;
   while next<>nil do begin
      write(next^.data:6:1);
      next:=next^.link;
      end;
   writeln;
end.
例3 读入一批数据,遇负数时停止,将读入的正数组成先进后出的链表并输出。
{建立先进后出链表}
type
   point=^node;
   node=record
           data:real;
           link:point
        end;

var
   head,last,next:point;
   x:real;

begin
   {初始准备}
   head:=nil;
   read(x);  {读入第一个数}
   while x>=0 do begin
   {建立一个新结点}
      new(next);
      next^.data:=x;  {链接到表首}
      next^.link:=head;{指针前移}
      head:=next;      {读入下一个数}
      read(x);
      end;
   {输出链表}
   next:=head;
   while next<>nil do begin
      write(next^.data:6:1);
      next:=next^.link
      end;
   writeln;
end.
在链表中插入结点
在一个已建好的链表中插入一个结点,这是一种常见算法。当我们找到插入点后,就断开原先的链接,将新结点插入进来。
 
如图所求示:要把P3的结点插入到P2之前,应该这样操作:
(1)P1,P2之间的链断开,改为P1指向P3:        P1^.LINK:=P3;
(2)将P2,P3连接起来:        P3^.LINK:=P2;
于是,P3所指向的结点便插入进来了。
 
例4 插入一结点的过程
type
   node_ptr=^node_type;
   node_type=record
                key:longint;
                next:node_ptr;
             end;

var
   i:longint;
   head,t:node_ptr;

procedure makelist;
begin
   new(head);
   head^.key:=maxlongint;
   head^.next:=nil;
end;

procedure insert(var x:node_ptr;y:longint);
var
   p:node_ptr;
begin
   new(p);
   p^.next:=x^.next;
   p^.key:=y;
   x^.next:=p;
end;

begin
   makelist;
   for i:=1 to 10 do insert(head,i);
   t:=head;
   while t^.next<>nil do begin
      t:=t^.next;
      write(t^.key,' ');
      end;
   writeln;
end.
删除一个结点
要在一个链表中删去一个结点,首先在链表中找到该结点,将其前面的指针与该点断开,直接接到后面的结点,再用DISPOSE  命令将P3结点空间释放。如图,删除P3结点:
 
删除语句如下:
P1^.LINK:=P3^.LINK;
DISPOSE(P3);
 

3 楼

例5 删除结点的过程
type
   node_ptr=^node_type;
   node_type=record
                key:longint;
                next:node_ptr;
             end;

var
   i:longint;
   head,t:node_ptr;

procedure makelist;
begin
   new(head);
   head^.key:=maxlongint;
   head^.next:=nil;
end;

procedure insert(var x:node_ptr;y:longint);
var
   p:node_ptr;
begin
   new(p);
   p^.next:=x^.next;
   p^.key:=y;
   x^.next:=p;
end;

procedure delete(k:longint);
var
   p,q:node_ptr;
begin
   p:=head;
   while p^.next<>nil do begin
      if p^.next^.key=k then begin
         q:=p^.next;
         p^.next:=p^.next^.next;
         dispose(q);
         end;
      p:=p^.next;
      end;
end;

begin
   makelist;
   for i:=1 to 10 do insert(head,i);
   delete(10);
   delete(5);
   delete(1);
   t:=head;
   while t^.next<>nil do begin
      t:=t^.next;
      write(t^.key,' ');
      end;
   writeln;
end.
例6 在一个有序链表中装有1到100共100个整数。要求任意输入100以内的一个整数,把它从链表中删除。
                TYPE point=^pp;
                     pp=record
                        data:integer;
                        link:point;
                        end;
                VAR
                   p1,p2,p3,k:point;
                   i:integer;
                BEGIN
                  {建立一个1――100的整数的有序链表}
                   new(p1);
                   k:=p1;
                   p1^.data:=1;
                   for i:=2 to 100 do
                     begin
                      new(p2);
                      p2^.data:=i;
                      p1^.link:=p2;
                      p1:=p2;
                    end;
p2^.link:=nil;
{输入要删除的结点的DATA值}
                   new(p3);
                   writeln('input p3');
                   readln(p3^.data);
                   P1:=k;p2:=k;
                    {P2指针查找P3结点}
                   while p2^.data<p3^.data do
p2:=p2^.link;
                    {P1指针定位于P3之前}
                   while p1^.link<>p2 do
                     p1:=p1^.link;
                   p1^.link:=p2^.link;
                   dispose(p3);{将P3结点的空间释放}
                    {输出修改后的链表}
                   repeat
                        write(k^.data,'->');
                        k:=k^.link;
                    until k^.data=100;
                    write(k^.data);
                END.

4 楼

加分啊

我来回复

您尚未登录,请登录后再回复。点此登录或注册