第二章线性表代码实现

代码获取

方法1:关注我的公众号,在最后面,扫描就ok了,回复“2262716”。
方法2:https://download.csdn.net/download/m0_61504367/85799926

定义

在这里插入图片描述

/*=============================
 * 线性表的顺序存储结构(顺序表)
 *
 * 包含算法: 2.3、2.4、2.5、2.6
 =============================*/

#ifndef SQLIST_H
#define SQLIST_H

#include <stdio.h>
#include <stdlib.h>     // 提供malloc、realloc、free、exit原型
#include "Status.h"     //**▲01 绪论**//

/* 宏定义 */
#define LIST_INIT_SIZE 100  // 顺序表存储空间的初始分配量
#define LISTINCREMENT  10   // 顺序表存储空间的分配增量

/* 顺序表元素类型定义 */
typedef int ElemType;

/*
 * 顺序表结构
 *
 * 注:elem在使用前需要先为其分配内存,且元素从elem[0]处开始存储
 */
typedef struct {
    
    
    ElemType* elem;     // 顺序表存储空间的基址(指向顺序表所占内存的起始位置)
    int length;   // 当前顺序表长度(包含多少元素)
    int listsize; // 当前分配的存储容量(可以存储多少元素)
} SqList;


/*
 * ████████ 算法2.3 ████████
 *
 * 初始化
 *
 * 初始化成功则返回OK,否则返回ERROR。
 */
Status InitList(SqList* L);

/*
 * 销毁(结构)
 *
 * 释放顺序表所占内存。
 */
Status DestroyList(SqList* L);

/*
 * 置空(内容)
 *
 * 只是清理顺序表中存储的数据,不释放顺序表所占内存。
 */
Status ClearList(SqList* L);

/*
 * 判空
 *
 * 判断顺序表中是否包含有效数据。
 *
 * 返回值:
 * TRUE : 顺序表为空
 * FALSE: 顺序表不为空
 */
Status ListEmpty(SqList L);

/*
 * 计数
 *
 * 返回顺序表包含的有效元素的数量。
 */
int ListLength(SqList L);

/*
 * 取值
 *
 * 获取顺序表中第i个元素,将其存储到e中。
 * 如果可以找到,返回OK,否则,返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数,但这不符合编码的通用约定。
 * 通常,i的含义应该指索引,即从0开始计数。
 */
Status GetElem(SqList L, int i, ElemType* e);

/*
 * ████████ 算法2.6 ████████
 *
 * 查找
 *
 * 返回顺序表中首个与e满足Compare关系的元素位序。
 * 如果不存在这样的元素,则返回0。
 *
 *【备注】
 * 元素e是Compare函数第二个形参
 */
int LocateElem(SqList L, ElemType e, Status(Compare)(ElemType, ElemType));

/*
 * 前驱
 *
 * 获取元素cur_e的前驱,
 * 如果存在,将其存储到pre_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e);

/*
 * 后继
 *
 * 获取元素cur_e的后继,
 * 如果存在,将其存储到next_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e);

/*
 * ████████ 算法2.4 ████████
 *
 * 插入
 *
 * 向顺序表第i个位置上插入e,插入成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListInsert(SqList* L, int i, ElemType e);

/*
 * ████████ 算法2.5 ████████
 *
 * 删除
 *
 * 删除顺序表第i个位置上的元素,并将被删除元素存储到e中。
 * 删除成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListDelete(SqList* L, int i, ElemType* e);

/*
 * 遍历
 *
 * 用visit函数访问顺序表L
 */
void ListTraverse(SqList L, void (Visit)(ElemType));

#endif

详细实现

InitList初始化

/*
 * ████████ 算法2.3 ████████
 *
 * 初始化
 *
 * 初始化成功则返回OK,否则返回ERROR。
 */
Status InitList(SqList* L) {
    
    
    // 分配指定容量的内存,如果分配失败,则返回NULL
    (*L).elem = (ElemType*) malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if((*L).elem == NULL) {
    
    
        // 存储内存失败
        exit(OVERFLOW);
    }
    
    (*L).length = 0;                    // 初始化顺序表长度为0
    (*L).listsize = LIST_INIT_SIZE;     // 顺序表初始内存分配量
    
    return OK;                          // 初始化成功
}

