C語言如何實現(xiàn)順序表(數(shù)據(jù)結(jié)構(gòu))
以下是我們需要實現(xiàn)的順序表的功能。
以下是寫在SeqList.h中的內(nèi)容,我們將全部需要聲明的內(nèi)容放在此處
pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> typedef int SLDateType; typedef struct SeqList { SLDateType* a; size_t size;// 當前存儲的數(shù)據(jù)個數(shù) size_t capacity; //允許的最大容量 }SeqList; // 對數(shù)據(jù)的管理:增刪查改 void SeqListInit(SeqList* ps);//初始化順序表 void SeqListDestory(SeqList* ps);//摧毀順序表 void SLCheckCapacity(SeqList * ps);//檢查空間是否充足 void SeqListPrint(SeqList* ps);//打印列表中的所有元素的值 void SeqListPushBack(SeqList* ps, SLDateType x);//在表尾插入數(shù)據(jù) void SeqListPushFront(SeqList* ps, SLDateType x);//在表頭位置插入數(shù)組 void SeqListPopFront(SeqList* ps);//彈出列表的首個元素 void SeqListPopBack(SeqList* ps);//彈出列表的尾元素 // 順序表查找 int SeqListFind(SeqList* ps, SLDateType x); // 順序表在pos位置插入x void SeqListInsert(SeqList* ps, size_t pos, SLDateType x); // 順序表刪除pos位置的值 void SeqListErase(SeqList* ps, size_t pos);
接下來我們來實現(xiàn)函數(shù)具體的功能
以下代碼是寫在SeqList.c中的內(nèi)容
一、初始化順序表
這里我們用assert判斷ps是否為NULL,也就是我們的順序表是否創(chuàng)建成功。
如果創(chuàng)建成功,我們就將順序表中的數(shù)組,當前的元素個數(shù),順序表的大小初始化。
并且打印初始化成功來提示我們完成了初始化。
#include"SeqList.h" void SeqListInit(SeqList* ps) { assert(ps); ps->a=NULL; ps->capacity=0; ps->size=0; printf("初始化列表成功\n"); }
二、從表尾插入元素
在用assert實現(xiàn)斷言之后,我們用(四)中的函數(shù)功能檢查ps當前的空間是否充足,在空間充足之后,我們在順序表的表尾添加我們的新元素。
void SeqListPushBack(SeqList* ps, SLDateType x) { assert(ps); SLCheckCapacity(ps); ps->a[ps->size]=x; ps->size++; printf("已成功添加至表尾\n"); }
三、打印順序表
在斷言之后,我們按照順序挨個打印順序表中的元素。
void SeqListPrint(SeqList* ps) { assert(ps); for(int i=0;i<ps->capacity;i++) { printf("%d\t",ps->a[i]); } printf("\n"); printf("成功打印\n"); }
四、檢查順序表的空間是否充足
當我們判斷當前的已經(jīng)含有的元素個數(shù)和總的存儲空間大小相同的時候,先判斷當前元素大小是不是0,如果是0,我們就將新的元素個數(shù)賦值為4,如果不是0,也就是不是初始化之后,我們將我們的元素個數(shù)×2。
當然,我們的realloc函數(shù)存在開辟空間失敗的問題,我們需要進行一定的判斷。
void SLCheckCapacity(SeqList * ps) { if (ps->size == ps->capacity) { int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; SLDateType* tmp = (SLDateType*)realloc(ps->a, newCapacity*sizeof(SLDateType)); if (tmp == NULL) { printf("realloc fail\n"); //exit(-1); return; } ps->a = tmp; ps->capacity = newCapacity; } }
五、在順序表表首插入元素
我們需要先將順序表中的每個元素后移一位,然后在表首的位置插入我們需要插入的元素。
void SeqListPushFront(SeqList* ps, SLDateType x) { assert(ps); SLCheckCapacity(ps); for(int end=ps->size;end>=0;end--) { ps->a[end+1]=ps->a[end]; } ps->a[0]=x; printf("在表首元素插入成功\n"); }
六、摧毀數(shù)據(jù)表
摧毀數(shù)據(jù)表我們需要將數(shù)據(jù)表的數(shù)組指針置空,將其中的元素個數(shù)和大小全部賦零。
void SeqListDestory(SeqList* ps) { assert(ps); ps->a=NULL; ps->capacity=0; ps->size=0; printf("摧毀列表成功\n"); }
七、彈出順序表的首元素
將首元素彈出并且打印之后,我們將首元素之后的元素每一個元素往前移動。
void SeqListPopFront(SeqList* ps) { assert(ps); if(ps->a[0]!=NULL) { int temp=ps->a[0]; printf("數(shù)組的首元素是%d,已成功從列表中彈出\n",temp); for(int i=0;i<ps->capacity-1;i++) { ps->a[i]=ps->a[i+1]; } ps->capacity-=1; } else { printf("當前列表為空,無法彈出首元素\n"); } }
八、彈出順序表的表尾元素
將表尾的元素打印,并且將總的元素個數(shù)-1
void SeqListPopBack(SeqList* ps) { assert(ps); printf("數(shù)組的尾元素是%d,已成功從列表中彈出\n",ps->a[ps->capacity-1]); ps->capacity-=1; }
九、查找順序表中的元素,并返回第一次出現(xiàn)的位置
我們采用for循環(huán)的形式查找順序表中指定元素的位置,然后返回其下標。
int SeqListFind(SeqList* ps, SLDateType x) { assert(ps); for(int i=0;i<ps->capacity;i++) { if(ps->a[i]==x) { printf("在順序表的%d位置(此處為真實位置-1)查找到了%d元素\n",i,x); return i; } } printf("查找不到該元素\n"); return -1; }
十、在指定位置插入元素
在指定位置插入元素,我們需要將指定位置之后的元素后移一位,為我們的指定位置的元素騰出空間,然后將我們的元素插入。
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x) { assert(ps); assert(pos >= 0 && pos <= ps->size); //檢查空間 ps->capacity++; SLCheckCapacity(ps); for(int end=ps->size;end>=pos;end--) { ps->a[end]=ps->a[end-1]; } ps->a[pos-1]=x; printf("已經(jīng)在列表的%d位置成功插入%d元素\n",pos,x); }
十一、刪除指定位置的元素
我們將指定位置之后的元素挨個往前移動,就能夠刪除指定位置的元素。
void SeqListErase(SeqList* ps, size_t pos) { assert(ps); assert(pos >= 0 && pos <= ps->size); for(int i=pos;i<ps->capacity-1;i++) { ps->a[i-1]=ps->a[i]; } ps->capacity--; printf("已經(jīng)成功刪除列表%d位置處的元素\n",pos); }
接下來就是我們的測試代碼
以下代碼寫在test.c文件中
#include "SeqList.h" int main() { SeqList sl; SeqListInit(&sl); SeqListPushBack(&sl,10); SeqListPushBack(&sl,1); SeqListPushBack(&sl,20); SeqListPushBack(&sl,30); SeqListPushFront(&sl, 8); SeqListPrint(&sl); SeqListPopFront(&sl); SeqListPrint(&sl); printf("%d",sl.capacity); SeqListPopBack(&sl); SeqListPrint(&sl); SeqListFind(&sl,0); SeqListInsert(&sl,4, 10); SeqListPrint(&sl); SeqListErase(&sl,3); SeqListPrint(&sl); SeqListDestory(&sl); printf("程序已完成執(zhí)行"); return 0; }
以下是SeqList.c中代碼的合集
// // Created by 楊凱亮 on 2022/4/22. // #include"SeqList.h" void SeqListInit(SeqList* ps) { assert(ps); ps->a=NULL; ps->capacity=0; ps->size=0; printf("初始化列表成功\n"); } void SeqListPushBack(SeqList* ps, SLDateType x) { assert(ps); SLCheckCapacity(ps); ps->a[ps->size]=x; ps->size++; printf("已成功添加至表尾\n"); } void SeqListPrint(SeqList* ps) { assert(ps); for(int i=0;i<ps->capacity;i++) { printf("%d\t",ps->a[i]); } printf("\n"); printf("成功打印\n"); } void SLCheckCapacity(SeqList * ps) { if (ps->size == ps->capacity) { int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; SLDateType* tmp = (SLDateType*)realloc(ps->a, newCapacity*sizeof(SLDateType)); if (tmp == NULL) { printf("realloc fail\n"); //exit(-1); return; } ps->a = tmp; ps->capacity = newCapacity; } } void SeqListPushFront(SeqList* ps, SLDateType x) { assert(ps); SLCheckCapacity(ps); for(int end=ps->size;end>=0;end--) { ps->a[end+1]=ps->a[end]; } ps->a[0]=x; printf("在表首元素插入成功\n"); } void SeqListDestory(SeqList* ps) { assert(ps); ps->a=NULL; ps->capacity=0; ps->size=0; printf("摧毀列表成功\n"); } void SeqListPopFront(SeqList* ps) { assert(ps); if(ps->a[0]!=NULL) { int temp=ps->a[0]; printf("數(shù)組的首元素是%d,已成功從列表中彈出\n",temp); for(int i=0;i<ps->capacity-1;i++) { ps->a[i]=ps->a[i+1]; } ps->capacity-=1; } else { printf("當前列表為空,無法彈出首元素\n"); } } void SeqListPopBack(SeqList* ps) { assert(ps); printf("數(shù)組的尾元素是%d,已成功從列表中彈出\n",ps->a[ps->capacity-1]); ps->capacity-=1; } int SeqListFind(SeqList* ps, SLDateType x) { assert(ps); for(int i=0;i<ps->capacity;i++) { if(ps->a[i]==x) { printf("在順序表的%d位置(此處為真實位置-1)查找到了%d元素\n",i,x); return i; } } printf("查找不到該元素\n"); return -1; } void SeqListInsert(SeqList* ps, size_t pos, SLDateType x) { assert(ps); assert(pos >= 0 && pos <= ps->size); //檢查空間 ps->capacity++; SLCheckCapacity(ps); for(int end=ps->size;end>=pos;end--) { ps->a[end]=ps->a[end-1]; } ps->a[pos-1]=x; printf("已經(jīng)在列表的%d位置成功插入%d元素\n",pos,x); } void SeqListErase(SeqList* ps, size_t pos) { assert(ps); assert(pos >= 0 && pos <= ps->size); for(int i=pos;i<ps->capacity-1;i++) { ps->a[i-1]=ps->a[i]; } ps->capacity--; printf("已經(jīng)成功刪除列表%d位置處的元素\n",pos); }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語言詳解關(guān)鍵字sizeof與unsigned及signed的用法
這篇文章主要為大家詳細介紹了C語言關(guān)鍵字sizeof&&unsigned&&signed,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06詳解C++ 臨時量與臨時對象及程序的相關(guān)優(yōu)化
這篇文章主要介紹了C++ 臨時量與臨時對象及程序的相關(guān)優(yōu)化,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04C++可調(diào)用對象callable object深入分析
所謂的callable object,表示可以被某種方式調(diào)用其某些函數(shù)的對象。它可以是:一個函數(shù)、一個指向成員函數(shù)的指針、一個函數(shù)對象,該對象擁有operator()、一個lambda表達式,嚴格的說它是一種函數(shù)對象2022-08-08C++11 std::function和std::bind 的使用示例詳解
C++11中的std::function和std::bind是函數(shù)對象的重要組成部分,它們可以用于將函數(shù)和參數(shù)綁定在一起,形成一個可調(diào)用的對象,這篇文章主要介紹了C++11 std::function和std::bind 的使用示例詳解,需要的朋友可以參考下2023-03-03C++ 中的INT_MAX,INT_MIN數(shù)值大小操作
這篇文章主要介紹了C++ 中的INT_MAX,INT_MIN數(shù)值大小操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03