顺序表代码

文章目录

    • 顺序表代码
      • 1.结构体复习
      • 2.顺序表初始化
        • 顺序表初始化优化
        • 添加注释更详细点
      • 3.顺序表插入元素
        • 插入函数1
        • 插入函数优化
        • 指针方式插入
        • `typora`快捷键
        • 算法2.4,指针方式插入元素优化
        • 改成用户输入插入位置和元素
        • 提高算法健壮性
      • 4.顺序表删除元素
        • 删除函数开始
        • 写成指针形式
        • 算法2.5
      • 至此完整代码1
      • 完整代码2
      • `main.cpp`
      • `head.h`
      • `base_op.cpp`
      • `base_op.cpp完整版`
      • `more_op.cpp`
      • 顺序表重点代码
        • 1.线性表的动态分配顺序存储结构
        • 2. 顺序表初始化
        • 3.顺序表插入元素
        • 4.顺序表删除元素
        • 5.在Lb中但不在La中的数据元素插入到La中
        • 6.归并
      • 顺序表经典例题
        • 1.删除最小值(假设唯一)
        • 2.删除最小值(空位填补)
        • 3.顺序表元素逆置
        • 4.删除顺序表L中所有值为x的元素
        • 5.有序顺序表删除s到t
          • 优化(推荐这个)
          • 答案写法

顺序表代码

1.结构体复习

#include //标准输入输出头文件 scanf(), printf()

int main() {//int是函数的返回值
    /*
    结构体,本质上是一种自定义的数据类型
    int char float
    int a;
    */

    struct stu {
        char *name;
        int num;
        int age;
    } stu1 = {"xiao_ming", 12, 18};
    //struct stu stu1;//声明

    /*
    stu1.name = "xiao_ming";
    stu1.num = 12;
    stu1.age = 18;
    */
    printf("%s %d %d", stu1.name, stu1.num, stu1.age);
    return 0;
}

2.顺序表初始化

#include //标准输入输出头文件 scanf(), printf()
#include 
//int a;
//int* p;
int main() {//int是函数的返回值
    struct seq_list{
        int *elem;
        int length;
        int listsize;
    };
    struct seq_list L;

    /*顺序表的初始化*/
    L.elem = (int *)malloc(sizeof(int) * 100);//分配字节空间
    L.length = 0;//空表的长度为0
    L.listsize = 100;


    /*顺序表赋值,输入元素*/
    int n = 6;
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);
        L.length++;
    }

    /*输出元素*/
    printf("顺序表初始化成功:");
    for (int i = 0; i < L.length; ++i) {
        printf("%d ", L.elem[i]);
    }
    return 0;
}

顺序表初始化优化

#include //标准输入输出头文件 scanf(), printf()
#include 
#define OVERFLOW -2//溢出
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
typedef int Status;
typedef char ElemType;
typedef struct {//起别名叫SqList
    ElemType *elem;
    int length;
    int listsize;
} SqList;
//typedef struct seq_list SqList;


Status InitList_Sq(SqList &L);
Status CreateList_Sq(SqList &L);
Status ListTraverse_Sq(SqList L);

int main() {//int是函数的返回值
    SqList L;//声明顺序表L
    InitList_Sq(L);//顺序表初始化
    CreateList_Sq(L);//给顺序表赋几个值
    ListTraverse_Sq(L);//遍历输出元素
    return 0;
}
//顺序表的初始化
Status InitList_Sq(SqList &L) {
    L.elem = (ElemType *) malloc(sizeof(ElemType) * LIST_INIT_SIZE);//分配字节空间
    if (!L.elem) {
        printf("初始空间分配失败");
        exit(OVERFLOW);//exit(n)就是退出,传入参数n是程序退出时的状态码,0表示正常退出,其他非正常
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;
    return OK;
}

//元素创建,顺序表赋值,输入元素n
Status CreateList_Sq(SqList &L) {
    int n;
    printf("要输入几个元素:");
    scanf("%d", &n);
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);
        L.length++;
    }
    return OK;
}

//遍历输出元素
Status ListTraverse_Sq(SqList L) {
    if(!L.elem){
        printf("线性表未初始化或被销毁!!!");
        return ERROR;
    }
    if(L.length == 0){
        printf("线性表中无元素!");
    }else{
        printf("顺序表初始化成功:");
        for (int i = 0; i < L.length; ++i) {
            printf("%d ", L.elem[i]);
        }
    }
    return OK;
}

添加注释更详细点

#include //标准输入输出头文件 scanf(), printf()
#include //内存操作函数malloc、free等

//函数结果状态代码
#define OVERFLOW -2 //溢出
#define ERROR 0
#define OK 1

#define LIST_INIT_SIZE 100 //线性表的存储空间的初始分配增量

//注意区分给变量宏定义和给数据类型起别名
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;//数据元素类型约定为ElemType

/*线性表的动态分配顺序存储结构*/
typedef struct {
    ElemType *elem; //存储空间基址,声明了一个名为elem的长度不确定的数组,也叫“动态数组”
    int length; //当前长度
    int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
} SqList;

Status InitList_Sq(SqList &L);

Status CreateList_Sq(SqList &L);

Status visit(ElemType e);

Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType));

int main() {//int是函数的返回值
    SqList L;//声明一个顺序表
    InitList_Sq(L);//初始化顺序表
    CreateList_Sq(L);//向顺序表中添加元素
    ListTraverse_Sq(L, visit);//遍历输出元素
    return 0;
}

//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L) {
    L.elem = (ElemType *) malloc(sizeof(ElemType) * LIST_INIT_SIZE);//分配字节空间
    if (!L.elem) {
        printf("初始化空间失败");
        exit(OVERFLOW);//exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;
    return OK;
}//算法2.3

/*创建顺序表,顺序表赋值,输入元素*/
Status CreateList_Sq(SqList &L) {
    int n;
    printf("要输入几个元素:");
    scanf("%d", &n);
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);
        L.length++;
    }
    return OK;
}

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status visit(ElemType e) {
    printf("%d ", e);
    return OK;
}

/*遍历输出元素*/
Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType)) {
    if (!L.elem) {
        printf("线性表未初始化或被销毁了!!!");
        return ERROR;
    }
    if (L.length == 0) {
        printf("线性表中无元素!");
    } else {
        printf("顺序表初始化并赋值成功:");
        for (int i = 0; i < L.length; ++i) {
            pfn_visit(L.elem[i]);
            //printf("%d ", L.elem[i]);
        }
    }
    return OK;
}

