《大话数据结构》第三章 线性表

来源:互联网 发布:淘宝店铺退款怎么退款 编辑:程序博客网 时间:2024/06/04 17:45

**

第三章 线性表

**
有序、有限、最多一个前驱和一个后继
基本操作:
InitList(&L)
ListEmpty(L)
ClearList(&L)
GetElem(L, i, &e)
LocateElem(L, e)
ListInsert(&L, i, e)
ListDelete(&L, i, &e)
ListLength(L)

线性表集合A和B的合并操作

/*将所有的在线性表Lb中,但不在La中的数据元素插入到La中*/void union(List *La, List Lb){    int La_len, Lb_len;    ElemType e;    La_len = ListLength(La);    Lb_len = ListLength(Lb);    for(int i=1; i<=Lb_len; i++){        GetElem(Lb,i,&e);        if(!LocateElem(La,e))        ListInsert(&La,++La_len,e);     }} 

线性表的顺序存储的结构代码

#define MaxSize 20typedef int ElemTypetypedef struct{    Elemtype data[MaxSize];    int Length;}SqList;

随机存取结构,其存取时间性能为O(1)

获得元素的操作

#define OK 1#define ERROR 0#define TRUE 1#define FASLE 0typedef int Status;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;}

插入操作

Statue ListInsert(SqList *L, int i, ElemType e){    int k;    if(L->Length == MaxSize)            return ERROR;    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;}

删除操作

Statue 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-1; k<L->Length-1; k++)            L->data[k]=L->data[k+1]     }    L->Length--;    return OK;}

存取快,插入删除慢


链式存储结构
这里写图片描述
头指针是必要元素,头指针均不为空,但头结点不一定是链表的必要元素,头结点是为了操作的统一和方便设立的,放在第一元素节点前,数据域一般放链表长度
若线性表为空表,则头结点的指针域为空。

单链表的结构代码

typedef struct Node{       //结点由数据域和指针域组成    ElemType data;    struct Node *next;} Node, *LinkList;

单链表的读取

Status GetElem(LinkList L, int i, ElemType *e){    //LinkList即为Node*    int j;    LinkList p;    p=L->next;  //让p指向第一个结点,L理解为头结点的指针    j=1;    //j为计数器    while(p && j<i) //p不为空且计数器j还没等于i时,循环继续    {        p=p->next;        j++;        }    if(!p || j>i)        return ERROR;    *e=p->data;    return OK; }

单链表的插入

Status LinkInsert(LinkList *L, int i, ElemType e){    int j;    LinkList p, s;    p=*L;    j=0;    while(!p && j<i-1){        p=p->next;        ++j;    }    if(!p || j>i-1)        return ERROR;    s=(LinkList)malloc(sizeof(Node));    s->data = e;    s->next = p->next;    p->next = s;    return OK; }

单链表的删除

Status ListDelete(LinkList *L, int i, ElemType *e){    int j;    LinkList p, q;    p=*L;    j=0;    while(p && j<i-1){        p=p->next;        ++j;     }    if(!p || j>i-1)        return ERROR;    if(!(p->next))        return ERROR;    q=p->next;    p->next = q->next;    *e = q->data;    free(q);    return OK} 

创建单链表 头插法

void CreateListHead(LinkList *L, int n){    LinkList p;    int i;    srand(time(0));    *L =(LinkList)malloc(sizeof(Node));    (*L)->next=NULL;    for(int i=1; i<=n; i++){        p=(LinkList)malloc(sizeof(Node));        p->data = rand()%100+1;        p->next = (*L)->next;        (*L)->next = p;     }}

创建单链表 尾插法

void CreateLinkTail(LinkList *L, int n){    LinkList p, r;    int i;    srand(time(0));    (*L)=(LinkList)malloc(sizeof(Node));    r=*L;    for(i=1; i<=n; i++){        p = (LinkList)malloc(sizeof(Node));        p->data = rand()%100+1;        r->next = p;        //p->next = r->next;        r=p;     }    r->next=NULL; }

单链表的整表删除

Status ClearList(LinkList *L){    LinkList p,q;    p=(*L)->next;    while(p){        q=p->next;        free(p);        p=q;    }     (*L)->next=NULL;    return OK;}

静态链表
这里写图片描述
游标实现法

#define MaxSize 1000typedef struct{    ElemType data;    int cur;    //游标cursor }Component, StaticLinkList[MaxSize];

初始化

Statues InitList(StaticLinkList space){    int i;    for(i=0; i<MaxSize-1; i++)        space[i].cur = i+1;    space[i].cur = 0;    return OK;}/*数组第一个元素的cur用来存放备用链表第一个节点的下标把未被使用的数组元素成为备用链表,下一位置数据为空则next0表示数组的最后一个元素的cur用来存放第一个插入元素的下标,当整个链表为空时,为0*/ 

链表的插入操作

int Malloc_SLL(StaticLinkList space){    int i=space[0].cur;    if(space[0].cur)        space[0].cur = space[i].cur;    return i;}Status ListInsert(SaticLinkList L, int i, ElemType e){    int j, k, l;    k = MaxSize-1;    j = Malloc_SLL(L);    if(i<1 || i>ListLength(L)+1)        return ERROR;    if(j){        L[j].data = e;        for(l=1; l<=i-1; l++)            k=L[k].cur;        L[j].cur=L[k].cur;        L[k].cur=j;        return OK;    }    return ERROR;}int ListLength(StaticLinkList space){    int j=0;    int i=space[MaxSize-1].cur;    while(i){        j++;        i=space[i].cur;    }    return j;}

链表的删除操作

Status ListDelete(StaticLinkList L, int i){    int j, k;    k=MaxSize-1;    if(i<1 || i>ListLength(L))        return ERROR;    for(j=1; j<=i-1; j++)        k=L[k].cur;    j=L[k].cur;    L[k].cur=L[j].cur;    Free_SSL(L,j);    return OK;}void Free_SSL(StaticLinkList space, int k){    space[k].cur=space[0].cur;    space[0].cur=k;}int ListLength(StaticLinkList L){    int j,k,i;    i=L[Maxsize-1].cur;    j=0;    while(i){        ++j;        i=L[i].cur;    }    return j;}

循环链表
设置循环链表的尾指针rear,便于访问尾结点
判断循环结束的条件 p->next 是否等于头结点
只用设置尾结点即可

合并两个链表的操作
这里写图片描述

p=rearA->next;rearA->next=rearB->next->next;rearB->next=p;free(p);

双向链表
双向链表的存储结构
这里写图片描述

typedef struct DulNode{    ElemType data;    struct DulNode *prior;    struct DulNode *next;} DulNode, *DuLinkList;

双向链表的插入s操作

s->prior=p;s->next=p->next;p->next=s;p->next->prior=s;Status DuListInsert(DuLinkList *L, int i, ElemType e){    int j;    DuLinkList p,s;    p=*L;    j=0;    while(p->next && j<i){        ++j;        p=p->next;    }    if(!p || j>i)        return ERROR;    s=(DuLinkList)malloc(sizeof(DulNode));    s->data=e;    s->next=p;    s->prior=p->prior;    p->prior=s;    s->prior->next=s;    return OK;}

双向链表的删除p操作

p->next->prior = p->prior;p->prior->next = p->next;free(p);Status DuListDelete(DuLinkList *L, int i, ElemType *e){    int j;    DuLinkList p;    p=*L;    j=0;    while(p->next && j<i){        p=p->next;        ++j;    }    if(!p || j>i)        return ERROR;    *e=p->data;    p->next->prior = p->prior;    p->prior->next = p->next;    free(p);    return OK;}
原创粉丝点击