1.顺序表(链式存储)
顺序表的基本操作:
//可扩容的链式存储顺序表结构体设计
typedef int ELEM_TYPE;
#define INIT_SIZE 10 //初始化时malloc的开辟空间大小
typedef struct SeqList
{
ELEM_TYPE* elem; //接收malloc返回的数组首地址
int length; //存放有效值个数
int listsize; //存放数组的总大小
}SeqList, * PSeqList;
1.初始化
void Init_SeqList(struct SeqList* head)
{
//0.安全性处理
//若传入的head指针为NULL,后续对head->data或其他行为的访问会导致程序崩溃
assert(NULL != head) ;
if(NULL == head) exit(EXIT_FAILURE);
//1.对elem来malloc,再堆区malloc连续空间
head->elem = (ELEM_TYPE*)malloc(INIT_SIZE*sizeof(ELEM_TYPE));
//判断malloc是否成功
if(NULL == head->elem) exit(EXIT_FAILURE);
//2.对length和listsize初始化
head->length = 0 ;
head->listsize = INIT_SIZE ;
}
2.插入数据
//头插法
bool Insert_SeqList_head(PSeqList head,ELEM_TYPE val)
{
//0.安全性处理
assert(NULL != head) ;
if(NULL == head) exit(EXIT_FAILURE);
//0.判满 若满则扩容
if(Is_Full(head)) Increase(head);
//1.集体向后移动
for(int i = head->length - 1;i >= 0 ;i++)
{
//由第i位置的元素覆盖第i+1位置的元素
head->elem[i+1] = head->elem[i];
}
//2.插入0号下标
head->elem[0] = val;
head->length++;//长度加一
return true;
}
//尾插法
bool Insert_SeqList_tail(PSeqList head,ELEM_TYPE val)
{
//0.安全性处理
assert(NULL != head);
if(NULL == head) exit(EXIT_FAILURE);
//1.判满 若满则扩容
if(Is_Full(head)) Increase(head) ;
//1.插入元素 尾插不需要挪动元素
//length指向的位置是下一次要插入的位置,所以不需要-1
head->elem[head->length] = val;
head->length++;
return true;
}
//按位置插入
bool Insert_SeqList_pos(PSeqList head,ELEM_TYPE val,int pos)
{
//0.安全性处理
assert(NULL != NULL);
//判断pos位置的合法性,避免pos指向非法位置
assert(pos >= 0 && pos <=head->length);
if(NULL == head) exit(EXIT_FAILURE);
//1.判满
if(Is_Full(head)) Increase(head) ;
//2.将插入位置之后的元素同意向后挪动,空出待插入位置
//当i==pos时的元素也要挪动,因为val要插在pos位置
for(int i = head->length - 1;i >= pos ; i++)
{
head->elem[i+1] = head->elem[i];
}
//3.插入元素,length++
head->elem[pos] = val;
head->length++;
return true;
}
3.删除数据
在线性表中,删除元素即是覆盖元素
//头删
bool Del_SeqList_head(SeqList* head)
{
//0.安全性处理
assert(NULL != head);
if(NULL == head) exit(EXIT_FAILURE);
//1.判空
if(Is_Empty(head)) return false;
//2.头删 即将第一个位置的元素覆盖
for(int i = 1;i < head->length ; i++)
{
head->elem[i-1] = head->elem[i];
}
head->length--;
return true;
}
//尾删
bool Del_SeqList_head(SeqList* head)
{
//0.安全性处理
assert(NULL != head);
if(NULL == head) exit(EXIT_FAILURE);
//1.判空
if(Is_Empty(head)) return false;
head->length--;//此时length指向的位置即便有值,也是无效值,下次插入即覆盖
return true;
}
//按位置删
bool Del_SeqList_pos(SeqList* h, int pos)
{
//0.安全性处理
assert(NULL != head);
if(NULL == head) exit(EXIT_FAILURE);
//1.判空
if(Is_Empty(head)) return false;
//2.找到要删除元素的位置,然后将其之后的元素全部向前挪动,即覆盖掉了要删除的元素
for(itn i = pos + 1;i < head->length ; i++)
{
head->elem[i+1] = head->elem[i];
}
head->length--;
return true;
}
//按值删(只删除该值第一次出现的位置)
bool Del_SeqList_val(SeqList* head, ELEM_TYPE val)
{
//0.安全性处理
assert(NULL != head);
if(NULL == head) exit(EXIT_FAILURE);
//1.判空
if(Is_Empty(head)) return false;
//2.通过调用查找函数,查找val在顺序表的位置
int index = Search_SeqList(head, val);
if(index == -1) return false;//没找到值,该值不存在
else Del_SeqList_pos(head,index);//有了位置后,就可以调用按位置删函数
return true;
}
//按位置删(删除所有val值)
bool Del_SeqList_AllVal(SeqList* head, ELEM_TYPE val)
{
//0.安全性处理
assert(NULL != head);
//1.判空
if(Is_Empty(head)) return false;
//双指针法
int slow = 0;
for(int fast = 0 ; fast < head->length ; fast++)
{
if(head->elem[fast] != val)
{
//保留非目标val值
head->elem[slow++] = head->elem[fast];
}
}
//此时slow值即length新的长度
head->length = slow;
return true;
}
4.查找数据
//4.查找数据是否已经存在(存在则返回下标,反之返回-1)
int Search_SeqList(PSeqList head, ELEM_TYPE val)
{
for (int i = 0; i < head->length; i++)
{
if (head->elem[i] == val) return i;
}
return -1;
}
5.判空与判满
//判空
bool Is_Empty(PSeqList head)
{
return head->length == 0;
}
//判满
bool Is_Full(PSeqList head)
{
return head->length == head->length;
}
6.扩容函数
//扩容函数 默认两倍扩容
void Increase(PSeqList psl)
{
ELEM_TYPE* tmp = (ELEM_TYPE*)realloc(psl->elem, psl->listsize * sizeof(ELEM_TYPE) * 2);
//扩容是否成功
if (tmp != nullptr)
{
psl->elem = tmp;
}
}
7.清空与销毁
//清空 无需释放malloc购买的内存
void Clear(PSeqList head)
{
head->length = 0;
}
//销毁 需释放malloc购买的内存
void Destory(PSeqList head)
{
free(head->elem);
head->length = head->listsize = 0;
}