ListEmpty判断是否为空

/*
 * 判空
 *
 * 判断顺序表中是否包含有效数据。
 *
 * 返回值:
 * TRUE : 顺序表为空
 * FALSE: 顺序表不为空
 */
Status ListEmpty(SqList L) {
    
    
    return L.length == 0 ? TRUE : FALSE;
}

ListInsert

/*
 * ████████ 算法2.4 ████████
 *
 * 插入
 *
 * 向顺序表第i个位置上插入e,插入成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListInsert(SqList* L, int i, ElemType e) {
    
    
    ElemType* newbase;
    ElemType* p, * q;
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
        return ERROR;
    }
    
    // i值越界
    if(i < 1 || i > (*L).length + 1) {
    
    
        return ERROR;
    }
    
    // 若存储空间已满,则增加新空间
    if((*L).length >= (*L).listsize) {
    
    
        // 基于现有空间扩容
        newbase = (ElemType*) realloc((*L).elem, ((*L).listsize + LISTINCREMENT) * sizeof(ElemType));
        if(newbase == NULL) {
    
    
            // 存储内存失败
            exit(OVERFLOW);
        }
        
        // 新基址
        (*L).elem = newbase;
        // 存的存储空间
        (*L).listsize += LISTINCREMENT;
    }
    
    // q为插入位置
    q = &(*L).elem[i - 1];
    
    // 1.右移元素,腾出位置
    for(p = &(*L).elem[(*L).length - 1]; p >= q; --p) {
    
    
        *(p + 1) = *p;
    }
    
    // 2.插入e
    *q = e;
    
    // 3.表长增1
    (*L).length++;
    
    return OK;
}

ListTraverse

/*
 * 遍历
 *
 * 用visit函数访问顺序表L
 */
void ListTraverse(SqList L, void(Visit)(ElemType)) {
    
    
    int i;
    
    for(i = 0; i < L.length; i++) {
    
    
        Visit(L.elem[i]);
    }
    
    printf("\n");
}

ListDelete


 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListDelete(SqList* L, int i, ElemType* e) {
    
    
    ElemType* p, * q;
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
        return ERROR;
    }
    
    // i值越界
    if(i < 1 || i > (*L).length) {
    
    
        return ERROR;
    }
    
    // p为被删除元素的位置
    p = &(*L).elem[i - 1];
    
    // 1.获取被删除元素
    *e = *p;
    
    // 表尾元素位置
    q = (*L).elem + (*L).length - 1;
    
    // 2.左移元素,被删除元素的位置上会有新元素进来
    for(++p; p <= q; ++p) {
    
    
        *(p - 1) = *p;
    }
    
    // 3.表长减1
    (*L).length--;
    
    return OK;
}

GetElem

/*
 * 取值
 *
 * 获取顺序表中第i个元素,将其存储到e中。
 * 如果可以找到,返回OK,否则,返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数,但这不符合编码的通用约定。
 * 通常,i的含义应该指索引,即从0开始计数。
 */
Status GetElem(SqList L, int i, ElemType* e) {
    
    
    // 因为i的含义是位置,所以其合法范围是:[1, length]
    if(i < 1 || i > L.length) {
    
    
        return ERROR;                    //i值不合法
    }
    
    *e = L.elem[i - 1];
    
    return OK;
}

LocateElem

/*
 * ████████ 算法2.6 ████████
 *
 * 查找
 *
 * 返回顺序表中首个与e满足Compare关系的元素位序。
 * 如果不存在这样的元素,则返回0。
 *
 *【备注】
 * 元素e是Compare函数第二个形参
 */
