任务描述
定义SqList类型,实现顺序表的基本操作。基本操作的定义参照教材抽象数据类型ADT List的定义。
设顺序表的初始存储空间的容量LIST_INIT_SIZE是10,当顺序表的存储空间已满,扩容时的增量LISTINCREMENT是2。
相关知识
线性表的类型定义
线性表的逻辑结构
线性表的顺序存储结构
编程要求
根据提示,在右侧编辑器补充代码,实现线性表的基本操作。注意以下两点:
(1)void CreateList(SqList*)函数从键盘(测试集)读入线性表中数据元素个数n(n>=0),再依次读入n个数据元素。若读入的n是负值,则视为读入0;
(2)void ListTraverse(SqList)函数的输出格式是用一对花括号{ }将数据元素括起来,数据元素间隔一个空格。例如:对有8个整数的线性表(3, 2, 1, 5, 7, 6, 8, 9),其输出格式是{ 3 2 1 5 7 6 8 9 }。
测试说明
平台会对你编写的代码进行测试:
关注void ListTraverse(SqList)函数的输出格式,见上述编程要求中的注意事项,花括号与数据元素也间隔一个空格。
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define LIST_INIT_SIZE 10
#define LISTINCREMENT 2
typedef int ElemType;
typedef struct
{ElemType* elem;int length;int listsize;
} SqList;Status InitList(SqList* L)
{L->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));if (!L->elem){return OVERFLOW; // 存储分配失败} L->length = 0;L->listsize = LIST_INIT_SIZE;return OK;
}void DestroyList(SqList* L)
{if (L->elem) {free(L->elem);L->elem = NULL;}L->length = 0;L->listsize = 0;
}void ClearList(SqList* L)
{L->length = 0;
}Status ListEmpty(SqList L)
{return L.length == 0 ? TRUE : FALSE;
}int ListLength(SqList L)
{return L.length;
}Status GetElem(SqList L, int i, ElemType* e)
{if (i < 1 || i > L.length){return ERROR; } *e = L.elem[i - 1];return OK;
}int LocateElem(SqList L, ElemType e)
{int i;for (i = 0; i < L.length; i++) {if (L.elem[i] == e) return i + 1; // 返回位序,从1开始}return 0; // 如果没找到,返回0
}Status PriorElem(SqList L, ElemType cur, ElemType* pre)
{int i;for (i = 0; i < L.length; i++) {if (L.elem[i] == cur) {if (i == 0) return ERROR; // cur是第一个元素,没有前驱元素*pre = L.elem[i - 1];return OK;}}return ERROR; // 没有找到cur
}Status NextElem(SqList L, ElemType cur, ElemType* next)
{int i;for (i = 0; i < L.length; i++) {if (L.elem[i] == cur) {if (i == L.length - 1){return ERROR; // cur是最后一个元素,没有后继元素 } *next = L.elem[i + 1];return OK;}}return ERROR; // 没有找到cur
}Status ListInsert(SqList* L, int i, ElemType e)
{int j;if (i < 1 || i > L->length + 1){return ERROR; }if (L->length >= L->listsize) { // 当前存储空间已满,增加存储空间ElemType* newbase = (ElemType*)realloc(L->elem, (L->listsize + LISTINCREMENT) * sizeof(ElemType));if (!newbase){return OVERFLOW; // 存储分配失败}L->elem = newbase;L->listsize += LISTINCREMENT;}for (j = L->length - 1; j >= i - 1; j--) {L->elem[j + 1] = L->elem[j]; // 插入位置及之后的元素后移}L->elem[i - 1] = e;L->length++;return OK;
}Status ListDelete(SqList* L, int i, ElemType* e)
{int j;if (i < 1 || i > L->length){return ERROR; // 删除位置不合法}*e = L->elem[i - 1];for (j = i; j < L->length; j++) {L->elem[j - 1] = L->elem[j]; // 被删除元素之后的元素前移}L->length--;return OK;
}void CreateList(SqList* L)
{int n, i;printf("要输入的元素个数:") ; scanf("%d", &n); // 读取元素数量if (n < 0) n = 0;for (i = 0; i < n; i++) {if (L->length >= L->listsize) { // 当前存储空间已满,增加存储空间L->elem = (ElemType*)realloc(L->elem, (L->listsize + LISTINCREMENT) * sizeof(ElemType));if (!L->elem) exit(1); // 存储分配失败L->listsize += LISTINCREMENT; // 增加存储容量}printf("元素 %d: ", i + 1); scanf("%d", &L->elem[L->length++]); // 读取元素}
}void ListTraverse(SqList L)
{int i;if (L.length > 0){printf("{ ");for (i = 0; i < L.length; i++) {printf("%d", L.elem[i]);if (i < L.length - 1) {printf(" ");}}printf(" }");}else{printf("{ }");}
}
int main() {SqList L;ElemType e;Status status;int i;ElemType new_value;int positions_to_insert[] = {-3, 0, 2, 6, 9, 12}; // 插入元素的位置示例ElemType test_elements[] = {3, 13, 1, 11, 7, 17, 8, 18}; // 用于定位元素位置的测试数组ElemType pre_e, next_e;// 初始化链表status = InitList(&L);if (status != OK) {printf("顺序表初始化失败\n");return 1;}// 创建链表CreateList(&L);// 遍历顺序表printf("顺序表内容: ");ListTraverse(L);printf("\n");// 检查顺序表是否为空if (ListEmpty(L)) {printf("顺序表为空\n");} else {printf("顺序表不为空\n");}// 获取顺序表长度printf("顺序表长度:%d\n", ListLength(L));// 插入元素printf("请输入要插入的元素:");scanf("%d", &new_value);for (i = 0; i < 6; i++) {status = ListInsert(&L, positions_to_insert[i], new_value);if (status == OK) {printf("在第%d个位置插入元素%d后,顺序表内容:", positions_to_insert[i], new_value);ListTraverse(L);printf("\n");} else {printf("插入元素失败,位置:%d\n", positions_to_insert[i]);}}// 删除元素status = ListDelete(&L, 3, &e);if (status == OK) {printf("删除第3个元素后,顺序表内容:");ListTraverse(L);printf("\n");} else {printf("删除元素失败\n");}// 获取第2个元素status = GetElem(L, 2, &e);if (status == OK) {printf("顺序表的第2个元素是:%d\n", e);} else {printf("获取元素失败\n");}// 获取元素的前驱和后继for (i = 1; i <= ListLength(L); i++) {ElemType cur_e;GetElem(L, i, &cur_e);if (PriorElem(L, cur_e, &pre_e) == OK) {printf("元素%d的前驱是:%d\n", cur_e, pre_e);} else {printf("元素%d没有前驱或找不到该元素\n", cur_e);}if (NextElem(L, cur_e, &next_e) == OK) {printf("元素%d的后继是:%d\n", cur_e, next_e);} else {printf("元素%d没有后继或找不到该元素\n", cur_e);}}// 定位元素的位置for (i = 0; i < 8; i++) {int pos = LocateElem(L, test_elements[i]);if (pos) {printf("元素%d在顺序表中的位置是:%d\n", test_elements[i], pos);} else {printf("元素%d不存在\n", test_elements[i]);}}// 销毁顺序表DestroyList(&L);if (L.elem == NULL) {printf("顺序表已销毁\n");}return 0;
}