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

数据结构-线性表

抽象描述

定义

  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. 头插法建立链表

    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. 尾插法

    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. 序号索引

    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. 插入结点

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

    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节点

    s->next=p->next;
    p->next->prior=s;
    s->prior=p;
    p->next=s;
    
  2. 删除一个p之后的q节点

    p->next=q->next;
    q->next->prior=p;
    free(q);
    

小结

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

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

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

习题

暂空。

posted @ 2018-10-29 19:59  NeverMoes  阅读(353)  评论(0编辑  收藏  举报