int LocateElem(SqList L, ElemType e, Status(Compare)(ElemType, ElemType)) {
    
    
    int i;
    ElemType* p;
    
    // 确保顺序表结构存在
    if(L.elem == NULL) {
    
    
        return ERROR;
    }
    
    /*
     * i的初值为第1个元素的位序
     *
     * 其实,更自然的写法是将i初始化为第1个元素的索引
     * 但由于教材中是按位序计数的,所以这里仍写作位序
     */
    i = 1;
    
    // p的初值为第1个元素的存储位置
    p = L.elem;
    
    // 遍历顺序表
    while(i <= L.length && !Compare(*p++, e)) {
    
    
        ++i;
    }
    
    if(i <= L.length) {
    
    
        return i;
    } else {
    
    
        return 0;
    }
}

前驱节点和后驱节点

/*
 * 前驱
 *
 * 获取元素cur_e的前驱,
 * 如果存在,将其存储到pre_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e) {
    
    
    int i;
    
    // 确保顺序表结构存在,且最少包含两个元素
    if(L.elem == NULL || L.length < 2) {
    
    
        return ERROR;
    }
    
    // 这里的i初始化为第1个元素的【索引】
    i = 0;
    
    // 从第1个元素开始,查找cur_e的位置
    while(i < L.length && L.elem[i] != cur_e) {
    
    
        ++i;
    }
    
    // 如果cur_e是首个元素(没有前驱),或者没找到元素cur_e,返回ERROR
    if(i==0 || i >= L.length) {
    
    
        return ERROR;
    }
    
    // 存储cur_e的前驱
    *pre_e = L.elem[i - 1];
    
    return OK;
}

/*
 * 后继
 *
 * 获取元素cur_e的后继,
 * 如果存在,将其存储到next_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e) {
    
    
    int i;
    
    // 确保顺序表结构存在,且最少包含两个元素
    if(L.elem == NULL || L.length < 2) {
    
    
        return ERROR;
    }
    
    // 这里的i初始化为第1个元素的【索引】
    i = 0;
    
    // 从第1个元素开始,查找cur_e的位置
    while(i < L.length-1 && L.elem[i] != cur_e) {
    
    
        ++i;
    }
    
    // 如果cur_e是最后1个元素(没有前驱),或者没找到元素cur_e,返回ERROR
    if(i >= L.length-1) {
    
    
        return ERROR;
    }
    
    // 存储cur_e的前驱
    *next_e = L.elem[i + 1];
    
    return OK;
}

清空和销毁

/*
 * 销毁(结构)
 *
 * 释放顺序表所占内存。
 */
Status DestroyList(SqList* L) {
    
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
//        不存在
        return ERROR;
    }
    
    // 释放顺序表内存
    free((*L).elem);
    
    // 释放内存后置空指针
    (*L).elem = NULL;
    
    // 顺序表长度跟容量都归零
    (*L).length = 0;
    (*L).listsize = 0;
    
    return OK;
}

/*
 * 置空(内容)
 *
 * 只是清理顺序表中存储的数据,不释放顺序表所占内存。
 */
Status ClearList(SqList* L) {
    
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
        return ERROR;
    }
    
    (*L).length = 0;
    
    return OK;
}

整体代码

main.c

#include <stdio.h>
#include "SqList.h"                                //**02 线性表**//

// 判断data>e是否成立
Status CmpGreater(ElemType data, ElemType e) {
    
    
    return data > e ? TRUE : FALSE;
}

// 测试函数,打印元素
void PrintElem(ElemType e) {
    
    
    printf("%d ", e);
}


