1 线性表的概念

(1) 定义

零个或多个数据元素的有限序列

(2) 属性

  • 有序性:元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。
  • 有限性:线性表元素的个数n(n≥0)定义为线性表的长度,当n=0时,称为空表。
  • 同类型

2 线性表的抽象数据类型

ADT 线性表(List)
Data
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,*e) 在线性表L中的第i个位置插入新元素e。
    ListDelete(*L,*e) 删除线性表L中第i个位置元素,并用e返回其值。
    ListLength(L) 返回线性表L的元素个数。
endADT

3 线性表的顺序存储结构

(1) 定义

  • 是用一段地址连续的存储单元依次存储线性表的数据元素。
  • 通过占位的形式,把一定内存空间给占了,然后把相同数据类型的数据元素依次存放在这块空地中。用一维数组来实现顺序存储结构,即把第一个数据元素存到数组下标为0的位置中,接着把线性表相邻的元素存储在数组中相邻的位置。
  • 为了建立一个线性表,要在内存中找一块地,于是这块地的第一个位置就非常关键,它是存储空间的起始位置。

(2) 三个属性

  • 存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置
  • 线性表的最大存储容量:数组长度MaxSize
  • 线性表的当前长度:length
    线性表的长度是线性表中数据元素的个数,在任意时刻,线性表的长度≤数组的长度

(3) 结构代码

#define MAXSIZE 20 //存储空间初始分配量
typedef int ElemType; //ElementType类型根据实际情况而定,这里假设为int
typedef struct
{
    ElemType data[MAXSIZE]; //数组存储数据元素,最大值是MAXSIZE
    int length; //线性表当前长度
} *sqlist;

(4) 操作

A 初始化顺序结构

int InitList(sqlist *L)  
{
    (*L)=(sqlist)malloc(sizeof(sqlist));
    (*L)->length=0; //空表长度为0
    return 1;  
}

B 插入

int ListInsert(sqlist L,int i,ElemType e){
    int k;
    if(L->length==MAXSIZE){ //顺序线性表已满 
        return 0;
    }
    if(i<1 || i>L->length+1){ //当i不在范围内时
        return 0;
    }
    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++; //表长+1 
    return 1;
}

C 删除

int ListDelete(sqlist L,ElemType e){
    int k;
    if(L->length==0){ //线性表为空
        return 0;
    }
    if(i<1 || i>L->length){ //删除位置不正确
        return 0;
    }
    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--; //表长-1 
    return 1;
}

D 获得元素

int GetElem(sqlist L,ElemType e){
    if(L.length==0 || i<1 || i>L.length){
        return 0;
    }
    e=L.data[i-1];
    return 1;
}

E 打印元素

int ListTraverse(sqlist L)
{  
    int i,len;  
    len=L->length;  
    for(i=1;i<=len;i++){  
        printf("位置:%d,元素:%d\n",L->data[i-1]);
    }  
    return 1;  
}

(5) 实例

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 20 //存储空间初始分配量
typedef int ElemType; //ElementType类型根据实际情况而定,这里假设为int
typedef struct
{
    ElemType data[MAXSIZE]; //数组存储数据元素,最大值是MAXSIZE
    int length; //线性表当前长度
} *sqlist;

/*初始化顺序结构*/ 
int InitList(sqlist *L)  
{
    (*L)=(sqlist)malloc(sizeof(sqlist));
    (*L)->length=0; //空表长度为0
    return 1;  
}

/*插入元素*/
int ListInsert(sqlist L,ElemType e){
    int k;
    if(L->length==MAXSIZE){ //顺序线性表已满 
        return 0;
    }
    if(i<1 || i>L->length+1){ //当i不在范围内时
        return 0;
    }
    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++; //表长+1 
    return 1;
}

/*删除元素*/ 
int ListDelete(sqlist L,int i){
    int k;
    if(L->length==0){ //线性表为空
        return 0;
    }
    if(i<1 || i>L->length){ //删除位置不正确
        return 0;
    }
    if(i<L->length){ //如果删除不是最后位置 
        for(k=i;k<L->length;k++){ //将删除位置后继元素前移
            L->data[k-1]=L->data[k];
        }
    }
    L->length--; //表长-1 
    return 1;
}

/*获得元素*/
int GetElem(sqlist L,int i){
    if(L->length==0 || i<1 || i>L->length){
        return 0;
    }
    printf("%d\n",L->data[i-1]);
    return 1;
}