顺序表初始化成功。ListTraverse_Sq遍历函数的参数可能不太好理解,下面进行解释:

  1. 遍历函数里的形参用一个函数指针 Status (*pfn_visit)(ElemType) 的好处:提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
  2. 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

细心的话会发现,课本上在声明ListTraverse_Sq这个函数的时候,用的是ListTraverse(L, visit())依次对L的每个数据元素调用函数visit(),一旦visit()失败,则操作失败,真正实现的时候用到了函数指针,会让代码变得更加晦涩难懂,这里对于初学者有很大的影响,上面给出具体实现和简单的解释,读者不必过多纠结,只要会调用时候函数就行了。

3.顺序表插入元素

插入函数1

//在L中第pos个位置插入新的元素e,L的长度加1
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
    for (int i = L.length; i >= pos; i--) {
        L.elem[i] = L.elem[i - 1];
    }
    L.elem[pos - 1] = e;//插入e
    L.length++;//表长增1
    return OK;
}

插入函数优化

//在L中第pos个位置插入新的元素e,L的长度加1
Status ListInsert_Sq(SqList &L) {
    //从最后一个元素开始依次向后移动,注意下标从0开始,位置从1开始
    int pos;
    ElemType e;
    printf("请输入插入位置和要插入的元素:");
    scanf("%d %d", &pos, &e);
    for (int i = L.length; i >= pos; i--) {
        L.elem[i] = L.elem[i - 1];
    }
    L.elem[pos - 1] = e;//插入e
    L.length++;//表长增1
    return OK;
}

指针方式插入

//在L中第pos个位置插入新的元素e,L的长度加1
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
    //从最后一个元素开始依次向后移动,注意下标从0开始,位置从1开始
    for (ElemType *p = &L.elem[L.length-1]; p >= &L.elem[pos-1]; p--) {
        *(p+1) = *p;
        /*p是指针 声明指针 int *p;
        使用时p代表指针
        非声明的时候,*p 代表取地址上的元素*/
        //L.elem[i] = L.elem[i - 1];
    }
    *&L.elem[pos - 1] = e;//插入e
    L.length++;//表长增1
    return OK;
}

typora快捷键

代码块 ctrl+shift+K
标题 ctrl+数字
大纲 ctrl+shift+L

CLion 格式化ctrl+alt+L

算法2.4,指针方式插入元素优化

//在L中第pos个位置插入新的元素e,L的长度加1
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
    //从最后一个元素开始依次向后移动,注意下标从0开始,位置从1开始
    ElemType *p = &L.elem[L.length-1];
    ElemType *q = &L.elem[pos-1];
    for ( ; p >= q; p--) {
        *(p+1) = *p;
    }
    *&L.elem[pos - 1] = e;//插入e
    ++L.length;//表长增1
    return OK;
}//算法2.4
//a = b++;先赋值再++
//a= ++b;先++再赋值

改成用户输入插入位置和元素

//在L中第pos个位置插入新的元素e,L的长度加1
Status ListInsert_Sq(SqList &L) {
    //从最后一个元素开始依次向后移动,注意下标从0开始,位置从1开始
    int pos;
    ElemType e;
    printf("请输入插入位置和要插入的元素:");
    scanf("%d %d", &pos, &e);
    ElemType *p = &L.elem[L.length-1];
    ElemType *q = &L.elem[pos-1];
    for ( ; p >= q; p--) {
        *(p+1) = *p;
    }
    *&L.elem[pos - 1] = e;//插入e
    ++L.length;//表长增1
    return OK;
}//算法2.4初版

提高算法健壮性

//插入元素
Status ListInsert_Sq(SqList &L) {
    int pos;//position插入位置
    ElemType e;//要插入元素e
    printf("请输入要插入的元素位置和元素的值:");
    scanf("%d %d", &pos, &e);
    if(pos < 1 || pos > L.length+1){
        printf("插入位置有问题");
        return ERROR;
    }
    //realloc()更改已分配的内存单元的大小
    if(L.length >= L.listsize){
        ElemType *newbase = (ElemType *) realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof(ElemType));
        if (!newbase) {
            printf("初始化空间失败");
            exit(OVERFLOW);//exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出
        }
        L.elem = newbase; //新基址
        L.listsize = L.listsize + LISTINCREMENT;
        //printf("L.listsize = %d\n", L.listsize);
    }
    ElemType *q = &(L.elem[pos - 1]);            //q为插入位置,即将插入位置的地址赋给q
    ElemType *p = &(L.elem[L.length - 1]);    //p为最后一个元素的地址
    for (; p >= q; --p) {
        *(p + 1) = *p;                        //插入位置及之后的元素右移
    }
    *q = e;                                    //插入e
    ++L.length;                                //表长增1
    return OK;
}//算法2.4终版

4.顺序表删除元素

删除函数开始

// 初始条件:线性表L已存在且非空,1≤pos≤ListLength(L)。
// 操作结果:删除L的第pos个数据元素,并用e返回其值,L的长度减1。
Status ListDelete_Sq(SqList &L, int pos, ElemType &e)
{
    for (int i = pos; i < L.length; i++) {
        L.elem[i-1] = L.elem[i];
    }
    L.length--;
    return OK;
}

写成指针形式

//删除元素
Status ListDelete_Sq(SqList &L) {
    int pos;
    printf("请输入删除位置:");
    scanf("%d", &pos);
    printf("您删除的值是:%d\n", L.elem[pos - 1]);
    ElemType *p = &L.elem[pos];
    ElemType *q = &L.elem[L.length];
    for (; p < q; p++) {
//        L.elem[i-1] = L.elem[i];
        *(p - 1) = *p;
    }
    L.length--;
    return OK;
}

算法2.5

//删除元素
Status ListDelete_Sq(SqList &L) {
    int pos;
    printf("请输入删除位置:");
    scanf("%d", &pos);
    if(pos<1 || pos >L.length){
        printf("删除位置有误");
        return ERROR;
    }
    printf("您删除的值是:%d\n", L.elem[pos - 1]);
    ElemType *p = &L.elem[pos];
//    ElemType *q = &L.elem[L.length-1];
    ElemType *q = L.elem + L.length - 1;
    for (; p <= q; p++) {
        *(p - 1) = *p;
    }
    L.length--;
    return OK;
}//算法2.5

