靜態順序表的實現
阿新 • • 發佈:2018-12-11
順序表:用一段地址連續的儲存地址單元一次儲存資料元素的線性結構。
實現一個具有增、刪、查、改、初始化、輸入、列印等簡單功能的順序表。
實現程式碼如下:
#include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int DataType; #define MAX_SIZE (100) typedef struct SeqList{ DataType array[MAX_SIZE]; int size; // 1. 儲存順序表裡已經存了的資料個數 // 2. 當前可用下標 } SeqList; //typedef struct SeqList SeqList // 介面(函式) // 初始化/銷燬 // 增/刪/查/改(寫) //初始化(函式設計) void SeqListInit(SeqList *pSeq) { //1.初始化 size //2.可能需要去把容器空間清空下 assert(pSeq != NULL); pSeq->size = 0; //memset(pSeq->array, 0, MAX_SIZE * sizeof(DataType)); } //銷燬 void SeqListDestroy(SeqList *pSeq) { assert(pSeq); pSeq->size = 0; } //增 //尾插(儘量和 C++ 的 STL 統一) void SeqListPushBack(SeqList *pSeq, DataType data) { assert(pSeq); //特殊情況(滿了) if (pSeq->size >= MAX_SIZE){ printf("滿了!\n"); assert(0); return; } //正常情況 pSeq->array[pSeq->size] = data; pSeq->size++; } //頭插 void SeqListPushFront(SeqList *pSeq, DataType data) { assert(pSeq); //特殊情況(滿了) if (pSeq->size >= MAX_SIZE){ printf("滿了!\n"); assert(0); return; } //正常情況 //現有資料整體往後搬一格 for (int i = pSeq->size; i > 0; i--) { // 前面是位置 後面是資料 pSeq->array[i] = pSeq->array[i - 1]; } // i 代表的是資料 /* for (int i = pSeq->size - 1; i >= 0; i--) { pSeq->array[i + 1] = pSeq->array[i]; } */ //插入 pSeq->array[0] = data; pSeq->size++; } //中間插入 void SeqListInsert(SeqList *pSeq, int pos, DataType data) { assert(pSeq); assert(pos >= 0 && pos <= pSeq->size); //特殊情況(滿了) if (pSeq->size >= MAX_SIZE){ printf("滿了!\n"); assert(0); return; } //正常情況 // 1. 資料搬移 // 1) 從後往前 2) i 取 資料 [size - 1, pos] for (int i = pSeq->size - 1; i >= pos; i--){ pSeq->array[i + 1] = pSeq->array[i]; } // 2. 插入 pSeq->array[pos] = data; pSeq->size++; } //刪 //尾刪 void SeqListPopBack(SeqList *pSeq) { assert(pSeq); //特殊情況(空了) if (pSeq->size <= 0){ printf("空了!\n"); assert(0); return; } //正常情況 pSeq->size--; } //頭刪 void SeqListPopFront(SeqList *pSeq) { assert(pSeq); //特殊情況(空了) if (pSeq->size <= 0){ printf("空了\n"); assert(0); return; } //通常情況 for (int i = 0; i < pSeq->size; i++){ pSeq->array[i] = pSeq->array[i + 1]; } pSeq->size--; } //中間刪 void SeqListErase(SeqList *pSeq, int pos) { assert(pSeq); assert(pos >= 0 && pos < pSeq->size); // 特殊情況(空了) if (pSeq->size <= 0){ printf("空了!\n"); assert(0); return; } // 資料搬移 // 1) 從前往後 2) i 取位置 for (int i = pos; i <= pSeq->size - 2; i++){ pSeq->array[i] = pSeq->array[i + 1]; } pSeq->size--; } //列印 // 傳指標減少空間,不改變值 void SeqListPrint(const SeqList *pSeq) { assert(pSeq != NULL); for (int i = 0; i < pSeq->size; i++){ printf("%d ", pSeq->array[i]); } printf("\n"); } // 查詢 // 找到第一個遇到的數的下標,沒找到返回 -1 (更理想返回型別 ssize_t) int SeqListFind(SeqList *pSeq, DataType data) { // 特殊情況(空) if (pSeq->size <= 0) { printf("空\n"); assert(0); return -1; } //順序遍歷查詢 for(int i = 0; i < pSeq->size; i++){ if (data == pSeq->array[i]){ //返回下標 return i; } } //沒找到 return -1; } // 查詢(方法2) int SeqListFind2(SeqList *pSeq, DataType data) { // 特殊情況(空) if (pSeq->size <= 0) { printf("空\n"); assert(0); return -1; } //二分查詢(前提:有序) int left = 0; int right = pSeq->size; int mid = 0; while (right>=left){ mid = (left + right) / 2; if (data == pSeq->array[mid]) { // 找到返回下標 return mid; } else if (data > pSeq->array[mid]){ left = mid + 1; } else{ right = mid - 1; } } //沒找到 if (right < left){ return -1; } } // 刪除第二種形態 (根據資料刪除) // 1. 刪遇到的第一個資料 void SeqListRemove(SeqList *pSeq, DataType data) { int pos = SeqListFind(pSeq, data); if (pos == -1){ //沒找到 return; } SeqListErase(pSeq, pos); } //2.刪遇到的所有資料 //(1). void SeqListRemoveAll1(SeqList *pSeq, DataType data) { int pos = 0; while ((pos = SeqListFind(pSeq, data)) != -1){ SeqListErase(pSeq, pos); } } // (2). 一次遍歷刪除 // 好處: 一次遍歷,時間比較快 // 壞處: 開了新空間,空間大小和 size 有關係 // 1) 開新陣列 void SeqListRemoveAll2(SeqList *pSeq, DataType data) { DataType *newArray = (DataType*)malloc(sizeof(DataType)*pSeq->size); int i, j; for (i = 0, j = 0; i < pSeq->size; i++){ if (data != pSeq->array[i]){ newArray[j] = pSeq->array[i]; j++; } } //把資料搬回來 for (i = 0; i < j; i++){ pSeq->array[i] = newArray[i]; } pSeq->size = j; //釋放 free(newArray); } void SeqListRemoveAll3(SeqList *pSeq, DataType data) { int i, j; for (i = 0, j = 0; i < pSeq->size; i++){ if (data != pSeq->array[i]){ pSeq->array[j] = pSeq->array[i]; j++; } } pSeq->size = j; }
測試:
// 使用場景 void test() { // 1. SeqList seqList; SeqListInit(&seqList); // 1. seqList, 2. &seqList // 1). 指標空間更小 2).改變值 // 2. //SeqList *pSeqList; //pSeqList = SeqListInit(); printf("插入:\n"); SeqListPushBack(&seqList, 6); SeqListPushBack(&seqList, 7); SeqListPushBack(&seqList, 8); SeqListPushBack(&seqList, 9); SeqListPrint(&seqList); printf("尾插:\n"); SeqListPopBack(&seqList); SeqListPrint(&seqList); printf("頭插:\n"); SeqListPushFront(&seqList, 4); SeqListPushFront(&seqList, 3); SeqListPushFront(&seqList, 2); SeqListPushFront(&seqList, 1); SeqListPrint(&seqList); printf("中間插:\n"); SeqListInsert(&seqList, 4, 5); SeqListPrint(&seqList); printf("尾刪:\n"); SeqListPopBack(&seqList); SeqListPrint(&seqList); printf("頭刪:\n"); SeqListPopFront(&seqList); SeqListPrint(&seqList); printf("中間刪:\n"); SeqListErase(&seqList, 5); SeqListPrint(&seqList); printf("查詢:\n"); printf("%d\n", SeqListFind(&seqList, 5)); printf("%d\n", SeqListFind2(&seqList, 5)); printf("根據資料刪除:\n"); SeqListRemoveAll1(&seqList,2); SeqListPrint(&seqList); SeqListRemoveAll2(&seqList, 3); SeqListPrint(&seqList); SeqListRemoveAll3(&seqList, 4); SeqListPrint(&seqList); }
主函式:
int main()
{
test();
return 0;
}
效果: