动态顺序表
相较于静态顺序表的好处在于其能够根据需要动态地调整存储空间的大小。
以下是动态顺序表的优势:
1. 空间利用更高效:动态顺序表可以根据数据量的增长动态增加容量,避免了因预先分配过大空间而造成的浪费。
2. 灵活性更强:动态顺序表在数据量增大时可以自动扩容,而在数据量减少时可以缩小容量,这种灵活性使得它更加适用于数据规模变化较大的场景。
3. 避免内存泄漏:虽然静态顺序表不存在内存泄漏问题,但动态顺序表通过合理的内存管理(如使用malloc和free函数)也可以避免内存泄漏的风险。
动态顺序表提供了更加灵活和高效的内存管理方式,尤其适合处理数据规模不确定或变化较大的情况。而静态顺序表则在数据规模较小且确定的情况下更为简单和方便。在实际应用中,应根据具体需求选择合适的顺序表类型。
代码实现:
头文件
#define _CRT_SECURE_NO_WARNINGS #pragma once #include<stdio.h> #include<string.h> #include<stdlib.h> #include<assert.h> //增强程序的可维护性 typedef int SQDataType; //动态的 typedef struct SeqList { SQDataType* a; int size; //有效数据的个数 int capacity; //容量 }SL; //增删查改等接口函数 void SeqListInit(SL* ps); void SeqListPrint(SL* ps); void SeqListDestroy(SL* ps); //头插 尾插 头删 尾删 void SeqListPushFront(SL* ps, SQDataType x); void SeqListPushBack(SL* ps, SQDataType x); void SeqListPopBack(SL* ps); void SeqListPopFront(SL* ps); void SeqListInsert(SL* ps, int pos, SQDataType x); void SeqListErase(SL* ps, int pos); //查找 修改 int SeqListFind(SL* ps, SQDataType x); void SeqListModify(SL* ps, int pos, SQDataType x);
源文件
#include"SeqListTest.h" void SeqListInit(SL* ps) { //可以开始给空间ps->a = malloc ps->a = NULL; ps->size = 0; ps->capacity = 0; } void SeqListCheckCapacity(SL* ps) { if (ps->size == ps->capacity) { //满了就要扩容,一般满了扩容两倍,如果一直扩容一个的话,需要一直扩容 int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; //realloc如果刚开始为空则malloc一个空间 SQDataType* tmp = (SQDataType*)realloc(ps->a, newcapacity * sizeof(SQDataType)); if (tmp == NULL) { printf("realloc fail\n"); exit(-1); } else { ps->a = tmp; ps->capacity = newcapacity; } } } void SeqListDestroy(SL* ps) { free(ps->a); ps->a = NULL; ps->capacity = ps->size = 0; } //头插 尾插 头删 尾删 void SeqListPushBack(SL* ps, SQDataType x) { //SeqListCheckCapacity(ps); //ps->a[ps->size] = x; //ps->size++; SeqListInsert(ps, ps->size, x); } void SeqListPushFront(SL* ps, SQDataType x) { //SeqListCheckCapacity(ps); 1、初始条件 2、结束条件 3、迭代过程 //int end = ps->size - 1; //while (end >= 0) //{ // ps->a[end + 1] = ps->a[end]; // --end; //} //ps->a[0] = x; //ps->size++; SeqListInsert(ps, 0, x); } void SeqListPopBack(SL* ps) { //assert(ps->size > 0); //ps->size--; SeqListErase(ps, ps->size - 1); } void SeqListPopFront(SL* ps) { assert(ps->size > 0); //int start = 1; //while (start < ps->size) //{ // ps->a[start - 1] = ps->a[start]; // ++start; //} //ps->size--; SeqListErase(ps, 0); } void SeqListInsert(SL* ps, int pos, SQDataType x) { assert(pos <= ps->size); SeqListCheckCapacity(ps); int end = ps->size - 1; while (end >= pos) { ps->a[end + 1] = ps->a[end]; --end; } ps->a[pos] = x; ps->size++; } void SeqListErase(SL* ps, int pos) { assert(pos < ps->size); int start = pos + 1; while (start < ps->size) { ps->a[start - 1] = ps->a[start]; ++start; } ps->size--; } int SeqListFind(SL* ps, SQDataType x) { for (int i = 0; i < ps->size; i++) { if (ps->a[i] == x) { return i; } } return -1; } void SeqListModify(SL* ps, int pos, SQDataType x) { assert(pos < ps->size); ps->a[pos] = x; } void SeqListPrint(SL* ps) { for (int i = 0; i < ps->size; ++i) { printf("%d ", ps->a[i]); } printf("\n"); }
测试文件
#include"SeqListTest.h" void TestSeqList1() { SL sl; SeqListInit(&sl); SeqListPushBack(&sl, 1); SeqListPushBack(&sl, 2); SeqListPushBack(&sl, 3); SeqListPushBack(&sl, 4); SeqListPushBack(&sl, 5); SeqListPushBack(&sl, 6); printf("头插\n"); SeqListPrint(&sl); } void TestSeqList2() { SL sl; SeqListInit(&sl); SeqListPushFront(&sl, 1); SeqListPushFront(&sl, 2); SeqListPushFront(&sl, 3); SeqListPushFront(&sl, 4); SeqListPushFront(&sl, 5); SeqListPushFront(&sl, 6); printf("尾插\n"); SeqListPrint(&sl); } void TestSeqList3() { SL sl; SeqListInit(&sl); SeqListPushFront(&sl, 1); SeqListPushFront(&sl, 2); SeqListPushFront(&sl, 3); SeqListPushFront(&sl, 4); SeqListPushFront(&sl, 5); SeqListPushFront(&sl, 6); printf("尾删\n"); SeqListPrint(&sl); SeqListPopBack(&sl); SeqListPrint(&sl); } void TestSeqList4() { SL sl; SeqListInit(&sl); SeqListPushFront(&sl, 1); SeqListPushFront(&sl, 2); SeqListPushFront(&sl, 3); SeqListPushFront(&sl, 4); SeqListPushFront(&sl, 5); SeqListPushFront(&sl, 6); printf("头删\n"); SeqListPrint(&sl); SeqListPopFront(&sl); SeqListPrint(&sl); } void TestSeqList5() { SL sl; SeqListInit(&sl); SeqListPushFront(&sl, 1); SeqListPushFront(&sl, 2); SeqListPushFront(&sl, 3); SeqListPushFront(&sl, 4); SeqListPushFront(&sl, 5); SeqListPushFront(&sl, 6); printf("指定位置插入,在下标为1的位置插入了值为20的数\n"); SeqListPrint(&sl); SeqListInsert(&sl, 1, 20); SeqListPrint(&sl); } void TestSeqList6() { SL sl; SeqListInit(&sl); SeqListPushFront(&sl, 1); SeqListPushFront(&sl, 2); SeqListPushFront(&sl, 3); SeqListPushFront(&sl, 4); SeqListPushFront(&sl, 5); SeqListPushFront(&sl, 6); printf("指定位置删除,删除了下标为1的位置的数\n"); SeqListInsert(&sl, 1, 20); SeqListPrint(&sl); SeqListErase(&sl, 1); SeqListPrint(&sl); } void menu() { printf("****************************************************\n"); printf("1.尾插数据 2.头插数据\n"); printf("3.尾删数据 4.头删数据\n"); printf("5.打印数据 -1.退出\n"); printf("****************************************************\n"); printf(" 请输入你要操作的选项 :"); } int main() { /*TestSeqList1(); TestSeqList2(); TestSeqList3(); TestSeqList4(); TestSeqList5(); TestSeqList6();*/ //操作已经测试,无问题, 可以复用insert和erase接口 SL s; SeqListInit(&s); int option = 0; int x = 0; while (option != -1) { menu(); scanf("%d", &option); switch (option) { case 1: printf("请输入你要尾插的数据,以-1结束\n"); do { scanf("%d", &x); if (x != -1) { SeqListPushBack(&s, x); } } while (x != -1); break; case 2: printf("请输入你要头插的数据,以-1结束\n"); do { scanf("%d", &x); if (x != -1) { SeqListPushFront(&s, x); } } while (x != -1); break; case 3: printf("请输入你要尾删几个数据,以-1结束\n"); do { scanf("%d", &x); if (x != -1) { for (int i = 0; i < x; i++) { SeqListPopBack(&s); } } } while (x != -1); break; case 4: printf("请输入你要头删几个数据,以-1结束\n"); do { scanf("%d", &x); if (x != -1) { for (int i = 0; i < x; i++) { SeqListPopFront(&s); } } } while (x != -1); break; case 5: SeqListPrint(&s); break; case 6: printf("请输入你要查找的数据,以-1结束\n"); do { scanf("%d", &x); if (x != -1) { printf("所查找到数据的下标为:"); SeqListFind(&s, x); } } while (x != -1); break; default: break; } } SeqListDestroy(&s); return 0; }
运行结果
(模块测试)
(菜单实现)
尾插:
头插:
尾删:
头删:
退出:
希望对你有帮助,加油!!