L.elem + L.length - 1; //表尾元素的位置的理解:

L.elem+0是第1个的地址,L.elem+1是第二个的地址,所以最后一个是 L.elem+(L.length-1)

至此完整代码1

#include //标准输入输出头文件 scanf(), printf()
#include //malloc(), realloc()

//函数结果状态代码
#define OVERFLOW -2 //溢出
#define ERROR 0 //错误代码
#define OK 1

#define LIST_INIT_SIZE 100 //线性表的存储空间的初始分配增量
#define LISTINCREMENT 5 //存储空间分配增量

//注意区分给变量宏定义和给数据类型起别名
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;//数据元素类型约定为ElemType

/*线性表的动态分配顺序存储结构*/
typedef struct {
    ElemType *elem; //存储空间基址,声明了一个名为elem的长度不确定的数组,也叫“动态数组”
    int length; //当前长度
    int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
} SqList;

//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L);

//给顺序表添加数据元素
Status CreateList_Sq(SqList &L);

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status visit(ElemType e);

Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType));

//插入数据元素
Status ListInsert_Sq(SqList &L);

Status ListDelete_Sq(SqList &L);

int main() {//int是函数的返回值
    SqList L;//声明一个顺序表
    InitList_Sq(L);//初始化顺序表
    CreateList_Sq(L);//向顺序表中添加元素
    //ListInsert_Sq(L);//插入元素
    ListDelete_Sq(L);
    ListTraverse_Sq(L, visit);//遍历输出元素
    return 0;
}

//删除元素
Status ListDelete_Sq(SqList &L) {
    int pos;
    printf("请输入删除位置:");
    scanf("%d", &pos);
    if(pos<1 || pos >L.length){
        printf("删除位置有误");
        return ERROR;
    }
    printf("您删除的值是:%d\n", L.elem[pos - 1]);
    ElemType *p = &L.elem[pos];
//    ElemType *q = &L.elem[L.length-1];
    ElemType *q = L.elem + L.length - 1;
    for (; p <= q; p++) {
        *(p - 1) = *p;
    }
    L.length--;
    return OK;
}//算法2.5

//插入元素
Status ListInsert_Sq(SqList &L) {
    int pos;//position插入位置
    ElemType e;//要插入元素e
    printf("请输入要插入的元素位置和元素的值:");
    scanf("%d %d", &pos, &e);
    if (pos < 1 || pos > L.length + 1) {
        printf("插入位置有问题");
        return ERROR;
    }
    if (L.length >= L.listsize) {
        ElemType *newbase = (ElemType *) realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
        //realloc()更改已分配的内存单元的大小
        if (!newbase) {
            printf("初始化空间失败");
            exit(OVERFLOW);//exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出
        }
        L.elem = newbase; //新基址
        L.listsize = L.listsize + LISTINCREMENT;
        //printf("L.listsize = %d\n", L.listsize);
    }
    ElemType *q = &(L.elem[pos - 1]);            //q为插入位置,即将插入位置的地址赋给q
    ElemType *p = &(L.elem[L.length - 1]);    //p为最后一个元素的地址
    for (; p >= q; --p) {
        *(p + 1) = *p;                        //插入位置及之后的元素右移
    }
    *q = e;                                    //插入e
    ++L.length;                                //表长增1
    return OK;
}//算法2.4

//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L) {
    L.elem = (ElemType *) malloc(sizeof(ElemType) * LIST_INIT_SIZE);//分配字节空间
    if (!L.elem) {
        printf("初始化空间失败");
        exit(OVERFLOW);//exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;
    return OK;
}//算法2.3

/*创建顺序表,顺序表赋值,输入元素*/
Status CreateList_Sq(SqList &L) {
    int n;
    printf("要输入几个元素:");
    scanf("%d", &n);
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);//读入一个元素
        L.length++;//表长增加1,也可以写成 --L.length
    }
    return OK;
}

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status visit(ElemType e) {
    printf("%d ", e);
    return OK;
}

/*遍历输出元素*/
Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType)) {//函数指针
    if (!L.elem) {
        printf("线性表未初始化或被销毁了!!!");
        return ERROR;
    }
    if (L.length == 0) {//提高算法的健壮性
        printf("线性表中无元素!");
    } else {
        printf("结果是:");
        for (int i = 0; i < L.length; ++i) {
            pfn_visit(L.elem[i]);
            //printf("%d ", L.elem[i]);
        }
    }
    return OK;
}

完整代码2

#include //标准输入输出头文件 scanf(), printf()
#include //malloc(), realloc()

//函数结果状态代码
#define OVERFLOW -2 //溢出
#define ERROR 0 //错误代码
#define OK 1

#define LIST_INIT_SIZE 100 //线性表的存储空间的初始分配增量
#define LISTINCREMENT 5 //存储空间分配增量

//注意区分给变量宏定义和给数据类型起别名
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;//数据元素类型约定为ElemType

/*线性表的动态分配顺序存储结构*/
typedef struct {
    ElemType *elem; //存储空间基址,声明了一个名为elem的长度不确定的数组,也叫“动态数组”
    int length; //当前长度
    int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
} SqList;

//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L);

//给顺序表添加数据元素
Status CreateList_Sq(SqList &L);

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status visit(ElemType e);

Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType));

//插入数据元素
Status ListInsert_Sq(SqList &L, int pos, ElemType e);

Status ListDelete_Sq(SqList &L, int pos, ElemType &e);

int main() {//int是函数的返回值
    ElemType e;
    int pos;
    SqList L;//声明一个顺序表
    InitList_Sq(L);//初始化顺序表
    CreateList_Sq(L);//向顺序表中添加元素

    /*插入*/
    printf("请输入要插入的元素位置和元素的值:");
    scanf("%d %d", &pos, &e);
    ListInsert_Sq(L, pos, e);//插入元素

    ListTraverse_Sq(L, visit);//遍历输出元素

    /*删除*/
    printf("请输入删除位置:");
    scanf("%d", &pos);
    ListDelete_Sq(L, pos, e);
    printf("您删除的值是:%d\n", e);
    
    ListTraverse_Sq(L, visit);//遍历输出元素
    return 0;
}

