美文网首页
线性表—顺序表 and 单链表

线性表—顺序表 and 单链表

作者: 土豆骑士 | 来源:发表于2020-04-12 21:23 被阅读0次

    一、线性表——> 顺序存储 ——> 数组

    开辟一块连续的内存来存储数据,(数据之间,逻辑相邻,物理地址相邻 )a[1] a[2] ==> 数组 int a[10] = {…}

    //顺序表结构设计
    typedef struct {
        ElemType *data;//ElemType类型根据实际情况而定,这里假设为int
        int length;
    }Sqlist;
    
    // 顺序表 初始化
    int InitList(Sqlist *L){
        //为顺序表分配一个大小为MAXSIZE 的数组空间
        L->data =  malloc(sizeof(ElemType) * MAXSIZE);
        
        if(!L->data) exit(0);//存储分配失败退出
    
        L->length = 0;//空表长度为0
    
        return 1;
    }
    
    // 顺序表的插入    ==> 在顺序表的i位置插入e。起点从1开始,不是0。
    int ListInsert(Sqlist *L,int i,ElemType e){
        
        //i值不合法判断
        if((i<1) || (i>L->length+1)) return ERROR;
        //存储空间已满
        if(L->length == MAXSIZE) return ERROR;
     
        //插入数据不在表尾,则先移动出空余位置
        if(i <= L->length){
            for(int j = L->length-1; j>=i-1;j--){
           
                //插入位置以及之后的位置后移动1位
                L->data[j+1] = L->data[j];
            }
        }
        
        L->data[i-1] = e;//将新元素e 放入第i个位置上
        
        ++L->length;//长度+1;
        
        return 1;
    }
    
    //顺序表的取值   读取第i个元素
    Int temp = L->data[i-1];
    
    //顺序表删除    ==> 删除第i个数据
    int ListDelete(Sqlist *L,int i){
        
        //线性表为空
        if(L->length == 0) return 0;
        
        //i值不合法判断
        if((i<1) || (i>L->length+1)) return 0;
        
        for(int j = i; j < L->length;j++){
            //被删除元素之后的元素向前移动 ==》 覆盖第i个元素
            L->data[j-1] = L->data[j];
        }
        //表长度-1;
        L->length --;
        
        return 1;
    }
    
    //清空顺序表 顺序线性表L已存在。操作结果:将L重置为空表 */
    int ClearList(Sqlist *L) {
        L->length=0;
        return 1;
    }
    
    //顺序表查找元素并返回位置 (L已存在)
    int LocateElem(Sqlist L,ElemType e)
    {
        if (L.length==0) return 0;
    
        int I;
        for(i=0;i<L.length;i++) {
            if (L.data[i]==e)
                break;
        }
      
        if(i>=L.length) return 0;
        return I+1;
    }
    

    二、单链表——>线性表的链式存储,在内存中是不连续的

    对于非空的线性表和线性结构特点:

    • 存在唯一 被称为“第一个”的数据元素
    • 存在唯一 被称为“最后一个”的数据元素
    • 存在唯一 被称为“第一个”的数据元素

    一对一,有头尾,有前驱和后继。

    单链表节点

    单链表节点
    //定义结点
    typedef struct Node{
        ElemType data;    //数据域
        struct Node *next;//带有后继的指针域
    }Node;
    typedef struct Node * LinkList;//
    

    单链表逻辑状态——带有头结点的链表(头结点数据域为NULL)

    单链表插入
    //初始化单链表线性表     指针L指向头结点
    int InitList(LinkList *L) {//*L == Node **L
        
        *L = (LinkList)malloc(sizeof(Node)); //产生头结点,并使用L指向此头结点
        
        if(*L == NULL) return 0;    //存储空间分配失败
        
        (*L)->next = NULL;//将头结点的指针域置空
        
        return 1;
    }
    

    单链表插入——逻辑

    单链表删除
    //单链表插入    在list 第i位置插入元素e
    int ListInsert(LinkList *L,int i,ElemType e){
     
        int j = 1;
        LinkList p,s;
        p = *L;
        
        while (p && j<i) { //寻找第i-1个结点
            p = p->next;
            ++j;
        }
        
        //第i个元素不存在
        if(!p || j>i) return 0;
        
        
        s = (LinkList)malloc(sizeof(Node));//生成新结点s
        
        s->data = e;//将e赋值给s的数值域
       
        s->next = p->next; //将p的后继结点赋值给s的后继
       
        p->next = s; //将s赋值给p的后继
        
        return 1;
    }
    

    单链表删除元素 —逻辑

    单链表删除
    //单链表删除元素  删除L的第i个数据元素,并用e返回其值
    int ListDelete(LinkList *L,int i,ElemType *e){
        
        int j = 1;
        LinkList p,q;
        p = *L;
        
        while (p && j<i) {//查找第i-1个结点,p指向该结点
            p = p->next;
            j += 1;
        }
        
        if (!(p->next) || (j>i-1)) return  0; //当i>n 或者 i<1 时,删除位置不合理
        
        q = p->next;//q指向要删除的结点
        
        p->next = q->next;//将q的后继赋值给p的后继
       
        *e = q->data; //将q结点中的数据给e
        
        free(q);//让系统回收此结点,释放内存;
        
        return 1;
    }
    

    **单链表取值 **

    //单链表取值   获取第i个元素, 用e返回L中第i个数据元素的值
    int GetElem(LinkList L,int i,ElemType *e){
        
        int j = 1;
        LinkList p;
        
        //p不为空,且计算j不等于i,则循环继续
        while (p && j<=i) {
            p = p->next; //p指向下一个结点
            ++j;
        }
        
        if(!p || j < i) return 0;//如果p为空或者j>i,则返回0
        
        *e = p->data;//e = p所指的结点的data
        return 1;
    }
    

    单链表前插入法 —逻辑

    单链表前插入法
    //单链表前插入法     随机产生n个元素值,建立带表头结点的单链线性表L
    void CreateListHead(LinkList *L, int n){
        
        LinkList p;
        
        //建立1个带头结点的单链表
        *L = (LinkList)malloc(sizeof(Node));
        (*L)->next = NULL;
        
        for(int i = 0; i < n;i++) {//循环前插入随机数据
            
            p = (LinkList)malloc(sizeof(Node));//生成新结点
           
            p->data = i; //i赋值给新结点的data
            
            p->next = (*L)->next;//p->next = 头结点的L->next
            
            (*L)->next = p; //将结点P插入到头结点之后;
            
        }
    }
    

    单链表后插入法

    单链表后插入
    //单链表后插入法    随机产生n个元素值,建立带表头结点的单链线性表L
    void CreateListTail(LinkList *L, int n){
        
        LinkList p,r;
     
        //建立1个带头结点的单链表
        *L = (LinkList)malloc(sizeof(Node));
        //r指向尾部的结点
        r = *L;
        
        for (int i=0; i<n; i++) {
            p = (Node *)malloc(sizeof(Node)); //生成新结点
            p->data = I;
            
            r->next = p;//将表尾终端结点的指针指向新结点
           
            r = p; //将当前的新结点定义为表尾终端结点
        }
        
        //将尾指针的next = null
        r->next = NULL;
    }
    

    链表结构与顺序存储结构对比

    存储分配方式

    • 顺序存储结构用一段连续的存储单元依次存储性表的数据元素。
    • 单链表采用链式存储结构,用一组任意的存储单元存放线性表的数据元素。

    时间性能

    • 查找——顺序存储O(1), 单链表O(n)。
    • 插入和删除—— 存储结构需要平均移动半个表长的元素,时间O(n);单链表查找某位置后的指针后,插入删除为O(1)。

    空间性能:

    • 顺序存储结构需要预先分配存储空间,分太大,浪费空间,分小了,易溢出。
    • 单链表不需要预先分配存储空间,只要有就可以分配,元素个数不受限制。

    相关文章

      网友评论

          本文标题:线性表—顺序表 and 单链表

          本文链接:https://www.haomeiwen.com/subject/siqimhtx.html