正文

我所理解的链表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; }

阅读(3882) | 评论(5)


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

评论

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