//删除元素
Status ListDelete_Sq(SqList &L, int pos, ElemType &e) {
    if(pos<1 || pos >L.length){
        printf("删除位置有误");
        return ERROR;
    }
    e = L.elem[pos - 1];
    ElemType *p = &L.elem[pos];
//    ElemType *q = &L.elem[L.length-1];
    ElemType *q = L.elem + L.length - 1;
    for (; p <= q; p++) {
        *(p - 1) = *p;
    }
    L.length--;
    return OK;
}//算法2.5

//插入元素
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
    if (pos < 1 || pos > L.length + 1) {
        printf("插入位置有问题");
        return ERROR;
    }
    if (L.length >= L.listsize) {
        ElemType *newbase = (ElemType *) realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
        //realloc()更改已分配的内存单元的大小
        if (!newbase) {
            printf("初始化空间失败");
            exit(OVERFLOW);//exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出
        }
        L.elem = newbase; //新基址
        L.listsize = L.listsize + LISTINCREMENT;
        //printf("L.listsize = %d\n", L.listsize);
    }
    ElemType *q = &(L.elem[pos - 1]);            //q为插入位置,即将插入位置的地址赋给q
    ElemType *p = &(L.elem[L.length - 1]);    //p为最后一个元素的地址
    for (; p >= q; --p) {
        *(p + 1) = *p;                        //插入位置及之后的元素右移
    }
    *q = e;                                    //插入e
    ++L.length;                                //表长增1
    return OK;
}//算法2.4

//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L) {
    L.elem = (ElemType *) malloc(sizeof(ElemType) * LIST_INIT_SIZE);//分配字节空间
    if (!L.elem) {
        printf("初始化空间失败");
        exit(OVERFLOW);//exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;
    return OK;
}//算法2.3

/*创建顺序表,顺序表赋值,输入元素*/
Status CreateList_Sq(SqList &L) {
    int n;
    printf("要输入几个元素:");
    scanf("%d", &n);
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);//读入一个元素
        L.length++;//表长增加1,也可以写成 --L.length
    }
    return OK;
}

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status visit(ElemType e) {
    printf("%d ", e);
    return OK;
}

/*遍历输出元素*/
Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType)) {//函数指针
    if (!L.elem) {
        printf("线性表未初始化或被销毁了!!!");
        return ERROR;
    }
    if (L.length == 0) {//提高算法的健壮性
        printf("线性表中无元素!");
    } else {
        printf("结果是:");
        for (int i = 0; i < L.length; ++i) {
            pfn_visit(L.elem[i]);
            //printf("%d ", L.elem[i]);
        }
        printf("\n");
    }
    return OK;
}

main.cpp

#include "head.h"

int main() {//int是函数的返回值
    ElemType e;
    int pos;
    SqList L;//声明一个顺序表
    InitList_Sq(L);//初始化顺序表
    CreateList_Sq(L);//向顺序表中添加元素

    /*向顺序表L中第pos个位置插入元素e*/
    printf("请输入要插入的元素位置和元素的值:");
    scanf("%d %d", &pos, &e);
    ListInsert_Sq(L, pos, e);//插入元素
    ListTraverse_Sq(L, visit);//遍历输出元素

    /*删除顺序表L中第pos个位置的元素,用e返回删除的值*/
    printf("请输入要删除的位置:");
    scanf("%d", &pos);
    ListDelete_Sq(L, pos, e);
    printf("位置%d上的元素%d被删除\n", pos, e);

    ListTraverse_Sq(L, visit);//遍历输出元素
    return 0;
}

head.h

//线性表的 动态分配顺序存储结构

//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//用到的库文件
#include 
#include 
#include 

//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
//数据元素类型约定为ElemType
typedef int ElemType;

//------线性表的动态分配存储结构------
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 5 // 线性表存储空间的分配增量
typedef struct {
    ElemType *elem; //存储空间基址
    int length; // 当前长度
    int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位
}SqList;

Status InitList_Sq(SqList &L);
Status DestroyList_Sq(SqList &L);
Status ClearList_Sq(SqList &L);
Status ListEmpty_Sq(SqList L);
int ListLength_Sq(SqList L);
Status GetElem_Sq(SqList L, int pos, ElemType &e);
Status compare(ElemType listElem, ElemType e);
int LocateElem_Sq(SqList L, ElemType e, Status (*pfn_compare)(ElemType, ElemType));
Status PriorElem_Sq(SqList L, ElemType cur_e, ElemType &pre_e);
Status NextElem_Sq(SqList L, ElemType cur_e, ElemType &next_e);
Status ListInsert_Sq(SqList &L, int pos, ElemType e);
Status ListDelete_Sq(SqList &L, int pos, ElemType &e);
Status visit(ElemType e);
Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType));
void union_Sq(SqList &La, SqList Lb);
void MergeList(SqList La, SqList Lb, SqList &Lc);
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc);
Status changeElem(SqList &L,ElemType elem,ElemType newElem);
Status CreateList(SqList &L);
Status CreateList_Sq(SqList &L);
void initMenu(SqList L);
void mainMenu();

base_op.cpp

#include "head.h"
//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L){//构造一个空的顺序表,动态申请存储空间
    L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if(!L.elem){//存储分配失败
        printf("初始化失败");
        exit(OVERFLOW);//exit(-1)程序异常退出
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;//空表的初始空间为LIST_INIT_SIZE
    return OK;
}//Initlist_Sq 算法2.3


// 初始条件:线性表L已存在。
// 操作结果:销毁线性表L。
Status DestroyList_Sq(SqList &L) {

    return OK;
}// DestroyList_Sq

// 初始条件:线性表L已存在。
// 操作结果:将L重置为空表。
Status ClearList_Sq(SqList &L) {

    return OK;
}// ClearList_Sq

// 初始条件:线性表L已存在。
// 操作结果:若L为空表,返回TRUE,否则返回FALSE。
Status ListEmpty_Sq(SqList L) {

}// ListEmpty_Sq

// 初始条件:线性表L已存在。
// 操作结果:返回L中数据元素个数。
int ListLength_Sq(SqList L) {

}// ListLength_Sq

// 初始条件:线性表L已存在,1≤pos≤ListLength(L) 。
// 操作结果:用e返回L中第pos个数据元素的值。
Status GetElem_Sq(SqList L, int pos, ElemType &e) {

    return OK;
}// GetElem_Sq

