zoukankan      html  css  js  c++  java
  • 链表

    1、链表思想:每个节点都存储分为数据和地址两个方面。

    数据是链表记录的内容,地址分为此节点的地址和它的前驱和后缀地址。

    通过,每次通过地址来时先链表的遍历,查找,删除等操作。

    2、链表分类

    如果是单链表,就是只有后继,只能向后移动,因此,为了方便查找链表的某个节点,常常设置头结点。

    双向链表:同时具有前驱和后缀,可以向前或者向后移动。

    循环链表:最后的单元反过来,直至第一个单元,可以有表头,也可以是双向链表

    3、链表的具体实现操作:

    (1)单链表的实现

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<stdlib.h>
    
    #define ERRROR -1
    
    //链表的结构 
    typedef int ElementType;
    struct Node{
        ElementType x;
        struct Node *next;
    };
    typedef struct Node* List;
    typedef List Position;
    
    //链表的操作
    List MakeEmpty(List L);
    int IsEmpty(List L);
    int IsLast(Position p,List L);
    Position Find(ElementType x,List L);
    void Delete(ElementType x,List L);
    Position FindPrevious(ElementType x,List L);
    void Insert(ElementType x,List L,Position p);
    void DeleteList(List L);
    
    
    //测试是否为空表
    int IsEmpty(List L)
    {
        return L->next==NULL;
    }
    
    //测试是否为最后一个节点 
    int IsLast(Position p,List L)
    {
        return p->next==NULL;
    }
    
    //初始化
    List Init(List L)
    {
        L = (List)malloc(sizeof(struct Node));
        if(L==NULL)
        {
            printf("Out of Space!
    ");
        }
        else L->next=NULL;
        return L;
    }
     
    //查找函数 
    Position Find(ElementType x,List L)
    {
        List p=L;
        while(p!=NULL&&p->x!=x)
        {
            p=p->next;
        }
        return p;
    } 
    
    //删除链表 
    void Delete(ElementType x,List L)
    {
        List tp,p;
        p=FindPrevious(x,L);
        if(!IsLast(p,L))
        {
            tp=p->next;
            p->next=tp->next;
            free(tp);
        }
    }
    
    //查找前一个元素 
    Position FindPrevious(ElementType x,List L)
    {
        Position p=L;
        while(p->next!=NULL&&p->next->x!=x)
        {
            p=p->next;
        }
        return p;
    }
    
    //插入
    void Insert(ElementType x,List L,Position p)
    {
        List tp;
        tp=(List)malloc(sizeof(struct Node));
        if(tp==NULL)
        {
            printf("Out of Space!!!
    ");
        }
        tp->x=x;
        tp->next=p->next;
        p->next=tp; 
    } 
    
    //删除
    void DeleteList(List L)
    {
        List p,tp;
        tp=L->next;
        L->next=NULL;
        while(tp!=NULL)
        {
            p=tp->next;
            free(tp);
            tp=p;
        }
    }
    
    void Print(List L)
    {
        List p=L->next;
        while(p!=NULL)
        {
            printf("%d ",p->x);
            p=p->next;
        }
        printf("
    ");
    }
    
    int main(void)
    {
        List L,p;
        L=Init(L);
        p=L;
        int i,x,n;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,L,p);
            p=p->next;
        }
        Print(L);
        
        printf("将7插入3的前面:
    ");
        p=FindPrevious(3,L);
        Insert(7,L,p);
        Print(L);
        
        printf("删除4:
    ");
        Delete(4,L);
        Print(L);
        
        return 0;
    }
    View Code

    (2)双向链表

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    struct Node{
        int data;
        struct Node *Pre,*Rear;
    };
    typedef struct Node* DoList;
    
    DoList Init(DoList L) //初始化 
    {
        L=(DoList)malloc(sizeof(struct Node));
        L->Pre=NULL;
        L->Rear=NULL;
        return L;
    }
    
    int IsEmpty(DoList L) //判断是否为空 
    {
        if(L->Pre==NULL&&L->Rear==NULL) return 1;
        return 0;
    }
    
    int IsLast(DoList L,DoList p) //判断最后一个元素 
    {
        if(p->Pre!=NULL&&p->Rear==NULL) return 1;
        return 0;
    }
    
    DoList FindPrevious(int x,DoList L) //找到前一个元素 
    {
        DoList p=L;
        while(p->Rear!=NULL&&p->Rear->data!=x)
        {
            p=p->Rear;
        }
        return p;
    }
    
    void Insert(int x,DoList L,DoList p) //插入某个元素 
    {
        DoList tp=(DoList)malloc(sizeof(struct Node));
        if(tp==NULL)
        {
            printf("Out of Space!!!
    ");
        }
        //printf("%d
    ",x);
        tp->data=x;
        //先前再后
        tp->Pre=p;
        tp->Rear=p->Rear;  
        if(p->Rear==NULL) p->Rear=tp; //这里要注意,因为可能存在p->Rear==NULL的情况。 
        else
        {
            p->Rear->Pre=tp;
            p->Rear=tp;
        }
    }
    
    void Delete(int x,DoList L) //删除某个元素 
    {
        DoList p,tp;
        p=FindPrevious(x,L);
        tp=p->Rear;
        p->Rear=tp->Rear;
        tp->Rear->Pre=p;
        free(tp);
    }
    
    void Print(DoList L) //正序输出 
    {
        DoList p=L->Rear;
        while(p!=NULL)
        {
            printf("%d ",p->data);
            p=p->Rear;
        }
        printf("
    ");
    }
    
    void RePrint(DoList L) //逆序输出
    {
        DoList p,tp;
        p=L->Rear;
        while(!IsLast(L,p)) p=p->Rear;
        while(p->Pre!=NULL)
        {
            printf("%d ",p->data);
            p=p->Pre;
        }
        printf("
    ");
    }
    
    void DeleteList(DoList L) //输出链表 
    {
        DoList p,tp;
        p=L->Rear;
        L->Rear=NULL;
        while(p!=NULL)
        {
            tp=p->Rear;
            free(p);
            p=tp;
        }
    }
    
    int main(void)
    {
        DoList L,p;
        L=Init(L);
        p=L;
        int n,x,i;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,L,p);
            p=p->Rear;
        }
        Print(L);
        
        p=FindPrevious(3,L);
        Insert(7,L,p);
        //DeleteList(L); 
        RePrint(L);
        return 0;
    }
    View Code

    (3)循环链表

    循环单链表

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    struct Node{
        int data;
        struct Node *next;
    }; 
    typedef struct Node* CyList;
    
    CyList Init(CyList L)
    {
        L=(CyList)malloc(sizeof(struct Node));
        L->data=-1;
        L->next=L;
        return L;
    }
    
    int Empty(CyList L)
    {
        return L->next==L;
    }
    
    CyList FindPrevious(int x,CyList L)
    {
        CyList p=L;
        while(p->next->data!=x&&p->next!=NULL)
        {
            p=p->next;
        }
        return p;
    }
    
    void Insert(int x,CyList L,CyList p)
    {
        CyList tp=(CyList)malloc(sizeof(struct Node));
        tp->data=x;
        tp->next=p->next;
        p->next=tp;
    }
    
    void Delete(int x,CyList L)
    {
        CyList p,tp;
        p=FindPrevious(x,L);
        if(p->next!=NULL)
        {
            tp=p->next;
            p->next=tp->next;
            delete tp;
        }
    }
    
    void Print(CyList L)
    {
        CyList p=L->next;
        while(p!=L)
        {
            printf("%d ",p->data);
            p=p->next;
        } 
        printf("
    ");
    }
    
    void DeleteList(CyList L)
    {
        CyList p,tp;
        p=L->next;
        L->next=L;
        while(p!=L)
        {
            tp=p->next;
            delete p;
            p=tp;
        }
    }
    
    void DoPrint(CyList L)
    {
        CyList p=L->next;
        int tim=0;
        while(1)
        {
            if(tim==1&&p==L) break;
            if(p==L&&tim==0)
            {
                p=p->next;
                tim=1;continue;
            }
            printf("%d ",p->data);
            p=p->next;
        }
    }
    
    int main(void)
    {
        CyList L,p;
        L=Init(L);
        p=L;
        int n,i,x;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,L,p);
            p=p->next;
        }
        p->next=L;
        Print(L);
        
        p=FindPrevious(3,L);
        Insert(7,L,p);
        Print(L);
        
        Delete(2,L);
        Print(L);
        
        DoPrint(L);
        return 0;
    }
    View Code

    循环双向链表

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    struct Node{
        int data;
        struct Node *Pre,*Rear;
    };
    typedef struct Node* DuList;
    
    DuList Init(DuList L)
    {
        L=(DuList)malloc(sizeof(struct Node));
        L->Pre=L;
        L->Rear=L;
        return L;
    }
    
    int IsEmpty(DuList L)
    {
        if(L->Pre==L&&L->Rear==L) return true;
        return false;
    }
    
    void Insert(int x,DuList L,DuList p)
    {
        DuList tp=(DuList)malloc(sizeof(struct Node));
        tp->data=x;
        tp->Pre=p;
        tp->Rear=p->Rear;
        p->Rear->Pre=tp;
        p->Rear=tp;
    }
    
    DuList FindPrevious(int x,DuList L)
    {
        DuList p=L;
        while(p->data!=x) p=p->Rear;
        return p->Pre;
    }
    
    void Delete(int x,DuList L)
    {
        DuList p,tp;
        p=FindPrevious(x,L);
        tp=p->Rear;
        p->Rear=tp->Rear;
        tp->Rear->Pre=p;
    }
    
    void Print(DuList L)
    {
        DuList p=L;
        printf("%d ",p->data);
        p=p->Rear;
        while(p!=L)
        {
            printf("%d ",p->data);
            p=p->Rear;
        }
        printf("
    ");
    }
    
    void DeleteList(DuList L)
    {
        DuList p=L->Rear,tp=L;
        delete tp;
        L=NULL;
        while(p!=NULL)
        {
            tp=p->Rear;
            delete tp;
            p=tp;
        }
    }
    
    int main(void)
    {
        int n,x,i;
        DuList p,L;
        scanf("%d",&n);
        scanf("%d",&x);
        p=Init(p);
        p->data=x;
        L=p;
        for(i=1;i<n;i++)
        {
            scanf("%d",&x);
            Insert(x,L,p);
            p=p->Rear;
        }
        Print(L);
        
        Delete(3,L);
        Print(L);
        
        p=FindPrevious(2,L);
        Insert(7,L,p);
        Print(L);
        
        return 0; 
    }
    View Code

    注意:1、如果对p->next进行操作,p一定不能为空,否则会出问题。

    2、双向链表中的插入操作,先对tp的前驱操作,再对tp的后驱操作。

    3、循环链表的最大特征就是首尾相连,空表时,自己指向自己(指的是单链表的头结点,如果是双向链表,直接让第一个节点的前驱指向最后一个节点,

    最后一个节点的后驱指向第一个节点就行了)。

    书后练习:

    3.2:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<time.h>
    
    struct Node{
        int id,data;
        struct Node* next;
    };
    typedef struct Node* List;
    
    List Init(List L)
    {
        L=(List)malloc(sizeof(struct Node));
        L->next=NULL;
        return L;
    }
    
    void Insert(int x,List L,List p)
    {
        List tp=(List)malloc(sizeof(struct Node));
        tp->data=x;
        if(tp==NULL)
        {
            printf("Out of Space!!!
    ");
        }
        tp->next=p->next;
        p->next=tp;
    }
    
    int FindNum(List L,int pos)
    {
        List tp,p=L->next;
        int i=1;
        while(p!=NULL&&i!=pos)
        {
            i++;p=p->next;
        }
        return p->data;
    }
    
    void PrintLots(List L,List p)
    {
        List tp=p->next;
        while(tp!=NULL)
        {
            printf("%d ",FindNum(L,tp->data));
            tp=tp->next;
        }
        printf("
    ");
    }
    
    void Print(List L)
    {
        List p=L->next;
        while(p!=NULL)
        {
            printf("%d ",p->data);
            p=p->next;
        }
        printf("
    ");
    }
    
    int main(void)
    {
        int begintime=0,endtime;
        List L1,p,L2;
        L1=Init(L1);
        L2=Init(L2);
        p=L1;
        int n,x,i;
        printf("创建L序列:
    ");
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,L1,p);
            p=p->next;
        }
        Print(L1);
        
        printf("创建P序列:
    ");
        p=L2;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,L2,p);
            p=p->next;
        }
        Print(L2);
        
        PrintLots(L1,L2);
        endtime=clock();
        printf("程序运行时间为:%dmm
    ",endtime-begintime);
        return 0;
    }
    View Code
  • 相关阅读:
    PTA L2-023 图着色问题-前向星建图 团体程序设计天梯赛-练习集
    PTA L2-004 这是二叉搜索树吗?-判断是否是对一棵二叉搜索树或其镜像进行前序遍历的结果 团体程序设计天梯赛-练习集
    PTA L2-006 树的遍历-二叉树的后序遍历+中序遍历,输出层序遍历 团体程序设计天梯赛-练习集
    HDU1166敌兵布阵(线段树单点更新)
    洛谷P1019——单词接龙(DFS暴力搜索)
    洛谷P1309——迷宫(傻瓜DFS)
    CodeForce-791B Bear and Friendship Condition(并查集)
    傻子都能懂的并查集题解——HDU1232畅通工程
    洛谷P1309——瑞士轮(归并排序)
    洛谷P1583——魔法照片(结构体排序)
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10017542.html
Copyright © 2011-2022 走看看