C语言:数据结构之顺序表
顺序表
一些比较重要的概念
-
free(),是释放动态申请内存的空间,不可以随便释放一个普通指针的空间
-
指针,存储的是地址,指针的概念一定要注意
-
指针存储的动态的申请的内存的地址,当动态内存被释放后,一定要把指针置为NULL,否则可能会出现问题
顺序表的特点:物理地址连续的存储,可实现增删查改等功能
静态顺序表比较简单,即是用定长的数组储存元素。
动态的顺序表随用随扩容,更加灵活。
SList.h文件中的定义:
#pragma once //动态顺序链表实现 #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int SLDateType; typedef struct SeqList { SLDateType* array; size_t size; size_t capacity; } SeqList;
此处的typedef 是为了将复杂的,不是很好的一些名字重新命名而已,不需要畏惧很长的名字,没有很高大上。
以下是要实现顺序表的一些功能,相对而言,这个CheckCapacity()是一个相对更加重要的实现。
要实现功能如下:
//初始化顺序表 void SeqListInit(SeqList* ps1); //检查空间 void CheckCapacity(SeqList* ps1); //尾插 void SeqListPushBack(SeqList* ps1, SLDateType x); //尾删 void SeqListPopBack(SeqList* ps1); //头插 void SeqListPushFront(SeqList* ps1, SLDateType x); //头删 void SeqListPopFront(SeqList* ps1); //顺序表查找 void SeqListFind(SeqList* ps1, SLDateType x); //顺序表pos位置插入x (pos位置为下标) void SeqListInsert(SeqList* ps1, size_t pos, SLDateType x); //顺序表中删除pos位置的值 (pos位置为下标) void SeqListErase(SeqList* ps1, size_t pos); //顺序表的销毁 void SeqListDestory(SeqList* ps1); //打印顺序表 void SeqListPrint(SeqList* ps1);
以上功能在 realize.c 文件中得到了实现:
realize.c的代码如下
#include "SList.h" //初始化的实现 void SeqListInit(SeqList* ps1) { assert(ps1); ps1->array = NULL; ps1->size = 0; ps1->capacity = 0; } //销毁的实现 void SeqListDestory(SeqList* ps1) { assert(ps1); if (ps1->array != NULL) { free(ps1->array); ps1->array = NULL; ps1->size = 0; ps1->capacity = 0; } } //打印的实现 void SeqListPrint(SeqList* ps1) { assert(ps1); for (int i = 0; i < ps1->size ; i++) { printf("%d ", ps1->array[i]); } printf("\n"); } //检查容积的实现 void CheckCapacity(SeqList*ps1) { assert(ps1); if (ps1->size == ps1->capacity) { int newCapacity = ps1->capacity == 0 ? 4 : ps1->capacity*2; SLDateType* tmp = (SLDateType*)realloc(ps1->array, sizeof(SLDateType) * newCapacity); if (tmp == NULL) { perror("realloc fail"); return; } ps1->array = tmp; ps1->capacity = newCapacity; tmp = NULL; } } //头部插入的实现 void SeqListPushFront(SeqList* ps1, SLDateType x) { assert(ps1); CheckCapacity(ps1); int end = ps1->size - 1; while (end>=0) { ps1->array[end + 1] = ps1->array[end]; end--; } ps1->array[0] = x; ps1->size++; } //头部删除的实现 void SeqListPopFront(SeqList* ps1) { assert(ps1); if (ps1->size == 0) return; int num = ps1->size - 1; for (int i = 0; i < num; i++) { ps1->array[i] = ps1->array[i + 1]; } ps1->size--; } //尾部插入的实现 void SeqListPushBack(SeqList* ps1, SLDateType x) { assert(ps1); CheckCapacity(ps1); ps1->array[ps1->size] = x; ps1->size++; } //尾部删除的实现 void SeqListPopBack(SeqList* ps1) { assert(ps1); if (ps1->size == 0) return; ps1->size--; } //查找的实现 void SeqListFind(SeqList* ps1, SLDateType x) { assert(ps1); for (int i = 0; i < ps1->size; i++) { if (ps1->array[i] == x) printf("%d ", (i + 1)); } return; } //在pos位置插入数字 void SeqListInsert(SeqList* ps1, size_t pos, SLDateType x) { assert(ps1); assert(pos >= 0 && pos <= ps1->size); CheckCapacity(ps1); int end =ps1-> size - 1; while (end>=pos) { ps1->array[end + 1] = ps1->array[end]; end--; } ps1->array[pos] = x; ps1->size++; } //删除pos的位置 void SeqListErase(SeqList* ps1, size_t pos) { assert(ps1); assert(pos >= 0 && pos < ps1->size); while (pos+1 < ps1->size) { ps1->array[pos] = ps1->array[pos + 1]; pos++; } ps1->size--; }
注意:
-
可以使用温柔的检查,如上代码有
if() return;
-
当然也可以暴力一点
直接 assert 断言。
测试样例:
#include "SList.h" void test1() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushFront(&p, 30); SeqListPushFront(&p, 40); SeqListPushFront(&p, 50); SeqListPushFront(&p, 60); SeqListPushFront(&p, 20); SeqListPushFront(&p, 80); SeqListPushFront(&p, 90); SeqListPrint(&p); SeqListDestory(&p); } void test2() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushFront(&p, 30); SeqListPushFront(&p, 40); SeqListPushFront(&p, 50); SeqListPopFront(&p); SeqListPopFront(&p); SeqListPopFront(&p); SeqListPopFront(&p); SeqListPrint(&p); SeqListDestory(&p); } void test3() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushBack(&p, 1); SeqListPushBack(&p, 2); SeqListPushBack(&p, 3); SeqListPushBack(&p, 4); SeqListPushBack(&p, 5); SeqListPrint(&p); SeqListDestory(&p); } void test4() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushBack(&p, 1); SeqListPushBack(&p, 2); SeqListPopBack(&p); SeqListPopBack(&p); SeqListPopBack(&p); SeqListPopBack(&p); SeqListPopBack(&p); SeqListPopBack(&p); SeqListPrint(&p); SeqListDestory(&p); } void test5() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushBack(&p, 1); SeqListPushBack(&p, 2); SeqListPrint(&p); SeqListFind(&p, 10); } void test6() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushBack(&p, 1); SeqListPushBack(&p, 2); SeqListPrint(&p); SeqListInsert(&p, 4, 100); SeqListInsert(&p, 5, 100); SeqListPrint(&p); } void test7() { SeqList p; SeqListInit(&p); SeqListPushFront(&p, 10); SeqListPushFront(&p, 70); SeqListPushBack(&p, 1); SeqListPushBack(&p, 2); SeqListPrint(&p); SeqListErase(&p, 0); SeqListPrint(&p); } int main() { //test1(); //test2(); //test3(); //test4(); //test5(); //test6(); //test7(); }
注意:
-
要学习debug,debug的过程是需要去不断培养进步的
希望各位可以喜欢我的文章,感谢。