// 初始条件:线性表L已存在,compare()是数据元素判定函数。
// 操作结果:返回L中第1个与e满足compare()的数据元素的位序,若这样的数据元素不存在,则返回值为0。
Status compare(ElemType listElem, ElemType e) {
    if(listElem==e)		//找到元素e
        return TRUE;
    else {
        //printf("在列表中没有值为%d的元素\n", e);
        return FALSE;
    }
}// Compare

//返回L中第一个等于e的数据元素的位序
int LocateElem_Sq(SqList L, ElemType e, Status (*pfn_compare)(ElemType, ElemType)) {

}// LocateElem_Sq 算法2.6

// 初始条件:线性表L已存在。
// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。
Status PriorElem_Sq(SqList L, ElemType cur_e, ElemType &pre_e) {

    return OK;
}

// 初始条件:线性表L已存在。
// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,pre_e无定义。
Status NextElem_Sq(SqList L, ElemType cur_e, ElemType &next_e) {

    return OK;
}

// 初始条件:线性表L已存在,1≤pos≤ListLength(L)+1。
// 操作结果:在L中第pos个位置之前插入新的元素e,L的长度加1。
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
    if (pos<1 || pos>L.length+1) { 			//pos的合法值为1≤pos≤ListLength(L)+1。即插入元素的位置pos应大于 0,小于 线性表的长度+1
        printf("插入位置有问题");
        return ERROR;
    }
    if (L.length >= L.listsize) {			//当前存储空间已满,增加分配
        ElemType *newbase = (ElemType*)realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof(ElemType));
        if (!newbase) {						//realloc更改已分配的内存单元大小
            printf("存储分配失败");
            exit(OVERFLOW);					//存储分配失败
        }
        L.elem = newbase;					//新基址
        L.listsize += LISTINCREMENT;		//增加存储容量
    }
    ElemType *q = &(L.elem[pos-1]);			//q为插入位置,即将插入位置的地址赋给q
    ElemType *p = &(L.elem[L.length-1]);	//p为最后一个元素的地址
    for ( ; p>=q; --p) {
        *(p+1) = *p;						//插入位置及之后的元素右移
    }
    *q = e;									//插入e
    ++L.length;								//表长增1
    return OK;
}//ListInsert_Sq 算法2.4

// 初始条件:线性表L已存在且非空,1≤pos≤ListLength(L)。
// 操作结果:删除L的第pos个数据元素,并用e返回其值,L的长度减1。
Status ListDelete_Sq(SqList &L, int pos, ElemType &e) {
    if (pos>L.length || pos<1) {			//pos的合法值为1<=pos<=ListLength_Sq(L),即删除元素的位置pos应大于 0,小于 线性表的长度+1
        printf("被删除元素的位置有误");
        return ERROR;
    }
    ElemType *p = &(L.elem[pos-1]);			//p为被删除元素的位置 ,即将被删除元素的地址赋给p
    e = *p;									//被删除元素的值赋给e
    ElemType *q = L.elem + L.length - 1;	//表尾元素的位置
    for (++p; p<=q; ++p) {					//被删除元素之后的元素左移
        *(p-1) = *p; 						//假定在线性表{11 12 13 14 15}中删除13,变为{11 12 14 15},
    }										//则有  pos=3,e=13,p=&e,则循环初始条件++p=&(L.elem[3])即*p=14,*(p-1)=*p即将14往前移一位
    --L.length;								//表长减1
    return OK;
}// ListDelete_Sq 算法2.5

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,则操作失败。
Status visit(ElemType e) {
    printf("%d ", e);
    return OK;
}
Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType)) {
    if(!L.elem)	{
        printf("\n线性表未初始化或被销毁了!!!");
        return ERROR;
    }
    if(L.length == 0)
        printf("线性表中无元素!!!");
    for (int i=0; i<L.length; i++) {
        visit(L.elem[i]);
        //printf("%d ", L.elem[i]);
    }
    printf("\n");
    return OK;
}

//顺序表的建立(随机创建)
Status CreateList(SqList &L) {

    return OK;
}
/*创建顺序表,顺序表赋值,输入元素*/
Status CreateList_Sq(SqList &L) {
    int n;
    printf("请输入元素个数:");
    scanf("%d", &n);
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);
        L.length++;
    }
    return OK;
}

base_op.cpp完整版

