第二章 线性表

第二章 线性表

写在前边的话写代码好比写诗,数据结构就好比唐诗三百首,熟读并默写这是基本功能,所以要闲的没事可以在纸上多写

大纲

  1. 线性表的定义和基本操作
  2. 线性表的实现
    2.1顺序存储结构
    2.2链式存储结构
    2.3线性表的应用

2.1 线性表的基本概念与实现

1. 线性表的逻辑特性
  只有一个表头元素,只有一个表尾元素,表头元素没有前驱,表尾元素没有后继元素,其它的只有一个前驱和后继元素。
2. 线性表的存储结构
 顺寻存储:顺序表
 链式存储:链表
 2.1顺序表
     顺序表就是线性表中所有元素按照其逻辑顺序,依次存储到从指定位置开始的一块连续的存储空间中。
 2.2链表
   在链表存储中,每个结点不仅包含所存元素本身信息,还包含元素之间的逻辑关系信息,即前驱结点包含后继结点的地址信息。
 2.3两种比较
   顺序表:随机访问、静态分配、占用连续存储空间
   链表:不支持随机访问、动态分配、结点存储空间利用率较顺序表低
   顺序表插入一个元素时,需要移动多个元素;链表插入元素时,不需要移动元素。
3. 链表5种形式
3.1单链表
  带头结点的 head->next==NULL 链表为空
  不带头结点的 head == NULL 链表为空
3.2双链表
3.3循环单链表
  带头结点的 head->next==head 链表为空
  不带头结点的 head == NULL 链表为空
3.4循环双链表
  带头结点的 head->next==head && head->prior==head 链表为空
  不带头结点的 head == NULL 链表为空
3.4静态链表

2.2 线性表的基本操作

2.2.1 线性表的定义

  具有相同特性的数据元素的一个有限序列。序列中所包含的元素个数叫做线性表的长度。

2.2.2 线性表的结构定义

#define maxSize 100

1、顺序表的结构定义

typedef struct{
int data[maxSize];
int length;
}Sqlist;

简写

int A[maxSize];
int n;

2、单链表结点定义

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

3、双链表结点的定义

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

2.2.3 顺序表的算法操作

1、定位 x

int locateElem(Sqlist L,int x){
    for(int i=1;i<=L.length;i++)
        if(x<L.data[i]){
            return i;
        }
    return i;
}

2、插入元素 x

void insert(Sqlist &L,int x){
    int p = locateElem(x);
    //移动顺序表
    for(int i=L.length;i>=p;i--){
        data[i+1] = data[i];
    }
    L.data[p]=x;
    ++L.length;
}

3、删除顺序表L中下标为p的元素,并将删除元素赋值给e

int listDelete(Sqlist &L,int p,int &e){
    if(p<1||p>L.length) return 0;
    e=L.data[p];
    for(int i=p;i<=L.length;i++)
        L.data[i] = L.data[i+1];
    --L.length;
    return 1;
}

4、初始化顺序表

void InitList(Sqlist &L){
    L.length = 0;
}

5、用e返回L指定位置p上的元素

int GetElem(Sqlist L,int p,int &e){
    if(p<1||p>L.length) return 0;
    e=L.data[p];
    return 1;
}

2.2.4 单链表的算法操作

1、有A、B两个带头结点的递增有序的单链表,将A和B归并为一个非递减有序的单链表C。

void merge(LNode *&A,LNode *&B,LNode *&C){
    LNode *p=A->next; //因为A B链表都是带头结点的链表
    LNode *q=B->next;
    C=A;
    C->next=NULL;  //表示从A取得的头结点要作为新的头结点
    LNode *r=C;
    free(B);
    while(p!=NULL&&q!=NULL){
        if(p->data < q->data){
            r->next=p;
            p=p->next;
            r=r->next;
        }
        else{
            r->next=q;
            q=q->next;
            r=r->next;
        }
    }
    r->next=NULL; //
    if(p!=NULL) r->next=p;
    if(q!=NULL) r->next=q;
}

2、使用尾插法创建链表

void CreatListR(LNode *&C,int a[],int n){
    LNode *r,*s;
    C=(LNode *)malloc(sizeof(LNode));
    C->next=NULL;
    r=C; //r指向头结点C
    for(int i=0;i<n;i++){
        s=(LNode *)malloc(sizeof(LNode));
        s->data=a[i];
        r->next=s;
        r=r->next;
    }
    r->next=NULL;
}

3、使用头插法创建链表

