先写头文件:Dsqlist.h
#pragma once
typedef int ELEM_TYPE;
#define INIT_SIZE 10
//不定长顺序表的结构体设计:
typedef struct Dsqlist
{
ELEM_TYPE *elem;//指针,用来接收malloc返回值
int length;//当前有效值个数(当前有多少个格子被占用)
int list_size;//当前总空间个数(当前一共有多少个格子)
}Dsqlist, *PDsqlist;
//不定长顺序表可以实现的操作函数:
//增删改查
//初始化
void Init_Dsqlist(struct Dsqlist * p);//void Init_sqlist(PDsqlist p);
//按位置插入
bool Insert_pos(PDsqlist p, int pos, int val);
//按位置删除
bool Del_pos(PDsqlist p, int pos);
//按值删除
bool Del_val(PDsqlist p, int val);
//获取其有效长度
int Get_length(PDsqlist p);
//扩容 以2倍扩容
void Inc(PDsqlist p);
//获取值所在下标(如果数据重复,则返回val第一次出现的位置)
int Search(PDsqlist p, int val);
//判空
bool IsEmpty(PDsqlist p);
//判满
bool IsFull(PDsqlist p);
//清空
void Clear(PDsqlist p);
//销毁
void Destroy(PDsqlist p);
//打印
void Show(PDsqlist p);
Dsqlist.cpp
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "Dsqlist.h"
/*
顺序表的特点:(插入删除操作较少,随机访问数组中值这个操作较多)
1.逻辑简单,实现简单
2.插入操作时间复杂度O(n),因为需要挪动数据 但是尾插不需要挪动数据(尾插时间复杂度O(1))
3.删除操作时间复杂度O(n),因为需要向前覆盖数据 但是尾删除不需要挪动数据(尾删时间复杂度O(1))
4.随机访问时间复杂O(1),因为顺序表可以通过下标直接访问数组中的元素值
顺序表:数据和数据之间,逻辑相邻,物理也相邻
*/
//不定长顺序表可以实现的操作函数:
//增删改查
//初始化
void Init_Dsqlist(struct Dsqlist * p)//void Init_sqlist(PDsqlist p);
{
assert(p != NULL);
if(p == NULL)
return;
p->elem = (ELEM_TYPE*)malloc(INIT_SIZE * sizeof(ELEM_TYPE));
assert(p->elem != NULL);
if(p->elem == NULL)
return;
p->length = 0;
p->list_size = INIT_SIZE;
}
//按位置插入
bool Insert_pos(PDsqlist p, int pos, int val)
{
//assert p
//assert pos
//判满 扩容
if(IsFull(p))
{
Inc(p);
}
//此时,肯定p不为NULL, 并且pos位置合法, 并且还用空闲位置让我插入
//4.首先挪动数据,让待插入位置空出来,再将值val放进去即可
//(插入,挪动数据,从后先前挪)
for(int i=p->length-1; i>=pos; i--)//i一开始指向最后一个元素下标,最后挪动的数据下标是pos
{
p->elem[i+1] = p->elem[i];
}
//此时,for循环执行结束 标识着挪动数据完成 现在只需要将插入的值val赋值进去
p->elem[pos] = val;
//别忘了 插入操作最后还有一个有效值个数length++
p->length++;
return true;
}
//按位置删除
bool Del_pos(PDsqlist p, int pos)
{
//1.判空 p!=NULL 判断定长顺序表是否存在
assert(p!=NULL);
if(p == NULL)
return false;
//2.判断删除位置 是否合法
assert(pos >=0 && pos<p->length);// 删除的时候pos==p->length不合法
if(pos<0 || pos>=p->length)
return false;
//3.判空操作
if(IsEmpty(p))
return false;
//4.将待删除位置后面的有效值,一次向前挪动一位,将删除位置覆盖掉即可
//(删除,向前覆盖数据,离待删除位置最近的元素先挪动)
for(int i=pos+1; i<=p->length-1; i++)
{
p->elem[i-1] = p->elem[i];
}
//此时,for循环执行结束 标识着数据向前覆盖完成 现在只需要将p->length--
p->length--;
return true;
}
//按值删除
bool Del_val(PDsqlist p, int val)
{
//assert p
//判断val这个值 存不存在
int index = Search(p, val);
if(index == -1)
{
return false;
}
return Del_pos(p, index);
}
//获取其有效长度
int Get_length(PDsqlist p)
{
//assert
return p->length;
}
//扩容 以2倍扩容
void Inc(PDsqlist p)
{
//assert p 这个断言需不需要? 不需要
/*ELEM_TYPE* tmp = (ELEM_TYPE*)realloc(p->elem, p->list_size*sizeof(ELEM_TYPE) * 2);
assert(tmp != NULL);
if(tmp == NULL)
{
printf("realloc error\n");
return;
}
else
{
p->elem = tmp;
}*/
p->elem = (ELEM_TYPE*)realloc(p->elem, p->list_size*sizeof(ELEM_TYPE) * 2);
assert(p->elem != NULL);
if(p->elem == NULL)
{
printf("realloc error\n");
return;
}
//p->length;//扩容之后 有效值个数不变
p->list_size *= 2;//扩容之后 总格子个数需要*2
}
//获取值所在下标(如果数据重复,则返回val第一次出现的位置)
int Search(PDsqlist p, int val)
{
//assert
for(int i=0; i<p->length; i++)
{
if(p->elem[i] == val)
{
return i;
}
}
return -1;
}
//判空
bool IsEmpty(PDsqlist p)
{
//assert
return p->length == 0;
}
//判满
bool IsFull(PDsqlist p)
{
//assert
return p->length == p->list_size;
}
//清空
void Clear(PDsqlist p)
{
//assert
p->length = 0;
}
//销毁 主要处理内存泄露
void Destroy(PDsqlist p)
{
//assert
free(p->elem);
}
//打印
void Show(PDsqlist p)
{
//assert
for(int i=0; i<p->length; i++)
{
printf("%d ", p->elem[i]);
}
printf("\n");
}
主函数:
#include <stdio.h>
#include "assert.h"
#include <stdlib.h>
#include <vld.h>
//#include "sqlist.h"
#include "Dsqlist.h"
//不定长顺序表测试用例
int main()
{
struct Dsqlist head;
Init_Dsqlist(&head);
printf("maxsize: %d\n", head.list_size);
printf("length = %d\n", Get_length(&head));
for(int i=0; i<10; i++)
{
Insert_pos(&head, i, i+1);
}
Insert_pos(&head, 0, 100);
Insert_pos(&head, head.length, 200);
printf("maxsize: %d\n", head.list_size);
printf("length = %d\n", Get_length(&head));
Show(&head);
Del_pos(&head, 3);
Show(&head);
Del_val(&head, 9);
Show(&head);
printf("%d\n", Search(&head, 5));
printf("%d\n", Search(&head, 300));
Clear(&head);
printf("length = %d\n", Get_length(&head));
Show(&head);
Destroy(&head);
return 0;
}