#include "head.h"
//操作结果:构造一个空的线性表L
Status InitList_Sq(SqList &L){//构造一个空的顺序表,动态申请存储空间
    L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if(!L.elem){//存储分配失败
        printf("初始化失败");
        exit(OVERFLOW);//exit(-1)程序异常退出
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;//空表的初始空间为LIST_INIT_SIZE
    return OK;
}//Initlist_Sq 算法2.3


// 初始条件:线性表L已存在。
// 操作结果:销毁线性表L。
Status DestroyList_Sq(SqList &L) {
    //free(L.elem);
    L.elem = NULL;
    L.length = 0;
    L.listsize = 0;
    return OK;
}// DestroyList_Sq

// 初始条件:线性表L已存在。
// 操作结果:将L重置为空表。
Status ClearList_Sq(SqList &L) {
    L.length = 0;
    return OK;
}// ClearList_Sq

// 初始条件:线性表L已存在。
// 操作结果:若L为空表,返回TRUE,否则返回FALSE。
Status ListEmpty_Sq(SqList L) {
    return L.length ? TRUE : FALSE;
}// ListEmpty_Sq

// 初始条件:线性表L已存在。
// 操作结果:返回L中数据元素个数。
int ListLength_Sq(SqList L) {
    return L.length;
}// ListLength_Sq

// 初始条件:线性表L已存在,1≤pos≤ListLength(L) 。
// 操作结果:用e返回L中第pos个数据元素的值。
Status GetElem_Sq(SqList L, int pos, ElemType &e) {
    e = L.elem[pos-1];
    return OK;
}// GetElem_Sq

// 初始条件:线性表L已存在,compare()是数据元素判定函数。
// 操作结果:返回L中第1个与e满足compare()的数据元素的位序,若这样的数据元素不存在,则返回值为0。
Status compare(ElemType listElem, ElemType e) {
    if(listElem==e)		//找到元素e
        return TRUE;
    else {
        //printf("在列表中没有值为%d的元素\n", e);
        return FALSE;
    }
}// Compare

//返回L中第一个等于e的数据元素的位序
int LocateElem_Sq(SqList L, ElemType e, Status (*pfn_compare)(ElemType, ElemType)) {
    int i = 1;
    ElemType *p = L.elem;
    while(i<=L.length && !pfn_compare(*p++, e))
        i++;
    if(i<=L.length){
        return i;
    }else{
        return 0;
    }
    /*
    for (i = 0; i < L.length; ++i) {
        if(L.elem[i] == e)
            break;
    }*/

}// LocateElem_Sq 算法2.6

// 初始条件:线性表L已存在。
// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。
Status PriorElem_Sq(SqList L, ElemType cur_e, ElemType &pre_e) {
    int i = LocateElem_Sq(L, cur_e, compare);
    if(i==0 || i==1) return ERROR;
    GetElem_Sq(L, i-1, pre_e);
    return OK;
}

// 初始条件:线性表L已存在。
// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,pre_e无定义。
Status NextElem_Sq(SqList L, ElemType cur_e, ElemType &next_e) {
    int i = LocateElem_Sq(L, cur_e, compare);
    if(i==0 || i==L.length) return ERROR;
    GetElem_Sq(L, i+1, next_e);
    return OK;
}

// 初始条件:线性表L已存在,1≤pos≤ListLength(L)+1。
// 操作结果:在L中第pos个位置之前插入新的元素e,L的长度加1。
Status ListInsert_Sq(SqList &L, int pos, ElemType e) {
    if (pos<1 || pos>L.length+1) { 			//pos的合法值为1≤pos≤ListLength(L)+1。即插入元素的位置pos应大于 0,小于 线性表的长度+1
        printf("插入位置有问题");
        return ERROR;
    }
    if (L.length >= L.listsize) {			//当前存储空间已满,增加分配
        ElemType *newbase = (ElemType*)realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof(ElemType));
        if (!newbase) {						//realloc更改已分配的内存单元大小
            printf("存储分配失败");
            exit(OVERFLOW);					//存储分配失败
        }
        L.elem = newbase;					//新基址
        L.listsize += LISTINCREMENT;		//增加存储容量
    }
    ElemType *q = &(L.elem[pos-1]);			//q为插入位置,即将插入位置的地址赋给q
    ElemType *p = &(L.elem[L.length-1]);	//p为最后一个元素的地址
    for ( ; p>=q; --p) {
        *(p+1) = *p;						//插入位置及之后的元素右移
    }
    *q = e;									//插入e
    ++L.length;								//表长增1
    return OK;
}//ListInsert_Sq 算法2.4

// 初始条件:线性表L已存在且非空,1≤pos≤ListLength(L)。
// 操作结果:删除L的第pos个数据元素,并用e返回其值,L的长度减1。
Status ListDelete_Sq(SqList &L, int pos, ElemType &e) {
    if (pos>L.length || pos<1) {			//pos的合法值为1<=pos<=ListLength_Sq(L),即删除元素的位置pos应大于 0,小于 线性表的长度+1
        printf("被删除元素的位置有误");
        return ERROR;
    }
    ElemType *p = &(L.elem[pos-1]);			//p为被删除元素的位置 ,即将被删除元素的地址赋给p
    e = *p;									//被删除元素的值赋给e
    ElemType *q = L.elem + L.length - 1;	//表尾元素的位置
    for (++p; p<=q; ++p) {					//被删除元素之后的元素左移
        *(p-1) = *p; 						//假定在线性表{11 12 13 14 15}中删除13,变为{11 12 14 15},
    }										//则有  pos=3,e=13,p=&e,则循环初始条件++p=&(L.elem[3])即*p=14,*(p-1)=*p即将14往前移一位
    --L.length;								//表长减1
    return OK;
}// ListDelete_Sq 算法2.5

// 初始条件:线性表L已存在。
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦vistit()失败,则操作失败。
Status visit(ElemType e) {
    printf("%d ", e);
    return OK;
}
Status ListTraverse_Sq(SqList L, Status (*pfn_visit)(ElemType)) {
    if(!L.elem)	{
        printf("\n线性表未初始化或被销毁了!!!");
        return ERROR;
    }
    if(L.length == 0)
        printf("线性表中无元素!!!");
    for (int i=0; i<L.length; i++) {
        visit(L.elem[i]);
        //printf("%d ", L.elem[i]);
    }
    printf("\n");
    return OK;
}

//顺序表的建立(随机创建)
Status CreateList(SqList &L) {
    int i;
    srand((unsigned )time(NULL));
    for (i = 0; i < 5; ++i) {
        L.elem[i] = rand() % 100;
        L.length++;
    }
    return OK;
}
/*创建顺序表,顺序表赋值,输入元素*/
Status CreateList_Sq(SqList &L) {
    int n;
    printf("请输入元素个数:");
    scanf("%d", &n);
    printf("请输入%d个元素:", n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &L.elem[i]);
        L.length++;
    }
    return OK;
}

more_op.cpp

#include "head.h"
//将所有在线性表Lb中但不在La中的数据元素插入到La中
void union_Sq(SqList &La, SqList Lb) {
    ElemType e;
    int La_len = ListLength_Sq(La);
    int Lb_len = ListLength_Sq(Lb);				//求线性表的长度
    for (int i=1; i<=Lb_len; i++) {
        GetElem_Sq(Lb, i, e);					//取Lb中第i个数据元素赋给e
        if(!LocateElem_Sq(La, e, compare))
            ListInsert_Sq(La, ++La_len, e);	//La中不存在和e相同的数据元素,刚插入之
    }
}// union_Sq 算法2.1

//已知线性表La和Lb中的数据元素按值非递减排列。归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列。
void MergeList(SqList La, SqList Lb, SqList &Lc) {
    InitList_Sq(Lc);
    int i = 1, j = 1;
    int k = 0;
    ElemType ai, bj;
    int La_len = ListLength_Sq(La);
    int Lb_len = ListLength_Sq(Lb);				//求线性表的长度
    while((i<=La_len) && (j<=Lb_len)) {		//La和Lb均非空
        GetElem_Sq(La, i, ai);				//取La中第i个元素赋给ai
        GetElem_Sq(Lb, j, bj);
        if(ai<=bj) {
            ListInsert_Sq(Lc, ++k, ai);		//插入La中的元素
            ++i;
        } else {
            ListInsert_Sq(Lc, ++k, bj);		//插入Lb中的元素
            ++j;
        }
    }
    while(i<=La_len) {						//插入La剩余的元素
        GetElem_Sq(La, i++, ai);
        ListInsert_Sq(Lc, ++k, ai);
    }
    while(j<=Lb_len) {						//插入Lb剩余的元素
        GetElem_Sq(Lb, i++, bj);
        ListInsert_Sq(Lc, ++k, bj);
    }
}// MergeList 算法2.2


