顺序表的动态申请空间版本
顺序表的动态版本与静态版本的区别在于:动态版本预先开辟比较小的空间,当空间不足时再追加若干空间,静态顺序表则一次开辟足够大的空间,静态顺序表的实现在我的上一篇博客。
动态顺序表仍需建立一个结构体:
typedef int DataType; //定义DataType类型 typedef struct SeqList { DataType* pData; //动态顺序表,只需创建一个指针维护即可 int count; //有效个数 int capacity; //容量 }SeqList, *pSeqList;每次插入新元素时,都需判断是否现有空间已满,所以用CheckCapacity()函数来检测容量,所以初始化的函数和检测容量的函数显得尤为重要:
void InitSeqList(pSeqList p) //初始化顺序表 { p->pData = (DataType*)malloc(sizeof(DataType)*DEFAULT_SZ); //预先开辟一定大小 if (p->pData == NULL) { perror("malloc失败"); return; } memset(p->pData, 0, sizeof(DataType)*DEFAULT_SZ); //初始化为0 p->count = 0; //有效个数 p->capacity = DEFAULT_SZ; //容量 } void CheckCapacity(pSeqList p) //检测容量 { assert(p); if (p->count == p->capacity) { DataType* ret = (DataType*)realloc(p->pData, sizeof(DataType)*(p->capacity + INC_SZ)); if (ret == NULL) { exit(EXIT_FAILURE); //开辟失败退出程序 } p->pData = ret; p->capacity += INC_SZ; //开辟成功增加容量 } }
1、test.c用来测试
2、seqlist.h用来声明各功能的函数和定义顺序表的结构体
3、seqlist.c文件用来实现seqlist.h文件中声明的函数
具体源码如下:
test.c:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include"seqlist.h" void test() { int input = 0; SeqList list; InitSeqList(&list); do { int ret = 0; int data = 0; menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 0: DestroySeqList(&list); break; case 1: { printf("请输入要尾插的元素:"); scanf("%d",&data); PushBack(&list, data); } break; case 2: PopBack(&list); printf("尾删成功!\n"); break; case 3: { printf("请输入要头插的元素:"); scanf("%d", &data); PushFront(&list, data); } break; case 4: PopFront(&list); printf("头删成功!\n"); break; case 5: { printf("请输入要查找的元素:"); scanf("%d", &data); ret = Find(&list, data); if (ret != -1) { printf("该元素下标为:%d\n", ret); } else { printf("查找不到该元素!\n"); } } break; case 6: { printf("请输入要删除的元素:"); scanf("%d", &data); Remove(&list, data); } break; case 7: { printf("请输入要删除的元素:"); scanf("%d", &data); RemoveAll(&list, data); } break; case 8: Show(&list); break; case 9: Sort(&list); printf("排序成功!\n"); break; case 10: { printf("请输入要查找的元素:"); scanf("%d", &data); ret = BinarySeach(&list, data); if (ret == -1) { printf("无该元素!\n"); } else { printf("该元素下标为:%d\n", ret); } } break; default: printf("请正确选择!\n"); break; } } while (input); } int main() { test(); return 0; }
#ifndef __SEQLIST_H__ #define __SEQLIST_H__ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<assert.h> #define DEFAULT_SZ 3 #define INC_SZ 2 typedef int DataType; typedef struct SeqList { DataType* pData; //动态顺序表,只需创建一个指针 int count; //有效个数 int capacity; //容量 }SeqList, *pSeqList; void menu(); //主界面 void InitSeqList(pSeqList p); //初始化顺序表 void CheckCapacity(pSeqList p);//检测容量 void PushBack(pSeqList p, DataType d); //尾插 void PopBack(pSeqList p); //尾删 void PushFront(pSeqList p, DataType d); //头插 void PopFront(pSeqList p); //头删 int Find(pSeqList p, DataType d); //查找(返回下标) void Remove(pSeqList p, DataType d); //删除第一个找到的元素 void RemoveAll(pSeqList p, DataType d); //删除所有找到的元素 void Show(pSeqList p); //打印顺序表 void Sort(pSeqList p); //排序 int BinarySeach(pSeqList p, DataType d); //二分查找 void DestroySeqList(pSeqList p); //销毁顺序表 #endif //__SEQLIST_H__
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include"seqlist.h" void menu() { printf("***********************************\n"); printf("****1.PushBack 2.PopBack ****\n"); printf("****3.PushFront 4.PopFront ****\n"); printf("****5.Find 6.Remove ****\n"); printf("****7.RemoveAll 8.Show ****\n"); printf("****9.Sort 10.BinarySeach****\n"); printf("**** 0.exit ****\n"); printf("***********************************\n"); } void InitSeqList(pSeqList p) { p->pData = (DataType*)malloc(sizeof(DataType)*DEFAULT_SZ); if (p->pData == NULL) { perror("malloc失败"); return; } memset(p->pData, 0, sizeof(DataType)*DEFAULT_SZ); //初始化为0 p->count = 0; //有效个数 p->capacity = DEFAULT_SZ; //容量 } void CheckCapacity(pSeqList p) //检测容量 { assert(p); if (p->count == p->capacity) { DataType* ret = (DataType*)realloc(p->pData, sizeof(DataType)*(p->capacity + INC_SZ)); if (ret == NULL) { exit(EXIT_FAILURE); //开辟失败退出程序 } p->pData = ret; p->capacity += INC_SZ; //开辟成功增加容量 } } void PushBack(pSeqList p, DataType d) //尾插 { assert(p); CheckCapacity(p); p->pData[p->count] = d; p->count++; } void PopBack(pSeqList p) //尾删 { assert(p); if (p->count == 0) { printf("顺序表已空!\n"); return; } p->count--; //直接将有效元素减一即可 } void PushFront(pSeqList p, DataType d) //头插 { assert(p); int i = p->count-1; CheckCapacity(p); for (i = p->count - 1; i >= 0; i--) { p->pData[i + 1] = p->pData[i]; } p->pData[0] = d; p->count++; } void PopFront(pSeqList p) //头删 { assert(p); int i = 0; if (p->count == 0) { printf("顺序表已空!\n"); return; } for (i = 0; i < p->count; i++) { p->pData[i] = p->pData[i + 1]; } p->count--; } int Find(pSeqList p, DataType d) //查找(返回下标) { assert(p); int i = 0; for (i = 0; i < p->count; i++) { if (p->pData[i] == d) { return i; } } return -1; } void Remove(pSeqList p, DataType d) //删除第一个找到的元素 { assert(p); int ret = 0; ret = Find(p, d); if (ret == -1) { printf("找不到要删除的元素\n"); return; } for (int i = ret; i < p->count-1; i++) { p->pData[i] = p->pData[i + 1]; } p->count--; printf("删除成功!\n"); } void RemoveAll(pSeqList p, DataType d) //删除所有找到的元素 { assert(p); int ret = 0; while (ret != -1) { ret = Find(p, d); if (ret != -1) { for (int i = ret; i < p->count - 1; i++) { p->pData[i] = p->pData[i + 1]; } p->count--; } } } void Show(pSeqList p) //打印顺序表 { assert(p); int i = 0; for (i = 0; i < p->count;i++) { printf("%d ", p->pData[i]); } printf("\n"); } void Sort(pSeqList p) //排序 { assert(p); for (int i = 0; i < p->count - 1; i++) { for (int j = 0; j < p->count - 1 - i; j++) { if (p->pData[j] > p->pData[j + 1]) { int tmp = p->pData[j]; p->pData[j] = p->pData[j + 1]; p->pData[j + 1] = tmp; } } } } int BinarySeach(pSeqList p, DataType d) //二分查找 { assert(p); Sort(p); //要进行二分查找先进行排序 int left = 0; int right = p->count - 1; while (left <= right) { int mid =left - ((left - right) >> 1); if (p->pData[mid] > d) { right = mid - 1; } else if (p->pData[mid] < d) { left = mid + 1; } else { return mid; } } return -1; } void DestroySeqList(pSeqList p) //销毁顺序表 { assert(p); free(p->pData); }