顺序表的动态申请空间版本
顺序表的动态版本与静态版本的区别在于:动态版本预先开辟比较小的空间,当空间不足时再追加若干空间,静态顺序表则一次开辟足够大的空间,静态顺序表的实现在我的上一篇博客。
动态顺序表仍需建立一个结构体:
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;
}
seqlist.h:
#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__
seqlist.c:
#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);
}