/*
int a;//变量
int b;//变量
int *p;//指针变量, 定义的时候加*代表它是一个指针。
int *p = &a;//指针变量赋值
p = &b;//修改指针变量的值
*p = a;// *p 使用的时候加*  ,取p地址上的元素
*/

//已知线性表La和Lb中的数据元素按值非递减排列。归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列。
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc){
    //InitList_Sq(Lc);
    
	Lc.listsize = La.length +Lb.length;
    Lc.length = Lc.listsize;
    Lc.elem = (ElemType *)malloc(sizeof (ElemType) * Lc.listsize);
    
    ElemType *pa = La.elem, *pb = Lb.elem, *pc = Lc.elem;

    ElemType *pa_last = &La.elem[La.length-1];
    ElemType *pb_last = &Lb.elem[Lb.length-1];

    while (pa <= pa_last && pb <= pb_last){

        if(*pa <= *pb){
            *pc = *pa;
//            printf("111:pa=%d, pb=%d, pc=%d\n", *pa, *pb, *pc);
            pa++;
            pc++;
            Lc.length++;
        }else{
            *pc = *pb;
//            printf("222:pa=%d, pb=%d, pc=%d\n", *pa, *pb, *pc);
            pc++;
            pb++;
            Lc.length++;
        }
    }
    while (pa <= pa_last){
        *pc = *pa;
        pa++;
        pc++;
        Lc.length++;
    }
    while (pb <= pb_last){
        *pc = *pb;
//        printf("333:pa=%d, pb=%d, pc=%d, Lclength=%d\n", *pa, *pb, *pc, Lc.length);
        pc++;
        pb++;
        Lc.length++;
    }
}


//1 2 2 2 3 3 3 4 5 6 7 8
/*
5
1 2 2 3 4
7
2 3 5 6 7 8 9
1 2 2 2 3 3 4 5 6 7 8 9*/

MergeList_Sq函数优化:

//已知线性表La和Lb中的数据元素按值非递减排列。归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列。
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc){
    //InitList_Sq(Lc);
    Lc.listsize = La.length +Lb.length;
    Lc.length = Lc.listsize;
    Lc.elem = (ElemType *)malloc(sizeof (ElemType) * Lc.listsize);
    
    ElemType *pa = La.elem, *pb = Lb.elem, *pc = Lc.elem;
    ElemType *pa_last = La.elem + La.length -1;
    ElemType *pb_last = &Lb.elem[Lb.length-1];
    while (pa <= pa_last && pb <= pb_last){
        if(*pa <= *pb){ *pc++ = *pa++; Lc.length++; }
        else{ *pc++ = *pb++; Lc.length++; }
    }
    while (pa <= pa_last){ *pc++ = *pa++; Lc.length++;}
    while (pb <= pb_last){ *pc++ = *pb++; Lc.length++;}
}

顺序表重点代码

1.线性表的动态分配顺序存储结构

typedef int ElemType;//数据元素类型约定为ElemType

/*线性表的动态分配顺序存储结构*/
typedef struct {
    ElemType *elem; //存储空间基址,声明了一个名为elem的长度不确定的数组,也叫“动态数组”
    int length; //当前长度
    int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
} SqList;

2. 顺序表初始化

Status InitList_Sq(SqList &L){//构造一个空的顺序表,动态申请存储空间
    L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if(!L.elem){//存储分配失败
        printf("初始化失败");
        exit(OVERFLOW);//exit(-1)程序异常退出
    }
    L.length = 0;//空表的长度为0
    L.listsize = LIST_INIT_SIZE;//空表的初始空间为LIST_INIT_SIZE
    return OK;
}//Initlist_Sq 算法2.3

3.顺序表插入元素

    ElemType *q = &(L.elem[pos - 1]);            //q为插入位置,即将插入位置的地址赋给q
    ElemType *p = &(L.elem[L.length - 1]);    //p为最后一个元素的地址
    for (; p >= q; --p) {
        *(p + 1) = *p;                        //插入位置及之后的元素右移
    }
    *q = e;                                    //插入e
    ++L.length;                                //表长增1

4.顺序表删除元素

    ElemType *p = &L.elem[pos];
//  ElemType *q = &L.elem[L.length-1];
    ElemType *q = L.elem + L.length - 1;
    for (; p <= q; p++) {
        *(p - 1) = *p;
    }
    L.length--;

5.在Lb中但不在La中的数据元素插入到La中

//将所有在线性表Lb中但不在La中的数据元素插入到La中
void union_Sq(SqList &La, SqList Lb) {
    ElemType e;
    int La_len = ListLength_Sq(La);
    int Lb_len = ListLength_Sq(Lb);				//求线性表的长度
    for (int i=1; i<=Lb_len; i++) {
        GetElem_Sq(Lb, i, e);					//取Lb中第i个数据元素赋给e
        if(!LocateElem_Sq(La, e, compare))
            ListInsert_Sq(La, ++La_len, e);	//La中不存在和e相同的数据元素,刚插入之
    }
}// union_Sq 算法2.1

6.归并

//已知线性表La和Lb中的数据元素按值非递减排列。归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列。
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc){
    //InitList_Sq(Lc);
    Lc.listsize = La.length +Lb.length;
    Lc.length = Lc.listsize;
    Lc.elem = (ElemType *)malloc(sizeof (ElemType) * Lc.listsize);
    
    ElemType *pa = La.elem, *pb = Lb.elem, *pc = Lc.elem;
    ElemType *pa_last = La.elem + La.length -1;
    ElemType *pb_last = &Lb.elem[Lb.length-1];
    while (pa <= pa_last && pb <= pb_last){
        if(*pa <= *pb){ *pc++ = *pa++; Lc.length++; }
        else{ *pc++ = *pb++; Lc.length++; }
    }
    while (pa <= pa_last){ *pc++ = *pa++; Lc.length++;}
    while (pb <= pb_last){ *pc++ = *pb++; Lc.length++;}
}

