(学习笔记 3)线性表

来源:互联网 发布:日式发型知乎 编辑:程序博客网 时间:2024/06/01 09:08

线性表(List):由零个或多个数据元素组成的有限序列。线性表中数据元素个数称为线性表的长度。长度为0的线性表称为空表。

线性表关键点:
首先,它是一个序列,即元素之间使有个先来后到的;
若元素存在多个,则第一个元素无前驱,而最后一个元素无后继,其他元素都有且只有一个前驱和后继。
线性表强调是有限的,即元素个数有限。

线性表抽象数据类型定义:

●ADT 线性表(List)

●Data

线性表的数据对象集合为{a1,a2,……,an},每个元素的类型均为DataType。其中,除第一个元素a1外,每个元素有且只有一个直接前驱,除了最后一个元素外,每个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。

●Operation

InitList(*L):初始化操作,建立一个空的线性表L。
ListEmpty(L):判断线性表是否为空表,若线性表为空,返回true,否则返回false。
ClearList(*L):将线性表清空。
GetElem(L,i,*e):将线性表L中的第i个位置元素值返回给e。
LocateElem(L,e):在线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号表示成功,否则返回0表示失败。
ListInsert(*L,i,e):在线性表L中第i个位置插入新元素e。
ListDelete(*L,i,*e):删除线性表L中第i个位置元素,并用e返回其值。
ListLength(L):返回线性表L的元素个数。

●endADT

线性表链式存储结构:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXSIZE 20#define OK 1#define ERROR 0typedef int status;typedef int ElemType;//定义结构体typedef struct SqList {    ElemType data[MAXSIZE];    int Length; // 线性表当前长度} sqList;//打印结构体信息status printList(sqList *L){    int i;    printf("data:");    for(i = 0; i < L->Length; i++){        printf("%d---",L->data[i]);    }    printf("\n");    printf("Length = %d\n",L->Length);    return OK;}//用e返回线性表L中第i个数据元素的值status getElem(sqList L, int i, ElemType *e){    if(L.Length == 0 || i < 1 || i > L.Length){        return ERROR;    }    *e = L.data[i-1];    return OK;}/** * 插入元素思路: *  如果插入位置不合理。抛出异常; *  如果线性表长度大于等于数组长度,则抛出异常或动态增加数组容量; *  从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置; *  将要插入元素填入位置i处; *  线性表长度+1。 * 初始条件:顺序线性表L已存在,1 <= i<= listLength(L) * 操作结果:在L中第i个位置之前插入新的数据元素e,L长度+1 */status listInsert(sqList *L, int i, ElemType e){    int k;    //线性表已经满了    if(L->Length == MAXSIZE){        return ERROR;    }    //当i不在范围内时    if(i <1 || i > L->Length+1){        return ERROR;    }    if(i <= L->Length){        //将要插入位置后的元素均向后移动一位        for(k = L->Length-1; k>=i-1; k--){            L->data[k+1] = L->data[k];        }    }    //将新元素插入    L->data[i-1] = e;    L->Length++;    return OK;}/** * 删除元素思路: *  如果删除位置不合理,抛出异常; *  取出删除元素; *  从删除元素位置开始遍历到最后一个元素位置,分别将它们向前移动一个位置; *  表长-1。 * * 初始条件:顺序线性表L已存在,1 <= i<= listLength(L) * 操作结果:删除L的第i个数据元素,并用e返回其值,L长度-1  * /status listDelete(sqList *L, int i, ElemType *e){    int k;    if(L->Length == 0){        return ERROR;    }    if(i < 1|| i > L->Length){        return ERROR;    }    *e = L->data[i-1];    if(i < L->Length){        for(k = i; k <= L->Length; k++){            L->data[k-1] = L->data[k];          }    }    L->Length--;    return OK;}int main(){    ElemType e = 0;    sqList sq = {{1,2,3,4,5},5};    printf("%d\n",sq.Length);    //获取指定位置的元素    getElem(sq,2,&e);    printf("%d\n", e);    //插入元素    listInsert(&sq,3,18);    printList(&sq);    //删除元素    listDelete(&sq,4,&e);    printf("%d\n", e);    printList(&sq);    return 0;}

时间复杂度计算:

插入和删除刚好在最后位置,时间复杂度O(1)
插入和删除刚好在第一个位置,时间复杂度O(n)
所以,平均情况的时间复杂度是O((n-1)/2),即最后得到的是O(n)

结论:

线性表的顺序存储结构,在存、读数据时,不管是哪个位置,时间复杂度都是O(1);
而在插入或删除时,时间复杂度都是O(n)。
因此,它比较适合元素个数比较稳定,不经常插入和删除的元素,更多的是存取数据的应用。

线性表顺序存储结构的优缺点:

优点:
    无须为表示表中元素之间的逻辑关系而增加额外的存储空间;
    可以快速地存取表中任意位置的元素。
缺点:
    插入和删除操作需要移动大量元素;
    当线性表长度变化较大时,难以确定存储空间的容量;
    容易造成存储空间的“碎片”

原创粉丝点击