/*打印顺序结构*/
int ListTraverse(sqlist L)
{  
    int i,L->data[i-1]);
    }  
    return 1;  
}  

int main(void)
{
    sqlist L;
    InitList(&L);
    ListInsert(L,1,1);
    ListInsert(L,2,2);
    ListTraverse(L);
    GetElem(L,2);
    ListDelete(L,2);
    ListTraverse(L);
    return 0;
}

4 线性表的链式存储结构

(1) 定义

A 头指针

  • 头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针
  • 无论链表是否为空,头指针均不为空
  • 头指针是链表的必要元素

B 头结点

  • 头结点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义(也可存放链表的长度)
  • 有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其它结点的操作就统一了
  • 头结点不一定是链表必须要素

(2) 结构代码

typedef int ElemType;
typedef struct Node{
    ElemType data;
    struct Node *next;
} Node;
typedef struct Node *LinkList;

(3) 操作

A 初始化链式结构

int InitList(LinkList *L)
{
    (*L)=(LinkList)malloc(sizeof(Node));
    (*L)->next=NULL;
    return 1;
}

B 插入

int ListInsert(LinkList L,ElemType e)
{
    int j;
    LinkList p,s;
    p=L;
    j=1;
    while (p && j<i){ //寻找第i结点
        p=p->next;
        ++j;
    }
    if(!p || j>i){
        return 0; //第i个元素不存在
    }
    s=(LinkList)malloc(sizeof(Node)); //生成新结点(C语言标准函数)
    s->data=e; //结构体即scanf
    s->next=p->next; //将p的后继结点赋值给s的后继
    p->next=s; //将s赋值给p的后继
    return 1;
}

C 删除

int ListDelete(LinkList L,q;
    p=L;
    j=1;
    while(p->next && j<i){ //历寻找第i个元素
        p=p->next;
        ++j;
    }
    if (!(p->next) || j>i){
        return 0; //第i个元素不存在
    }
    q=p->next;
    p->next=q->next; //将q的后继赋值给p的后继
    e=q->data; //将q结点中的数据给e
    free(q); //让系统回收此结点,释放内存
    return 1;
}

D 获得元素

int GetElem(LinkList L,ElemType e){
    int j;
    LinkList p; //声明一结点p
    p=L->next; //让p指向链表L的第一个结点 
    j=2; //j为计数器 
    while(p && j<i){ //p不为空或者计数器j还没有等于i时,循环继续 
        p=p->next; //让p指向下一个结点 
        ++j;
    }
    if(!p || j>i){
        return ERROR; //第i个元素不存在 
    }
    e=p->data; //取第i个元素的数据 
    return 1;
}

第一部分遍历查找第i个结点;第二部分插入和删除结点

E 整表删除

int ClearList(LinkList L)
{
    LinkList p,q;
    p=L->next; //p指向第一个结点
    while(p){ //没到表尾
        q=p->next;
        free(p);
        p=q;
    }
    L->next=NULL; //头结点指针域为空
    return 1;
}

F 打印元素

int ListTraverse(LinkList L){
    LinkList e;
    int i=1;
    e=L;
    if(e->next==NULL){
        return 0;
    }
    else{
        while(e->next!=NULL){
            printf("%d",e->next->data);
            e=e->next;
            i++;
        }
        return 1;
    }    
}

只有初始化的时候函数是带*的

(4) 实例

#include <stdio.h>
#include <stdlib.h>   
#include <string.h>
 
/*定义元素类型*/
typedef struct{
    char name[20];
    char press[20];
    char writer[20];
    char date[15];
    double money;
}Book;

typedef Book ElemType;

/*定义链表结构*/
typedef struct Node{
    ElemType data;
    struct Node *next;
} Node;

typedef struct Node *LinkList;

/*初始化链表*/
int InitList(LinkList *L)
{
    *L=(LinkList)malloc(sizeof(Node));
    (*L)->next=NULL;
    return 1;
}

/*借书*/
int ListDelete(LinkList L,char find[])
{
    int j;
    LinkList p,q;
    p=L;
    j=1;
    int a=0;
    if(p->next==NULL){
        printf("\n对不起,图书馆暂无图书,请先添加!\n");
        return 0;
    }
    else{
        while(p!=NULL){
            if(strcmp(p->next->data.name,find)==0){
                q=p->next;
                p->next=q->next;
                free(q);
                printf("\n删除%s成功!\n",find);
                a=1;
                break;
            }
            p=p->next;
        } 
    }
    if(a==0) printf("\n输入的书名有误,删除失败!\n");
}

