zoukankan      html  css  js  c++  java
  • 线性表

    一、线性表

    顺序存储:顺序表

    链式存储:单链表,双链表,循环链表---->利用指针实现

    &表示c++中的引用,如果传入的变量是指针类型的变量
    在c中采用指针的指针也可以同样效果。

    1、顺序表

    1.1、顺序表节点定义:

    顺序存储类型的定义:
    #define MaxSize 50//定义线性表的最大长度
    typedef struct{
        ElemType data[MaxSize];//顺序表的元素
        int length;//顺序表的当前长度
    }SeqList;//顺序表的类型定义
    一维数组可以静态分配,也可以动态分配。
    #define InitSize 100//表长度的初始定义
    typedef struct{
        ElemType *data;//指示动态分配数组的指针
        int MaxSize,length;//数组的最大容量和当前个数
    }SeqList

    动态分配数组的C语句: L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);

    顺序表所占存储空间=表长*sizeof(元素的类型) 动态分配数组的C++语句: L.data=new ElemType[InitSize];

    顺序表的特点:随机访问。也就是通过首地址和元素序号可以在O(1)时间访问指定的元素。 由于顺序表的逻辑上相邻的元素物理上也相邻,所以插入和删除需要移动大量元素。

    1.2、顺序表基本操作的实现(复杂度O(n))

    1、插入操作
    在第i个位置上插入新元素e。
    
    bool ListInsert(SeqList &L,int i,ElemType e)
    {
        if(i<1||i>L.length+1)return false;
        if(L.length>=MaxSize)return false;
        for(int j=L.length;j>=i;j--)//将第i个元素后面的元素先进行后移
            L.data[j]=L.data[j-1];
        L.data[i-1]=e;//在位置i处放入e
        L.length++;//线性表长度加1
        return true;
    }

    1.3、删除操作(复杂度O(n))

    删除L中第i个位置的元素,将被删除的元素用引用变量e返回

    bool ListDelete(SeqList &L,ElemType &e)
    {
        if(i<1||i>L.length)return false;
        e=L.data[i-1];//将被删除的元素赋值给e
        for(int j=i;j<L.length;j++)//将第i个位置之后的元素前移
            L.data[j-1]=L.data[j];
        L.length--;//线性表长度减1
        return true;
    }

    2、单链表

    单链表的节点类型定义:
    typedef struct LNode{
        ElemType data;//数据域
        struct LNode *next;//指针域
    }LNode,*LinkList;

     单链表是非随机存取的。因为查找某个特定的节点时,需要从表头开始遍历,依次查找

    头节点和头指针:

    不管带不带头节点,头指针始终指向链表的第一个节点。而带头节点链表的第一个节点,节点不存储信息的。

    无论链表是否为空,头指针始终指向头节点的非空指针

    2.1、采用头插法

    将新节点s插入到当前链表的表头。也就是头节点后面

    LinkList CreateList(LinkList &L)
    {
        LNode *s;
        int x;
        L=(LinkList)malloc(sizeof(LNode));//创建头节点
        L->next=null;//初始为空链表
        scanf("%d",&x)//输入节点的值
        while(x!=999)
        {
            s=(LNode*)malloc(sizeof(LNode));创建新的节点
            s->data=x;
            s->next=L->next;
            L->next=s;
            scanf("%d",&x);
        }
        return L;
    }

    2.2、采用尾插法

    头插法虽然建立链表简单,但是生成的链表的节点次序和输入的顺序相反。
    希望输入顺序一样,可以采用尾插法。
    思想:每次将新节点插入到当前链表的表尾上,所以必须要增加一个尾指针r。让它始终指向链表的尾节点。

    LinkList CreateList(LinkList &L)
    {
        int x;
        LNode *s,*r;//r为尾指针,s指向即将插入的新节点
        L=(LinkList)malloc(sizeof(LNode));//创建头节点。
        scanf("%d",&x);//输入节点的值
        while(x!=999)
        {
            s=(LNode*)malloc(sizeof(LNode));
            s->data=x;
            r->next=s;
            r=s;//把s赋给r,此时刚插入的新节点s成了尾指针
        }
        r->next=null;//尾指针置空
        return L;
    }

    2.3、按序号查找节点

    在单链表中从第一个节点出发,顺着指针next域一一往下搜索。直到找到第i个节点为止。

    LNode *GetElem(LinkList L,int i)
    {
        int flag=1;//计数,初始为1个
        LNode *p=L->next;//头节点指针赋给p
        if(i==0)return L;//如果i=0,返回头节点
        if(i<1)return null;//如果i无效,则返回null
        while(p&&j<i)//从第1个节点开始找,查找第i个节点
        {
            p=p->next;
            j++
        }
        return p;//返回第i个节点的指针。
    }
    //复杂度为O(n)

    2.4、按值来查找节点

    从单链表中第一个节点处出发,从前往后比较表中节点数据域的值,然后返回这个节点的指针。

    LNode *LocateElem(LinkList L,ElemType e)
    {
        LNode *p=L->next;
        while(p!=null&&p->data!=e)//从第一个节点开始找data域为e的节点
            p=p->next;
        return p;//找到后返回该节点指针。
    }

    2.5、插入节点操作

    插入节点时将值为x的新节点插入到单链表的第i个位置上。所以插入之前要检查位置的合法性。
    然后在找到它的前驱,也就是第i-1个节点,然后进行插入操作。
    所以首先调用方法GetElem(L,i-1);获取到i-1位置的指针

    LNode *p=GetElem(L,i-1);
    s->next=p->next;//先后连
    p->next=s;//在前连
    //插入操作复杂度为O(1)

    2.6、删除节点操作

    删除第i个节点。同理还是检查位置的合法性,然后查找第i-1个位置节点
    也即是它的前驱,然后删除
    所以还是调用方法GetElem(L,i-1);

    LNode *p=GetElem(L,i-1);
    LNode *s;
    s=p->next;//让s指针指向打算删除的节点
    p->nexts->next;//将s节点断开。
    free(s);//释放节点空间

    3、双链表

    3.1、节点类型定义:

    typedef struct DNode
    {
        ElemType data;//数据域
        struct DNode *prior,*next;//前驱和后继指针
    }DNode,*DLinkList;

    3.2、双链表的插入操作:

    在p节点之后插入新节点s

    //核心代码
    s->next=p->next;
    p->next->prior=s; 
    s->prior=p;
    p->next=s;

    3.2、双链表的删除操作

    p->next=p->next->next;
    p->next->next->prior=p;
    free(p->next);
    
    或者令s=p->next;
    p->next=s->next;
    s->next->prior=p;
    free(s);
  • 相关阅读:
    微信小程序 生命周期
    ftp uploadFileAction(重要)
    java FTP 上传下载删除文件
    httpsession
    db2 blob EMPTY_BLOB()
    java blob
    java session getCreationTime()
    eclipse 查看源代码
    java file类
    Vue.js 和 MVVM 小细节
  • 原文地址:https://www.cnblogs.com/drq1/p/9472900.html
Copyright © 2011-2022 走看看