美文网首页
数据结构.线性表

数据结构.线性表

作者: ChenL | 来源:发表于2020-04-02 21:48 被阅读0次

    数据结构分为线性结构和非线性结构。今天要探讨的是线性结构的存储方式线性表。

    本文讲述的是 顺序表、单链表

    线性表的特点

    • 存在唯⼀的⼀个被称作”第⼀个”的数据元素;
    • 存在唯⼀的⼀个被称作”最后⼀个"的数据元素
    • 除了第⼀个之外,结构中的每个数据元素均有⼀个前驱
    • 除了最后⼀个之外,结构中的每个数据元素都有⼀个后继.

    一、顺序表:

    #include <stdio.h>
    #include "stdlib.h"
    #include "math.h"
    #include "time.h"
    
    
    #define MAXSIZE 100
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    /* ElemType类型根据实际情况而定,这里假设为int */
    typedef int ElemType;
    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    typedef int Status;
    
    /*线性结构使用顺序表的方式存储*/
    
    //顺序表结构设计
    typedef struct {
        ElemType *data;
        int length;
    }Sqlist;
    

    1.1 顺序表初始化

    Status InitList(Sqlist *L){
        //为顺序表分配一个大小为MAXSIZE 的数组空间
        L->data =  malloc(sizeof(ElemType) * MAXSIZE);
        //存储分配失败退出
        if(!L->data) exit(ERROR);
        //空表长度为0
        L->length = 0;
        return OK;
    }
    

    1.2 顺序表的插入

    /*
     初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
     操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
     */
    Status 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];
            }
        }
        
        //将新元素e 放入第i个位置上
        L->data[i-1] = e;
        //长度+1;
        ++L->length;
        
        return OK;
        
    }
    

    1.3 顺序表的取值

    Status GetElem(Sqlist L,int i, ElemType *e){
        //判断i值是否合理, 若不合理,返回ERROR
        if(i<1 || i > L.length) return  ERROR;
        //data[i-1]单元存储第i个数据元素.
        *e = L.data[i-1];
        
        return OK;
    }
    

    1.4 顺序表删除

    /*
     初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
     操作结果: 删除L的第i个数据元素,L的长度减1
     */
    Status ListDelete(Sqlist *L,int i){
        
        //线性表为空
        if(L->length == 0) return ERROR;
        
        //i值不合法判断
        if((i<1) || (i>L->length)) return ERROR;
        
        for(int j = i; j < L->length;j++){
            //被删除元素之后的元素向前移动
            L->data[j-1] = L->data[j];
        }
        //表长度-1;
        L->length --;
        
        return OK;
        
    }
    

    1.5 清空顺序表

    /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
    Status ClearList(Sqlist *L)
    {
        L->length=0;
        return OK;
    }
    

    1.6 判断顺序表清空

    /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
    Status ListEmpty(Sqlist L)
    {
        if(L.length==0)
            return TRUE;
        else
            return FALSE;
    }
    

    1.7 获取顺序表长度ListEmpty元素个数

    int ListLength(Sqlist L)
    {
        return L.length;
    }
    

    1.8 顺序输出List

    /* 初始条件:顺序线性表L已存在 */
    /* 操作结果:依次对L的每个数据元素输出 */
    Status TraverseList(Sqlist L)
    {
        int i;
        for(i=0;i<L.length;i++)
            printf("%d\n",L.data[i]);
        printf("\n");
        return OK;
    }
    

    1.9 顺序表查找元素并返回位置

    /* 初始条件:顺序线性表L已存在 /
    /
    操作结果:返回L中第1个与e满足关系的数据元素的位序。 /
    /
    若这样的数据元素不存在,则返回值为0 */

    int LocateElem(Sqlist L,ElemType e)
    {
        int i;
        if (L.length==0) return 0;
        
        for(i=0;i<L.length;i++)
        {
            if (L.data[i]==e)
                break;
        }
      
        if(i>=L.length) return 0;
        return i+1;
    }
    

    二、单链表:

    在单链表中,数据都是有节点组成的,节点有数据域和指针域组成的。 截屏2020-04-0221.39.12.png

    假设要在单链表的两个数据元素a和b之间插⼊入一个数据元素x,先找到指向a指针p. x->next = p->next,p->next = x。


    image.png

    要删除次第i个元素:
    1.找到第i-1个元素的节点p
    2.要删除的节点q,q=p->next
    3.修改p的后继,使其指向q的后继,同时,删除q节点,释放占用的内存


    image.png
    单链表前插入
    2020-04-0221.43.37.png
    单链表后插入
    2020-04-0221.43.57.png
    #include <stdio.h>
    #include "string.h"
    #include "ctype.h"
    #include "stdlib.h"
    #include "math.h"
    #include "time.h"
    
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    
    #define MAXSIZE 20 /* 存储空间初始分配量 */
    
    typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
    
    //定义结点
    typedef struct Node{
        ElemType data;
        struct Node *next;
    }Node;
    
    typedef struct Node * LinkList;
    
    

    2.1 初始化单链表线性表

    Status InitList(LinkList *L){
        
        //产生头结点,并使用L指向此头结点
        *L = (LinkList)malloc(sizeof(Node));
        //存储空间分配失败
        if(*L == NULL) return ERROR;
        //将头结点的指针域置空
        (*L)->next = NULL;
        
        return OK;
    }
    

    2.2 单链表插入
    /*
    初始条件:顺序线性表L已存在,1≤i≤ListLength(L);
    操作结果:在L中第i个位置之后插入新的数据元素e,L的长度加1;
    */

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

    2.3 单链表取值
    /*
    初始条件: 顺序线性表L已存在,1≤i≤ListLength(L);
    操作结果:用e返回L中第i个数据元素的值
    */

    Status GetElem(LinkList L,int i,ElemType *e){
        
        //j: 计数.
        int j;
        //声明结点p;
        LinkList p;
        
        //将结点p 指向链表L的第一个结点;
        p = L->next;
        //j计算=1;
        j = 1;
       
        //p不为空,且计算j不等于i,则循环继续
        while (p && j<i) {
            
            //p指向下一个结点
            p = p->next;
            ++j;
        }
        
        //如果p为空或者j>i,则返回error
        if(!p || j > i) return ERROR;
        
        //e = p所指的结点的data
        *e = p->data;
        return OK;
    }
    

    2.4 单链表删除元素
    /*
    初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
    操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1
    */

    Status ListDelete(LinkList *L,int i,ElemType *e){
        
        int j;
        LinkList p,q;
        p = (*L)->next;
        j = 1;
        
        //查找第i-1个结点,p指向该结点
        while (p->next && j<(i-1)) {
            p = p->next;
            ++j;
        }
        
        //当i>n 或者 i<1 时,删除位置不合理
        if (!(p->next) || (j>i-1)) return  ERROR;
        
        //q指向要删除的结点
        q = p->next;
        //将q的后继赋值给p的后继
        p->next = q->next;
        //将q结点中的数据给e
        *e = q->data;
        //让系统回收此结点,释放内存;
        free(q);
        
        return OK;
    }
    
    /* 初始条件:顺序线性表L已存在 */
    /* 操作结果:依次对L的每个数据元素输出 */
    Status ListTraverse(LinkList L)
    {
        LinkList p=L->next;
        while(p)
        {
            printf("%d\n",p->data);
            p=p->next;
        }
        printf("\n");
        return OK;
    }
    
    /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
    Status ClearList(LinkList *L)
    {
        LinkList p,q;
        p=(*L)->next;           /*  p指向第一个结点 */
        while(p)                /*  没到表尾 */
        {
            q=p->next;
            free(p);
            p=q;
        }
        (*L)->next=NULL;        /* 头结点指针域为空 */
        return OK;
    }
    

    3.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));
           
            //i赋值给新结点的data
            p->data = i;
            //p->next = 头结点的L->next
            p->next = (*L)->next;
            
            //将结点P插入到头结点之后;
            (*L)->next = p;
            
        }
    }
    

    3.2 单链表后插入法
    /* 随机产生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;
        
    }
    
    

    相关文章

      网友评论

          本文标题:数据结构.线性表

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