计算机考研之数据结构-线性表

数据结构-线性表

抽象描述

定义

  1. 元素为单个的数据元素
  2. 元素个数有限
  3. 元素数据类型相同
  4. 有逻辑上的先后关系
    • 每个元素有且仅有一个直接前驱
    • 除最后一个元素以外,每个元素有且仅有一个直接后继

操作

InitList(&L),构造一个空的线性表。
Length(L),返回线性表长度。
LocateElem(L,e),根据值查找元素。
GetElem(L,i),根据索引查找元素。
ListInsert(&L,i,e),在指定索引处插入元素。
ListDelete(&L,i,&e),删除指定索引处的元素,并使用引用返回删除元素的值。
PrintList(L),顺序输出线性表索引的元素。
Empty(L),判断线性表是否为空。
DestroyList,销毁线性表。

顺序表

线性表的顺序存储结构称之为顺序表。
相对于链表,顺序表最重要的特征是随机访问,即顺序表可以使用O(1)的时间找到指定索引的元素。

定义

静态定义:

#define MAX 50
typedef struct{
    int data[MAX];
    int length;
}SqList;

动态定义:

#define InitSize 100
typedef struct{
    int *data; //指向动态分配数组的指针
    int MAX, length;
}SqList;

L.data = (int*)malloc(sizeof(int)*InitSize) //c的动态分配方式
L.data = new int[InitSize] //c++的动态分配方式

操作

这里分清楚次序与数组下标或者说索引,次序从1开始,数组下标从0开始,我们这里默认i是索引。MAX

插入,复杂度O(n)。

bool ListInsert(SqList &L, int i, int e){
    if(!(i>=0 && i<L.length)) return false;
    if(L.length>=MAX) return false;
    for(int j=L.length; j>=i+1; j--) 
        L.data[j] = L.data[j-1];
    L.data[i] = e
    L.length++;
    return true;
}

删除,复杂度O(n)。

bool ListDelete(SqList &L, int i, int &e){
    if(!(i>=0 && i<L.length)) return false;
    e = L.data[i];
    for(int j=i-1, j<L.length-1; j++){
        L.data[j-1]=L.data[j];
    }
    L.length--;
    return true;
}

值查找

bool LocateElem(SqList L, int e, int& i)
    int j;
    for(j=0; i<L.length; i++)
        if(L.data[j] == e){
            i = j;
            return true;
        }
    return false;
}

单链表

线性表的链式存储结构称之为链表。

定义

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode, *LinkList;

通常使用头指针来表示一个链表。为了操作上的方便有的时候也会在头指针之前附加一个头结点。
头结点一般不存储数据。
下面的所有操作都是以有头结点为例子的。

操作

  1. 头插法建立链表
    c LinkList CreatList(LinkList &L){ LNode *s; int x; L=(LinkList)malloc(sizeof(LNode)); //创建头结点 L->next=NULL; while(scanf("%d", &x)){ s=(LNode*)malloc(sizeof(LNode)); s->data=x; s->next=L->next; L->next=s; } return L; }

  2. 尾插法
    c LinkList CreatList(LinkList &L){ LNode *s, *r; int x; // r为指向表尾的指针 L=(LinkList)malloc(sizeof(LNode)); //创建头结点 L->next=NULL; while(scanf("%d", &x)){ s=(LNode*)malloc(sizeof(LNode)); s->data=x; r->next=s; r=s; } r->next=NULL; // 尾结点置空 return L; }

  3. 序号索引
    c LNode* GetElem(LinkList L, int i){ if(i<0) return NULL; if(i==0) return L; int j=1; LNode* p=L->next; while(p&&j<i){ p=p->next; j++; } return p; }

  4. 插入结点
    c p=GetElem(L, i-1); s->next=p->next; p->next=s;

  5. 删除结点
    c p=GetElem(L,i-1); q=p->next; p->next=q->next; free(q);

双链表

定义

typedef struct DNode{
    int data;
    struct DNode *prior;
    struct DNode *next;
}

操作

  1. 插入,在p后插入一个s节点
    c s->next=p->next; p->next->prior=s; s->prior=p; p->next=s;

  2. 删除一个p之后的q节点
    c p->next=q->next; q->next->prior=p; free(q);

小结

关于顺序表和链表的一些重要的比较:

  1. 存取方式
    • 顺序表可以顺序存储,也可以随机存储,但是链表只能顺序存储。
  2. 增删查操作
    • 链表的单独的增删操作都是O(1),索引查找为O(n)。而顺序表反之,索引查找O(1),增删操作O(n)。

所以,顺序表适合查找场景,链表适合频繁增删的场景。

习题

暂空。

转载于:https://www.cnblogs.com/nevermoes/p/9872848.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值