/*添书、还书*/
int ListInsert(LinkList L,int i)
{
    int j;
    LinkList p,s;
    p=L;
    j=1;
    while (p && j<i){ //寻找第i结点
        p=p->next;
        ++j;
    }
    if(!p || j>i){
        return 0; //第i个元素不存在
    }
    s=(LinkList)malloc(sizeof(Node)); //生成新结点(C语言标准函数)
    printf("\n请输入书名:"); 
    scanf("%s",s->data.name);
    printf("\n请输入作者:");
    scanf("%s",s->data.writer);
    printf("\n请输入出版社:");
    scanf("%s",s->data.press);
    printf("\n请输入日期:");
    scanf("%s",s->data.date);
    printf("\n请输入价格:");
    scanf("%lf",&s->data.money);
    s->next=p->next; //将p的后继结点赋值给s的后继
    p->next=s; //将s赋值给p的后继
    return 1;
}

/*查书*/
int findbook(LinkList L){
    LinkList e;
    int key;
    int sign=0;
    char find[20];
    e=L;
    printf("\n请选择你要查询的关键词种类:1、书名    2、作者    3、出版社    4、日期\n");
    scanf("%d",&key);
    switch(key){
        case 1:    
            printf("\n请输入您要查询的书名:");
            scanf("%s",find);
            while(e->next!=NULL){
                if(strcmp(e->next->data.name,find)==0){
                    printf("\n符合条件书的信息:\n书名:%s    作者:%s    出版社:%s    日期:%s    价格:%.2lf\n",e->next->data.name,e->next->data.writer,e->next->data.press,e->next->data.date,e->next->data.money);
                    sign=1;    
                }
                e=e->next;    
            }
            break;
        case 2:    
            printf("请输入您要查询的作者:");
            scanf("%s",find);
            while(e->next!=NULL){
                if(strcmp(e->next->data.writer,e->next->data.money);
                    sign=1;
                }
                e=e->next;    
            }
            break;
        case 3:    
            printf("\n请输入您要查询的出版社:");
            scanf("%s",find);
            while(e->next!=NULL){
                if(strcmp(e->next->data.press,e->next->data.money);
                }
                e=e->next;    
            }
            break;
        case 4:    
            printf("\n请输入您要查询的类日期:");
            scanf("%s",find);
            while(e->next!=NULL){
                if(strcmp(e->next->data.date,e->next->data.money);
                    sign=1;
                }
                e=e->next;    
            }
            break;
    }
    return sign;
}

/*显示*/ 
int ListTraverse(LinkList L){
    LinkList e;
    int i=1;
    e=L;
    if(e->next==NULL){
        return 0;
    }
    else{
        while(e->next!=NULL){
            printf("\n第%d本书的信息:\n书名:%s\t\t作者:%s\t\t出版社:%s\t\t日期:%s\t\t价格:%.2lf\n\n",e->next->data.money);
            e=e->next;
            i++;
        }
        return 1;
    }    
}

int main(void)
{  
    /*构造线性表 */
    LinkList books;
    InitList(&books);
    int n,insert,loc,sign;
    char key[20];
    do{
        printf("\n--------------------------------ZUST图书管理系统欢迎您-----------------------------------\n"); 
        printf("\n请选择功能:\n\n0、添加图书\t1、查询图书\t2、删除图书\t3、所有图书\t4、退出\n\n请输入您要进行的操作:");
        scanf("%d",&n);
        printf("\n-----------------------------------------------------------------------------------------\n"); 
        switch(n){
            case 0: 
                printf("\n请输入您要添加书的位置:");
                scanf("%d",&loc);
                insert=ListInsert(books,loc);
                if(insert==0) printf("\n位置输入有误,添加失败!\n");
                break;
            case 1: 
                sign=findbook(books);
                if(sign==0) printf("\n对不起,图书馆暂无此书!\n"); 
                break;
            case 2:
                printf("\n请输入您要删除的图书书名:");
                scanf("%s",key);
                ListDelete(books,key);
                break;
            case 3
            : 
                ListTraverse(books);
                break;
        }
    }while(n!=4);
    printf("\n图书管理系统已退出!\n"); 
    return 0;
}

5 循环链表

(1) 定义

  • 将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,行成头尾相接的单链表。
  • 其实循环链表和单链表的主要差异就在于循环的判断条件上,原来是判断p->next是否为空,现在则是p->next不等于头结点,则循环未结束。

(2) 双向链表

A 结构代码

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