int main(int argc, char** argv) {
    
    
    SqList L;   // 待操作的顺序表
    
    int i;
    ElemType e;
    
    printf("████████ InitList \n");
    {
    
    
        printf("█ 初始化顺序表 L ...\n");
        InitList(&L);
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ ListEmpty \n");
    {
    
    
        if(ListEmpty(L) == TRUE) {
    
    
            printf("█ L 为空!!\n");
        } else {
    
    
            printf("█ L 不为空!\n");
        }
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ ListInsert \n");
    {
    
    
        for(i = 1; i <= 8; i++) {
    
    
            printf("█ 作为示范,在 L 第 %d 个位置插入 \"%d\"...\n", i, 2 * i);
            ListInsert(&L, i, 2 * i);
        }
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ ListTraverse \n");
    {
    
    
        printf("█ L 中的元素为:L = ");
        ListTraverse(L, PrintElem);
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ ListLength \n");
    {
    
    
        i = ListLength(L);
        printf("█ L 的长度为 %d \n", i);
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ ListDelete \n");
    {
    
    
        printf("█ 删除前的元素:L = ");
        ListTraverse(L, PrintElem);
        
        printf("█ 尝试删除 L 中第 6 个元素...\n");
        
        if(ListDelete(&L, 6, &e) == OK) {
    
    
            printf("█ 删除成功,被删除元素是:\"%d\"\n", e);
        } else {
    
    
            printf("█ 删除失败,第 6 个元素不存在!\n");
        }
        
        printf("█ 删除后的元素:L = ");
        ListTraverse(L, PrintElem);
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ GetElem \n");
    {
    
    
        GetElem(L, 4, &e);
        printf("█ L 中第 4 个位置的元素为 \"%d\" \n", e);
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ LocateElem \n");
    {
    
    
        i = LocateElem(L, 7, CmpGreater);
        printf("█ L 中第一个元素值大于 \"7\" 的元素是 \"%d\" \n", L.elem[i - 1]);
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ PriorElem \n");
    {
    
    
        ElemType cur_e = 6;
        
        if(PriorElem(L, cur_e, &e) == OK) {
    
    
            printf("█ 元素 \"%d\" 的前驱为 \"%d\" \n", cur_e, e);
        } else {
    
    
            printf("█ 元素 \"%d\" 的前驱不存在!\n", cur_e);
        }
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ NextElem \n");
    {
    
    
        ElemType cur_e = 6;
        
        if(NextElem(L, cur_e, &e) == OK) {
    
    
            printf("█ 元素 \"%d\" 的后继为 \"%d\" \n", cur_e, e);
        } else {
    
    
            printf("█ 元素 \"%d\" 的后继不存在!\n", cur_e);
        }
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ ClearList \n");
    {
    
    
        printf("█ 清空 L 前:");
        if(ListEmpty(L) == TRUE) {
    
    
            printf(" L 为空!!\n");
        } else {
    
    
            printf(" L 不为空!\n");
        }
        
        ClearList(&L);
        
        printf("█ 清空 L 后:");
        if(ListEmpty(L) == TRUE) {
    
    
            printf(" L 为空!!\n");
        } else {
    
    
            printf(" L 不为空!\n");
        }
    }
    PressEnterToContinue(debug);
    
    
    printf("████████ DestroyList \n");
    {
    
    
        printf("█ 销毁 L 前:");
        if(L.elem != NULL) {
    
    
            printf(" L 存在!\n");
        } else {
    
    
            printf(" L 不存在!!\n");
        }
        
        DestroyList(&L);
        
        printf("█ 销毁 L 后:");
        if(L.elem != NULL) {
    
    
            printf(" L 存在!\n");
        } else {
    
    
            printf(" L 不存在!!\n");
        }
    }
    PressEnterToContinue(debug);
    
    
    return 0;
}

Sqlist.c

/*=============================
 * 线性表的顺序存储结构(顺序表)
 *
 * 包含算法: 2.3、2.4、2.5、2.6
 =============================*/

#include "SqList.h"

/*
 * ████████ 算法2.3 ████████
 *
 * 初始化
 *
 * 初始化成功则返回OK,否则返回ERROR。
 */
Status InitList(SqList* L) {
    
    
    // 分配指定容量的内存,如果分配失败,则返回NULL
    (*L).elem = (ElemType*) malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if((*L).elem == NULL) {
    
    
        // 存储内存失败
        exit(OVERFLOW);
    }
    
    (*L).length = 0;                    // 初始化顺序表长度为0
    (*L).listsize = LIST_INIT_SIZE;     // 顺序表初始内存分配量
    
    return OK;                          // 初始化成功
}

/*
 * 销毁(结构)
 *
 * 释放顺序表所占内存。
 */
Status DestroyList(SqList* L) {
    
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
//        不存在
        return ERROR;
    }
    
    // 释放顺序表内存
    free((*L).elem);
    
    // 释放内存后置空指针
    (*L).elem = NULL;
    
    // 顺序表长度跟容量都归零
    (*L).length = 0;
    (*L).listsize = 0;
    
    return OK;
}

/*
 * 置空(内容)
 *
 * 只是清理顺序表中存储的数据,不释放顺序表所占内存。
 */
Status ClearList(SqList* L) {
    
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
        return ERROR;
    }
    
    (*L).length = 0;
    
    return OK;
}

/*
 * 判空
 *
 * 判断顺序表中是否包含有效数据。
 *
 * 返回值:
 * TRUE : 顺序表为空
 * FALSE: 顺序表不为空
 */
Status ListEmpty(SqList L) {
    
    
    return L.length == 0 ? TRUE : FALSE;
}

/*
 * 计数
 *
 * 返回顺序表包含的有效元素的数量。
 */
int ListLength(SqList L) {
    
    
    return L.length;
}

/*
 * 取值
 *
 * 获取顺序表中第i个元素,将其存储到e中。
 * 如果可以找到,返回OK,否则,返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数,但这不符合编码的通用约定。
 * 通常,i的含义应该指索引,即从0开始计数。
 */
Status GetElem(SqList L, int i, ElemType* e) {
    
    
    // 因为i的含义是位置,所以其合法范围是:[1, length]
    if(i < 1 || i > L.length) {
    
    
        return ERROR;                    //i值不合法
    }
    
    *e = L.elem[i - 1];
    
    return OK;
}

/*
 * ████████ 算法2.6 ████████
 *
 * 查找
 *
 * 返回顺序表中首个与e满足Compare关系的元素位序。
 * 如果不存在这样的元素,则返回0。
 *
 *【备注】
 * 元素e是Compare函数第二个形参
 */
int LocateElem(SqList L, ElemType e, Status(Compare)(ElemType, ElemType)) {
    
    
    int i;
    ElemType* p;
    
    // 确保顺序表结构存在
    if(L.elem == NULL) {
    
    
        return ERROR;
    }
    
    /*
     * i的初值为第1个元素的位序
     *
     * 其实,更自然的写法是将i初始化为第1个元素的索引
     * 但由于教材中是按位序计数的,所以这里仍写作位序
     */
    i = 1;
    
    // p的初值为第1个元素的存储位置
    p = L.elem;
    
    // 遍历顺序表
    while(i <= L.length && !Compare(*p++, e)) {
    
    
        ++i;
    }
    
    if(i <= L.length) {
    
    
        return i;
    } else {
    
    
        return 0;
    }
}

/*
 * 前驱
 *
 * 获取元素cur_e的前驱,
 * 如果存在,将其存储到pre_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e) {
    
    
    int i;
    
    // 确保顺序表结构存在,且最少包含两个元素
    if(L.elem == NULL || L.length < 2) {
    
    
        return ERROR;
    }
    
    // 这里的i初始化为第1个元素的【索引】
    i = 0;
    
    // 从第1个元素开始,查找cur_e的位置
    while(i < L.length && L.elem[i] != cur_e) {
    
    
        ++i;
    }
    
    // 如果cur_e是首个元素(没有前驱),或者没找到元素cur_e,返回ERROR
    if(i==0 || i >= L.length) {
    
    
        return ERROR;
    }
    
    // 存储cur_e的前驱
    *pre_e = L.elem[i - 1];
    
    return OK;
}

/*
 * 后继
 *
 * 获取元素cur_e的后继,
 * 如果存在,将其存储到next_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e) {
    
    
    int i;
    
    // 确保顺序表结构存在,且最少包含两个元素
    if(L.elem == NULL || L.length < 2) {
    
    
        return ERROR;
    }
    
    // 这里的i初始化为第1个元素的【索引】
    i = 0;
    
    // 从第1个元素开始,查找cur_e的位置
    while(i < L.length-1 && L.elem[i] != cur_e) {
    
    
        ++i;
    }
    
    // 如果cur_e是最后1个元素(没有前驱),或者没找到元素cur_e,返回ERROR
    if(i >= L.length-1) {
    
    
        return ERROR;
    }
    
    // 存储cur_e的前驱
    *next_e = L.elem[i + 1];
    
    return OK;
}

/*
 * ████████ 算法2.4 ████████
 *
 * 插入
 *
 * 向顺序表第i个位置上插入e,插入成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListInsert(SqList* L, int i, ElemType e) {
    
    
    ElemType* newbase;
    ElemType* p, * q;
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
        return ERROR;
    }
    
    // i值越界
    if(i < 1 || i > (*L).length + 1) {
    
    
        return ERROR;
    }
    
    // 若存储空间已满,则增加新空间
    if((*L).length >= (*L).listsize) {
    
    
        // 基于现有空间扩容
        newbase = (ElemType*) realloc((*L).elem, ((*L).listsize + LISTINCREMENT) * sizeof(ElemType));
        if(newbase == NULL) {
    
    
            // 存储内存失败
            exit(OVERFLOW);
        }
        
        // 新基址
        (*L).elem = newbase;
        // 存的存储空间
        (*L).listsize += LISTINCREMENT;
    }
    
    // q为插入位置
    q = &(*L).elem[i - 1];
    
    // 1.右移元素,腾出位置
    for(p = &(*L).elem[(*L).length - 1]; p >= q; --p) {
    
    
        *(p + 1) = *p;
    }
    
    // 2.插入e
    *q = e;
    
    // 3.表长增1
    (*L).length++;
    
    return OK;
}

/*
 * ████████ 算法2.5 ████████
 *
 * 删除
 *
 * 删除顺序表第i个位置上的元素,并将被删除元素存储到e中。
 * 删除成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListDelete(SqList* L, int i, ElemType* e) {
    
    
    ElemType* p, * q;
    
    // 确保顺序表结构存在
    if(L == NULL || (*L).elem == NULL) {
    
    
        return ERROR;
    }
    
    // i值越界
    if(i < 1 || i > (*L).length) {
    
    
        return ERROR;
    }
    
    // p为被删除元素的位置
    p = &(*L).elem[i - 1];
    
    // 1.获取被删除元素
    *e = *p;
    
    // 表尾元素位置
    q = (*L).elem + (*L).length - 1;
    
    // 2.左移元素,被删除元素的位置上会有新元素进来
    for(++p; p <= q; ++p) {
    
    
        *(p - 1) = *p;
    }
    
    // 3.表长减1
    (*L).length--;
    
    return OK;
}

/*
 * 遍历
 *
 * 用visit函数访问顺序表L
 */
void ListTraverse(SqList L, void(Visit)(ElemType)) {
    
    
    int i;
    
    for(i = 0; i < L.length; i++) {
    
    
        Visit(L.elem[i]);
    }
    
    printf("\n");
}

Sqlist.h

/*=============================
 * 线性表的顺序存储结构(顺序表)
 *
 * 包含算法: 2.3、2.4、2.5、2.6
 =============================*/

#ifndef SQLIST_H
#define SQLIST_H

#include <stdio.h>
#include <stdlib.h>     // 提供malloc、realloc、free、exit原型
#include "Status.h"     //**▲01 绪论**//

/* 宏定义 */
#define LIST_INIT_SIZE 100  // 顺序表存储空间的初始分配量
#define LISTINCREMENT  10   // 顺序表存储空间的分配增量

/* 顺序表元素类型定义 */
typedef int ElemType;

/*
 * 顺序表结构
 *
 * 注:elem在使用前需要先为其分配内存,且元素从elem[0]处开始存储
 */
typedef struct {
    
    
    ElemType* elem;     // 顺序表存储空间的基址(指向顺序表所占内存的起始位置)
    int length;   // 当前顺序表长度(包含多少元素)
    int listsize; // 当前分配的存储容量(可以存储多少元素)
} SqList;


/*
 * ████████ 算法2.3 ████████
 *
 * 初始化
 *
 * 初始化成功则返回OK,否则返回ERROR。
 */
Status InitList(SqList* L);

/*
 * 销毁(结构)
 *
 * 释放顺序表所占内存。
 */
Status DestroyList(SqList* L);

/*
 * 置空(内容)
 *
 * 只是清理顺序表中存储的数据,不释放顺序表所占内存。
 */
Status ClearList(SqList* L);

/*
 * 判空
 *
 * 判断顺序表中是否包含有效数据。
 *
 * 返回值:
 * TRUE : 顺序表为空
 * FALSE: 顺序表不为空
 */
Status ListEmpty(SqList L);

/*
 * 计数
 *
 * 返回顺序表包含的有效元素的数量。
 */
int ListLength(SqList L);

/*
 * 取值
 *
 * 获取顺序表中第i个元素,将其存储到e中。
 * 如果可以找到,返回OK,否则,返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数,但这不符合编码的通用约定。
 * 通常,i的含义应该指索引,即从0开始计数。
 */
Status GetElem(SqList L, int i, ElemType* e);

/*
 * ████████ 算法2.6 ████████
 *
 * 查找
 *
 * 返回顺序表中首个与e满足Compare关系的元素位序。
 * 如果不存在这样的元素,则返回0。
 *
 *【备注】
 * 元素e是Compare函数第二个形参
 */
int LocateElem(SqList L, ElemType e, Status(Compare)(ElemType, ElemType));

/*
 * 前驱
 *
 * 获取元素cur_e的前驱,
 * 如果存在,将其存储到pre_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e);

/*
 * 后继
 *
 * 获取元素cur_e的后继,
 * 如果存在,将其存储到next_e中,返回OK,
 * 如果不存在,则返回ERROR。
 */
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e);

/*
 * ████████ 算法2.4 ████████
 *
 * 插入
 *
 * 向顺序表第i个位置上插入e,插入成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListInsert(SqList* L, int i, ElemType e);

/*
 * ████████ 算法2.5 ████████
 *
 * 删除
 *
 * 删除顺序表第i个位置上的元素,并将被删除元素存储到e中。
 * 删除成功则返回OK,否则返回ERROR。
 *
 *【备注】
 * 教材中i的含义是元素位置,从1开始计数
 */
Status ListDelete(SqList* L, int i, ElemType* e);

/*
 * 遍历
 *
 * 用visit函数访问顺序表L
 */
void ListTraverse(SqList L, void (Visit)(ElemType));

#endif

运行结果

████████ InitList
█ 初始化顺序表 L ...

████████ ListEmpty
█ L 为空!!

████████ ListInsert
█ 作为示范,在 L 第 1 个位置插入 "2"...
█ 作为示范,在 L 第 2 个位置插入 "4"...
█ 作为示范,在 L 第 3 个位置插入 "6"...
█ 作为示范,在 L 第 4 个位置插入 "8"...
█ 作为示范,在 L 第 5 个位置插入 "10"...
█ 作为示范,在 L 第 6 个位置插入 "12"...
█ 作为示范,在 L 第 7 个位置插入 "14"...
█ 作为示范,在 L 第 8 个位置插入 "16"...

████████ ListTraverse
█ L 中的元素为:L = 2 4 6 8 10 12 14 16

████████ ListLength
█ L 的长度为 8

████████ ListDelete
█ 删除前的元素:L = 2 4 6 8 10 12 14 16
█ 尝试删除 L 中第 6 个元素...
█ 删除成功,被删除元素是:"12"
█ 删除后的元素:L = 2 4 6 8 10 14 16

████████ GetElem
█ L 中第 4 个位置的元素为 "8"

████████ LocateElem
█ L 中第一个元素值大于 "7" 的元素是 "8"

████████ PriorElem
█ 元素 "6" 的前驱为 "4"

████████ NextElem
█ 元素 "6" 的后继为 "8"

████████ ClearList
█ 清空 L 前: L 不为空!
█ 清空 L 后: L 为空!!

████████ DestroyList
█ 销毁 L 前: L 存在!
█ 销毁 L 后: L 不存在!!


Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/m0_61504367/article/details/125484906