数据结构
接着看一下顺序表的其他知识
一、顺序表的删除
1.头删
从头开始从后向前挪动数据,原来第一位的数据会被覆盖以达到删除的目的。
//头删
void SeqListPopFront(SeqList* p)
{
assert(p);
assert(p->size > 0);
int i = 0;
for (i = 0; i < p->size - 1; i++)//从前向后遍历挪动数据
p->a[i] = p->a[i + 1];
p->size--;
}
2.尾删
只需让数组中有效数据的个数-1即可,由于顺序表的size减小1,所以此时不会访问到被删除的数据,虽然没有真正的删除掉末尾的数据,但达到了删除的目的。
//尾删
void SeqListPopBack(SeqList* p)
{
assert(p);
assert(p->size > 0);
CheckCapacity(p);
p->size--;
}
3.任意删
任意位置实现数据的删除只需将该位置及该位置之后的数据向前挪动一位即可。
//任意删除数据
void SeqListErase(SeqList* p, int pos)
{
assert(p);
assert(pos >= 0 && pos < p->size);
CheckCapacity(p);
int i = pos;
for (; i < p->size - 1; i++)
p->a[i] = p->a[i + 1];//向前挪动数据
p->size--;
}
效果如下图所示,完整代码在最后
二、顺序表的数据
1.查找
查找即遍历
//查找(第一个)值为x的数据的下标
int SeqListFind(SeqList* p, SeqListDataType x)
{
assert(p);
int i = 0;
for (i = 0; i < p->size; i++)
{
if (p->a[i] == x)
{
printf("1的位置的下标为%d\n",i);
}
// return i;
}
return -1;//找不到返回-1
}
2.修改
修改很简单,直接赋值就行
//将pos位置的值修改为x
void SeqListModify(SeqList* p, int pos, SeqListDataType x)
{
assert(p);
assert(pos >= 0 && pos < p->size);
p->a[pos] = x;
}
三、顺序表的优缺点
有关顺序表的优缺点,在面试的时候可能会问到,顺序表就是数组嘛,数组的缺点大家都知道,存储数据量会占用内容。
1.缺点
1.在头部插入效率低
2.顺序表容量有限,扩容时容量不具体浪费时间。
2.优点
1.容易理解
2.访问效率高
总结
实际应用中很少采用数据表,大都使用链表,链表可以很好的解决顺序表的缺点。
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define N 10
typedef int SeqListDataType;
typedef struct SeqList
{
SeqListDataType *a;//存储数据的数组(动态开辟)
int size;//顺序表中当前有效数据的个数
int capacity;//顺序表中最大存储的个数
}SeqList;
//初始化
int SeqListInit(SeqList *p)
{
assert(p);//用assert来防止传入空指针使程序崩掉
p->a = (int *)malloc(sizeof(int) * N);//将指向动态开辟的数组置为NULL。
p->size = 0;
p->capacity = 0;
return 1;
}
//销毁
void SeqListDestroy(SeqList *p)
{
assert(p != NULL);
free(p->a);//释放动态开辟的空间
p->a = NULL;
p->size = 0;
p->capacity = 0;
}
//扩容
void CheckCapacity(SeqList* p)
{
if (p->size == p->capacity)
{
int newcapacity = (p->capacity == 0) ? 4 : (p->capacity * 2);
//如果容量为0(第一次插入数据),默认开辟4个SeqListDataType的空间
//如果是在插入数据过程中顺序表已满,则将空间变为2倍(将空间变为2倍也可能会出现空间浪费的情况)
//这里扩容的倍数需要具体情况具体分析,此处以2倍为例
SeqListDataType* newA = (SeqListDataType*)realloc(p->a, sizeof(SeqListDataType)*newcapacity);
if (newA == NULL)//开辟失败
{
printf("newcapacity fail\n");
return;
}
p->a = newA;
p->capacity = newcapacity;
}
}
//尾插
void SeqListPushBack(SeqList* p, SeqListDataType x)
{
assert(p);
CheckCapacity(p);//当尾部空间不够时,就会自动扩容。
p->a[p->size] = x;
//p->size表示当前顺序表中有效的数据个数
//a[p->size]访问当前最后一个数据的下一个位置
p->size++;//注意此处要让有效数据的个数+1
}
//头插
void SeqListPushFront(SeqList* p, SeqListDataType x)
{
assert(p);
CheckCapacity(p);
int end = p->size;
for (; end > 0; end--)
{
p->a[end] = p->a[end - 1];//从后向前挪动数据
}
p->a[0] = x;
p->size++;//注意此处要让有效数据的个数+1
}
//任意位置插入
void SeqListInsert(SeqList* p, int pos, SeqListDataType x)
{
assert(p);
assert(pos >= 0 && pos <= p->size);
CheckCapacity(p);
int i = p->size;
for (; i > pos; i--)
p->a[i] = p->a[i - 1];//向后挪动数据
p->a[i] = x;
p->size++;
}
//打印数据表
void SeqListprintf(SeqList* p)
{
assert(p);
int i=0;
for(i=0;i<p->size;i++)
printf("%d\n",p->a[i]);
}
//头删
void SeqListPopFront(SeqList* p)
{
assert(p);
assert(p->size > 0);
int i = 0;
for (i = 0; i < p->size - 1; i++)//从前向后遍历挪动数据
p->a[i] = p->a[i + 1];
p->size--;
}
//尾删
void SeqListPopBack(SeqList* p)
{
assert(p);
assert(p->size > 0);
CheckCapacity(p);
p->size--;
}
//任意删除数据
void SeqListErase(SeqList* p, int pos)
{
assert(p);
assert(pos >= 0 && pos < p->size);
CheckCapacity(p);
int i = pos;
for (; i < p->size - 1; i++)
p->a[i] = p->a[i + 1];//向前挪动数据
p->size--;
}
//查找(第一个)值为x的数据的下标
int SeqListFind(SeqList* p, SeqListDataType x)
{
assert(p);
int i = 0;
for (i = 0; i < p->size; i++)
{
if (p->a[i] == x)
{
printf("1的位置的下标为%d\n",i);
}
// return i;
}
return -1;//找不到返回-1
}
//将pos位置的值修改为x
void SeqListModify(SeqList* p, int pos, SeqListDataType x)
{
assert(p);
assert(pos >= 0 && pos < p->size);
p->a[pos] = x;
}
int main()
{
SeqList sl;
int ret;
ret=SeqListInit(&sl);
if(1==ret)
// printf("顺序表创建成功\n");
SeqListPushBack(&sl,1);
SeqListPushBack(&sl,2);
SeqListPushBack(&sl,3);
SeqListPushBack(&sl,4);
// printf("尾插4321成功\n");
// SeqListprintf(&sl);
SeqListPushFront(&sl,5);
// printf("头插5成功\n");
// SeqListprintf(&sl);
SeqListInsert(&sl,2,99);
// printf("第三个位置插入99成功\n");
SeqListprintf(&sl);
SeqListPopFront(&sl);
printf("头删成功\n");
SeqListprintf(&sl);
SeqListPopBack(&sl);
printf("尾删成功\n");
SeqListprintf(&sl);
SeqListErase(&sl,2);
printf("删第三个数成功\n");
SeqListprintf(&sl);
printf("开始找1\n");
SeqListFind(&sl,1);
SeqListModify(&sl,1,2);
printf("把第二个数改成2\n");
SeqListprintf(&sl);
//SeqListDestroy(&sl);
// printf("销毁\n");
// SeqListprintf(&sl);
// printf("销毁成功");
}