B 操作

  • a 插入
s->prior=p; //S的前驱
s->next=p->next; //S的后继
p->next=prior=s; //后结点的前驱
p->next=s; //后结点的后继
  • b 删除
p->prior->next=p->next; //前结点的后继
p->next->prior=p->prior; //后结点的前驱
free(p);

6 单链表结构与顺序存储结构优缺点

  • 若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。
  • 若需要频繁插入和删除时,宜采用单链表结构。
  • 当元素个数变化较大或者根本不知道有多大时,用单链表结构。
  • 事先知道线性表的大致长度,用顺序存储结构。

7 线性表的关系

【数据结构】第二章 线性表的更多相关文章

  1. 使用最新的Flurry SDK和ios4重新启动应用程序

    我真的希望这对我来说只是一个愚蠢的错误.我很高兴使用Flurry但这样的事情会导致我的应用被拒绝.解决方法我写了关于这个的Flurry,他们很快回到我身边,他们会调查这个.大约一个星期后,他们回信并表示他们已经在v2.6中修复了它,现在可用了.我似乎无法重现这个问题.不是说我很棒或者什么,但我还是单枪匹马地解决了这个问题.

  2. 如何在Xcode 4.1中调试OpenCL内核?

    我有一些OpenCL内核没有做他们应该做的事情,我很想在Xcode中调试它们.这可能吗?当我在我的内核中使用printf()时,OpenCL编译器总是给我一大堆错误.解决方法将格式字符串转换为constchar*似乎可以解决此问题.这适用于Lion:这有上述错误:

  3. swift篇第一期:简单的数据结构

    首先我们可以去使用Playground来编码,并且会实时的显示对应的编码信息,这样我们就不用每次都去运行程序来显示输出的东西了哦,也方便了我们对某些语句的验证,这个是比较赞的var与let前者为可变修饰符,后者为不可变从字面意思我们就可以很好的区分了常用的类型呢,跟其他语言基本相同啦,主要有几种:1.int类型2.Float,Double类型3.String类型4.Boolean类型当我们去声明一

  4. Swift-ReactiveCocoa3.0二SignalProducer 2

    lift运算符|>内部也是调用了lift方法,作用是把原producer的结果transform完返回新的类型/值,再封装成新的producer返回。只有在第一个producer销毁后才会响应第二个producer。之后,每当其中一个再sendNext,都会在next回调zipwith压缩两个信号,每当两个都sendNext一次才回在next回调一次。例子:sampleOn采样,当sampleOn的信号sendNext一次,就取一次producer1的最新一次sendNext的值进行next回调takeu

  5. 深度解析swift中的String

    String是我们最常用到的语言元素,swift中的String初看起来相当简洁、易用,真正大量使用时,却有点摸不着头脑。直到看完了这篇文章,才算真正的明白了String的奥妙之处。每个Character所占用的内存空间不定,注定了String不能用普通的数组来存储内容,实际用的是双向链表。String.Index既然String是个双向链表,那么,访问其中的某个元素,或者substring,就要用指针了。NSRange和RangeNsstring中对于字符串区间,可以用NSRange来表示,而Strin

  6. Swift 集合数据结构性能分析

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  7. Swift 中数组和链表的性能

    尽管如此,我觉得链表的例子非常有意思,而且值得实现和把玩,它有可能会提升数组reduce方法的性能。同时我认为Swift的一些额外特性很有趣:比如它的枚举可以灵活的在对象和具体方法中自由选择,以及“默认安全”。这本书未来的版本可能就会用Swift作为实现语言。拷贝数组消耗的时间是线性的。使用链表还有其他的代价——统计链表节点的个数所需要的时间是统计数组元素个数时间的两倍,因为遍历链表时的间接寻址方式是需要消耗时间的。

  8. Swift中的集合类数据结构

    在那种情况下,你将会需要一种基本的集合类数据结构。继续学习,你将会比较成熟的Cocoa数据结构与对应的纯Swift结构的性能。常见iOS数据结构iOS中三种最常用的数据结构是arrays,dictionaries和sets。除了在Swift和Objective-C中旧的Foundation框架中的数据结构,现在又有了新的仅支持Swift版本的数据结构与语言紧密结合在一起。Swift数组是同质的,意味着每一个Swift数组都只包含一种类型的对象。

  9. 如何在Swift中调用C函数

    “,选择Yes,创建SwiftCallC-Bridging-Header.h文件给工程建立一个C语言文件。跟上述步骤3类似,只不过这里选择的是C文件,这里的文件取名为CFile.c,同时自动生成CFile.h文件开始编写代码。在SwiftCallC-Bridging-Header.h文件中声明C函数,这里是voidcallCDemo()在CFile.c中定义这个函数在main.swift中调用这个C函数编译运行

  10. 11.Swift 中的类和结构体

    举例来说,以下情境中适合使用结构体:1.几何形状的大小,封装一个width属性和height属性,两者均为Double类型。这次就讲到这里,下次我们继续