void CreatListF(LNode *&C,int a[],int n){
    LNode *s;
    C=(LNode *)malloc(sizeof(LNode));
    C->next=NULL;
    for(int i=0;i<n;i++){
        s=(LNode *)malloc(sizeof(LNode));
        s->data=a[i];
        s->next=C->next;
        C->next=s;
    }
}

头插法最后得到的链表顺序和原数组顺序是相反的

4、把之前的链表归并成一个递减有序的链表

使用头插法即可实现

void merge(LNode *&A,LNode *&B,LNode *&C){
    LNode *p=A->next;
    LNode *q=B->next;
    LNode *s;
    C=A;
    C->next=NULL;
    free(B);
    while(p!=NULL&&q!=NULL){
        if(p->data > q->data){
            s=p;
            p=p->next;
            s->next=c->next;
            c->next=s;  //C作为一个头结点,其指针域始终存着尾点s
        }else{
            s=q;
            q=q->next;
            q->next=c->next;
            c->next=s;
        }
    }
    while(p!=NULL){
        s=p;
        p=p->next;
        s->next=c->next;
        c->next=s;
    }
    while(q!=NULL){
        s=q;
        q=q->next;
        s->next=c->next;
        c->next=s;
    }
}

5、插入一个结点
->a->b 插入结点 s

s->next = a->next;
a->next = s;

6、删除一个结点
->a->b

q=a->next;  //用q接收b,为的是删除之后将该结点空间释放
a->next=a->next->next;
free(q);

7、查找一个链表C(带头结点)中是否含有值为 x 的元素,如果存在则删除该结点并返回 1

int SearchAndDelete(LNonde *&C, int x){
    LNode *p,*q;
    p=C;  //这里p指向的是C而不是C->next,因为是为了在查找的 时候得到的是要删除结点的前一个结点
    //查找开始
    while(p->next!=NULL){
        if(p->next->data==x){
            break;
        }
        p=p->next; //更新p
    }


    if(p->next==NULL){
        return 0;
    }
    else{
        q=p->next; //q指向了要删除的结点
        p->next = p->next->next;
        free(q);
        return 1;
    }
}

2.2.5 双联表的算法操作

1、采用尾插法建立双联表

void CreatDlistR(DLNode *&L,int a[],int n){
    DLNode *s,*r;
    L=(DLNode *)malloc(sizeof(DLNode));
    L->next=NULL;
    r=L;
    for(int i=0;i<n;i++){
        s=(DLNode *)malloc(sizeof(DLNode));
        s->data=a[i];
        r->next=s;
        s->prior=r; //首次只建立了当前结点的 prior 域,下次会建立 next 域
        r=s;
    }
    r->next=NULL;
}

2、查找结点值为 x 的结点,存在返回结点指针,否则返回NULL

DLNode* Search(DLNode *C,int x){
    DLNode *p =C->next;
    while(p!=NULL){
        if(p->data==x){
            break;
        }
        p=p->next;
    }
    return p; //最后不管是找到还是没找到都返回p,因为如果没找到,那么终止while的时候p也是为NULL
}

3、插入结点算法
p<->q 插入结点 s

s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;

4、删除 p结点的后继结点 算法
p<->

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

2.2.6 循环双联表的算法操作

判断 p 指针沿着循环链表走到表尾的条件是 p->next == head

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的兼职网,源码+论文答辩+毕业论文+视频演示 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,蜗牛兼职网当然也不能排除在外。蜗牛兼职网是以实际运用为开发背景,运用软件工程原理和开发方法,采用springboot框架构建的一个管理系统。整个开发过程首先对软件系统进行需求分析,得出系统的主要功能。接着对系统进行总体设计和详细设计。总体设计主要包括系统功能设计、系统总体结构设计、系统数据结构设计和系统安全设计等;详细设计主要包括系统数据库访问的实现,主要功能模块的具体实现,模块实现关键代码等。最后对系统进行功能测试,并对测试结果进行分析总结,得出系统中存在的不足及需要改进的地方,为以后的系统维护提供了方便,同时也为今后开发类似系统提供了借鉴和帮助。这种个性化的网上蜗牛兼职网特别注重交互协调与管理的相互配合,激发了管理人员的创造性与主动性,对蜗牛兼职网而言非常有利。 本蜗牛兼职网采用的数据库是MySQL,使用springboot框架开发。在设计过程中,充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。 功能要求:可以管理首页、个人中心、用户管理、企业管理、兼职信息管理、职位申请管理、留言板管理、系统管理等功能模块。 关键词:蜗牛兼职网,springboot框架 MySQL数据库 Java技术
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值