正文

我所理解的链表052005-12-07 21:08:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/goal00001111/7959.html

分享到:

和动态链表一样,以上操作为线性静态单链表的最基本的操作,其他操作可以是上述操作的组合。

例如要实现“判断结点P是否为链表L的尾结点”操作,函数如下:

int IsLLast(SLink L, Position P)

{

    if(LContaiP(L, P)

        return IsLast(P);

    return 0;

}

如果你仔细的阅读这些代码,你会发现动态链表和静态链表的基本操作的实现算法很相似,游标实现的接口和指针实现是一样的。静态链表可以代替动态链表实现,实际上在程序的其余部分不需要变化,而且速度更快。

同样的让我们用一个实际的例子说明。已知集合A={1,2,3,4,5},B={3,4,5,6,7,8,9,11},求集合A和B的交集的非,即(A-B)并(B-A)。

算法思路是先把集合A和B分别存入两个单向链表LA和LB中,以LB的结点P为研究对象,遍历LA,看是否有与其同值的结点,若有删除与结点P相同的结点,否则把结点P插入链表LA。最后得到的LA就是集合A和B的交集的非。

具体的实现如下所示,因为函数部分已经包含在“线性表的静态单链表基本操作的算法实现“中,所以不做重复,只把其他的部分列出来。程序经过测试,可以运行。

 

#include<stdio.h>

#include<stdlib.h>

#include<malloc.h>

#define MAXSIZE 100//链表的最大长度

typedef int Position;

typedef int SLink;

typedef int ElemType;

typedef struct Node{

    ElemType data;

    Position next;

} SLinkList[MAXSIZE];

 

SLink CreateList(ElemType a[], ElemType len);//用来构造一个链表

。。。//其他函数声明

int main(void)

{

   SLink LA, LB;

    Position P, Pre, S;

   ElemType X, A[5]={1,2,3,4,5}, B[8]={3,4,5,6,7,8,9,1};

 

   InitSpace_SL(Space);//构造一个“模拟空间分配站”,为全局变量

 

   //把集合A和B分别存入两个单向链表LA和LB中

   LA = CreateList(A, 5);

   LB = CreateList(B, 8);

   //以LB的结点P为研究对象,遍历LA,看是否有与其同值的结点,若有删除与结点P相同的结点,否则把结点P插入链表LA。

   P = Space[LB].next;  

    while(P)

   { 

        X = Space[P].data;    //把结点P的值赋给X

        Pre = FindPrefious(X, LA); //判断LA中是否有与P同值的结点 ,返回同值结点的前驱     

        if(Pre)    //若有,删除结点PA                  

            SListDelete(Pre);

        else  //否则

        {

             S = NewSLNode(X); //构造一个数据域为X的新结点,即复制结点P到S

             SListInsert(LA, S);  //把结点S插入链表LA

        }        

        P = Space[P].next;  //继续分析链表中的下一个结点        

    }

    //输出集合A和B的交集的非

    Pre = LA;

      printf("集合A和B的交集的非:\n");

      if(!Space[Pre].next)

        printf("交集的非为空集!");

    else   //输出链表LA的所有结点的值            

          while(Space[Pre].next)

       {

            X = Space[Space[Pre].next].data;

            printf("%d ", X);

            Pre = Space[Pre].next;

        }

     

      system("pause");    

   return 0;

}

 

SLink CreateList(ElemType a[], ElemType len)//用来构造一个链表

{

    SLink L, S;

    int i;

     

    L = InitList(); //构造一个空的线性表

    for(i=0; i<len; i++)

    { 

        S = NewSLNode(a[i]); //构造一个数据域为a[i]的新结点

        SListInsert(L, S); //把新结点S插到头结点后面。

    }

    return L;

 

如果你用静态链表去做“求集合A和B的交集”的题目,你会发现,它的主函数部分和用动态链表做几乎一样。

提问:如果要同时求集合A和B的交集以及交集的非 ,又该怎么办呢?

提示:算法思路是先把集合A和B分别存入两个单向链表LA和LB中,以LB的结点P为研究对象,遍历LA,看是否有与其同值的结点,若有删除与结点P相同的结点,否则把结点P插入链表LA;还要根据情况判断是否执行删除结点P的指令,以便得到A和B的交集。最后得到的LA就是集合A和B的交集的非;而LB是集合A和B的交集。

主函数部分:

int main(void)

{

   SLink LA, LB;

    Position PreA, PreB, S;

   ElemType X, A[5]={1,2,3,4,5}, B[8]={3,4,5,6,7,8,9,11};

 

   InitSpace_SL(Space);//构造一个“模拟空间分配站”,为全局变量

 

   //把集合A和B分别存入两个单向链表LA和LB中

   LA = CreateList(A, 5);

   LB = CreateList(B, 8);

   //以LB的结点P为研究对象,遍历LA,看是否有与其同值的结点,若有删除与结点P相同的结点,否则把结点P插入链表LA。

  //还要根据情况判断是否执行删除结点P的指令

   PreB = LB; //PreB表示结点P的前驱,在所有的操作中,我们都不直接操作被处理的结点,而是操作其前驱  

    while(Space[PreB].next)

   { 

        X = Space[Space[PreB].next].data;  //把结点PB的值赋给X

        PreA = FindPrefious(X, LA); //判断LA中是否有与PB同值的结点 ,返回同值结点的前驱

        if(PreA)  //若有,删除结点PA,继续分析链表中的下一个结点

        {                            

            SListDelete(PreA);

            PreB = Space[PreB].next; 

        }

        else //否则

        {

             S = NewSLNode(X); //构造一个数据域为X的新结点,即复制结点PB到S

             SListInsert(LA, S);//把结点S插入链表LA   

             SListDelete(PreB); //删除链表LB的结点PB

        }              

    }

    //输出集合A和B的交集的非

    PreA = LA;

      printf("集合A和B的交集的非:\n");

      if(!Space[PreA].next)

        printf("交集的非为空集!");

    else          

          while(Space[PreA].next)

       {

            X = Space[Space[PreA].next].data;

            printf("%d ", X);

            PreA = Space[PreA].next;   

        }

   //输出集合A和B的交集 

    PreB = LB;

      printf("\n集合A和B的交集:\n");

      if(!Space[PreB].next)

        printf("交集为空集!");

    else          

          while(Space[PreB].next)

       {

            X = Space[Space[PreB].next].data;

            printf("%d ", X);

            PreB = Space[PreB].next;   

        } 

      system("pause");    

   return 0;

}

阅读(3638) | 评论(5)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册