随机推荐

  1. 【数据结构】单调栈

    显然,每个发射站发来的能量有可能被0或1或2个其他发射站所接受,特别是为了安全,每个发射站接收到的能量总和是我们很关心的问题。由于数据很多,现只需要你帮忙计算出接收最多能量的发射站接收的能量是多少。输入输出格式输入格式:第1行:一个整数N;第2到N+1行:第i+1行有两个整数Hi和Vi,表示第i个人发射站的高度和发射的能量值。输入输出样例输入样例:34235610输出样例:7题解中有讲解代码实现

  2. BZOJ 1798 [Ahoi2009] Seq 维护序列seq [线段树+多重标记下传]【数据结构】

    有长为N的数列,不妨设为a1,a2,…Input第一行两个整数N和P。第二行含有N个非负整数,从左到右依次为a1,aN,。表示把所有满足t≤i≤g的ai改为ai×c。操作2:“2tgc”。同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。Output对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。SampleInput7431234567512553242379313347SampleOutput2358HINT初始时数列为。对第5次操作,和为29+34+15+16=

  3. 陈越《数据结构》第一讲 基本概念

    陈越《数据结构》第一讲基本概念1什么是数据结构1.1引子例子:如何在书架上摆放图书?数据结构是:1.数据对象在计算机中的组织方式;2.数据对象必定与一系列加在其上的操作相关联;3.完成这些操作所用的方法就是算法。抽象数据类型数据类型-数据对象集;-数据集合相关联的操作集。抽象-与存放数据的机器无关;-与数据存储的物理结构无关;-与实现操作的算法和编程语言均无关。

  4. 陈越《数据结构》第二章 线性结构

    表中元素个数称为线性表的长度;线性表没有元素时,称为空表;表起始位置称表头,表结束位置称表尾。插入和删除操作只能在链栈的栈顶进行。

  5. 【数据结构】

    非线性结构:线性结构的元素之间具有线性关系,非线性结构中的元素之间不再是序列的关系,他们呈现的是更复杂的层次关系,即一个数据元素有且仅有一个直接前驱,但可有另个或者多个直接后继,显然比序列关系复杂常见非线性结构:树,图散列表PHP中的hashtable就是哈希表就是由数组和链表组成,一个长度为16的数组中,每个元素存储的是一个链表的头结点。

  6. 【数据结构】【C++STL】FIFO队列&amp;优先队列

    首先都需要打头文件queueFIFO队列是先进先出的就好像排队一样STL定义FIFO队列优先队列的话是有优先级存在的STL定义优先队列定义方式都是大根堆FIFO队列和优先队列都有一些操作COYG

  7. 【数据结构】 堆

    自底向上://增加/减少已有节点值Heap_Increase_Key//向堆插入新的节点HeapInsert自顶向下://替换堆顶后,维持堆函数KeepHeap//弹出堆顶函数Pop

  8. 【数据结构】链表

    线性表的顺序存储结构有存储密度高及能够随机存取等优点,但存在以下不足:线性表的链式存储(单链表)的实现单向循环链表的实现

  9. 伸展树(SPLAY)个人总结+模板 [平衡树]【数据结构】【模板】

    前言最近3个月内,无论是现场赛还线上赛中SPLAY出现的概率大的惊人啊啊啊!!!然而不会的我就GG了,同时发现大家都会SPLAY,,,,然后就学习了一波。——————————————————————————-附上整体代码-md贴上来太卡了,去题解里看吧维护序列的维护一堆数的

  10. BZOJ 1895 &amp; POJ 3580 supermemo [SPLAY]【数据结构】

    Ay}Ttimes.Forexample,performing“REVOLVE242”on{1,5}INSERTxP:insertPafterAx.Forexample,performing“INSERT24”on{1,5}DELETEx:deleteAx.Forexample,performing“DELETE2”on{1,5}MINxy:querytheparticipantwhatistheminimumnumberinsub-sequence{Ax…Ay}.Forexample,thecorrec

返回
顶部