顺序表经典例题

1.删除最小值(假设唯一)

#include "head.h"
//从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值
//若顺序表为空则显示出错信息并退出运行
//若删除成功则返回true, 否则返回false
bool Del_Min(SqList &L, ElemType &min_value){
    if(L.length == 0) return false; //表空,中止操作返回

    min_value = L.elem[0];//假定0号元素元素的值最小
    int pos = 1;//假定0号元素元素的值最小,位置为1
    for(int i=1; i<L.length; i++){//遍历寻找最小值的元素
        if(L.elem[i] < min_value){
            min_value = L.elem[i];//更新最小值
            pos = i+1;//当前最小值位置为下标+1
        }
    }
    ListDelete_Sq(L, pos, min_value);//删除L中第pos位置的元素,用min_value返回
    return true;
}

//注意:本题也可用函数返回值返回,两者的区别是:函数返值只能返回一个值,而参数返回(引用传参)可以返回多个值

2.删除最小值(空位填补)

//---------------------删除最小值(假设唯一),空位填补-----------------------
//从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值
//空出的位置由最后一个元素填补
bool Del_Min_fill(SqList &L, ElemType &min_value){
    if(L.length == 0) return false; //表空,中止操作返回
    min_value = L.elem[0];//假定0号元素元素的值最小
    int pos = 1;
    for(int i=1; i<L.length; i++){//遍历寻找最小值的元素
        if(L.elem[i] < min_value){
            min_value = L.elem[i];
            pos = i+1;//当前最小值位置为下标+1
        }
    }
    L.elem[pos-1] = L.elem[L.length-1];//用最后一个元素覆盖要删除位置的元素
    L.length--;//表长减1
    return true;
}

3.顺序表元素逆置

法一:借助辅助空间,空间复杂度O(n)

void Reverse1(SqList &L){
    SqList Lb;//构造一个辅助数组Lb
    InitList_Sq(Lb);//对Lb进行初始化
    for(int i=0; i<L.length; i++){//将L中的元素倒着放到Lb中
        Lb.elem[i] = L.elem[L.length-i-1];
    }
    for (int i = 0; i < L.length; ++i) {//再将Lb中的元素一一对应赋值给L
        L.elem[i] = Lb.elem[i];
    }
}

法二:设计高效算法,空间复杂度O(1)

//设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为 0(1)
#include "head.h"
void Reverse(SqList &L){
    for(int i=0; i<L.length/2; i++){//首尾元素交换法完成元素逆置
        int temp = L.elem[i];
        L.elem[i] = L.elem[L.length - i - 1];
        L.elem[L.length-i-1] = temp;
    }
}

4.删除顺序表L中所有值为x的元素

方法一:

void del_x_1(SqList &L, ElemType x) {
    int a = 0, pos;//e为表中x的位置,a为x的值
    for (int i = 0; i < L.length; ++i) {
        pos = LocateElem_Sq(L, x, compare);
        if(pos == 0 ) break;
        ListDelete_Sq(L, pos, a);
    }
} 

方法二: 用 k 记录顺序表 L 中等于 x 的元素个数,边扫描 L 边统计 k,并将不等于 x 的元素前移 k 个位置,最后修改 L 的长度

//i 0 1 2 3 4 5 6 7 8
//  2 3 6 3 4 3 3 5 2
//  2 6 4 5
//k=3
void del_x_2(SqList &L, ElemType x){
    int k=0;//用k记录等于x的元素个数
    for (int i = 0; i < L.length; ++i) {
        if(L.elem[i]==x) k++;
        else L.elem[i-k] = L.elem[i];
    }
    L.length -= k;
}

方法三:

void del_x_3(SqList &L, ElemType x){
    int k = 0;//用k记录不等于x的元素个数
    for (int i = 0; i < L.length; ++i) {
        if(L.elem[i] != x){
            k++;
            L.elem[k-1] = L.elem[i];
        }
    }
    L.length = k;
}

5.有序顺序表删除s到t

有序顺序表中删除其值在给定值 s 与 t 之间( 要求 s < t )包含s和t 的所有元素

1 2 2 3 4 5 5 7 9--删除2到5之间--->1 7 9

先自己思考15分钟,写不出来了再往下翻,并给示例代码加注释。

bool Del_s_t(SqList &L, ElemType s, ElemType t){
    	/*从这里开始写你的代码*/
    	
        return true;
}

**提示:**因为是有序表 ,所以删除的元素必然是相连的整体。

示例代码:

bool Del_s_t(SqList &L, ElemType s, ElemType t){
    int m = 0, n = 0;
    for (int i = 0; i < L.length; ++i) {
        if(L.elem[i] < s){
            m++;
        }
        if(L.elem[i] >= s && L.elem[i] <= t){
            n++;
        }
    }
    for (int i = m+n; i < L.length; i++) {
        L.elem[m] = L.elem[i];
        m++;
    }
//    L.length -= n;
    L.length = m;
    return true;
}
优化(推荐这个)
//1 1 2 2 3 4 5 5 7 9--删除2到5之间--->1 1 7 9
bool Del_s_t(SqList &L, ElemType s, ElemType t){
    int m = 0, n = 0;
    for (int i = 0; i < L.length; ++i) {
        if(L.elem[i] < s)   m++;
        if(L.elem[i] <= t)    n++;
    }
    for (int j = n; j < L.length; j++)
        L.elem[m++] = L.elem[j];
    L.length = m;
    return true;
}

答案写法
bool Del_s_t_1(SqList &L, ElemType s, ElemType t){
    int i, j;
    if(s>=t || L.length==0) return false;

    for (i = 0; i < L.length && L.elem[i] < s; i++); //寻找值大于等于s的第一个元素的下标i
    if(i >= L.length)   return false;//所有值均小于s, 返回false

    for(j = i; j < L.length && L.elem[j] <= t; j++);//寻找值大于t的第一个元素的下标j

    for(;j<L.length;i++,j++)
        L.elem[i] = L.elem[j];//前移,填补被删除元素位置
    L.length = i;
    return true;
}

你可能感兴趣的:(数据结构,c语言,算法)