顺序表的特点
优点:
1.实现简单
2.支持随机(下标)访问
缺点:
1.插入数据时间复杂度O(n),但是尾插O(1)
2.删除数据O(n),但是尾删O(1)
该顺序表由dsqlist.h + dsqlist.cpp + main.cpp 组成
dsqlist.h文件 //头文件,存放数据结构和函数的声明
#pragma once//预防头文件被重复引用,每个头文件必须在最上面写这一句
typedef struct DsqList
{
int* elem;//保存动态内存的地址
int length;//有效数据个数
int listsize;//总单元格数量
}DsqList, * PDsqList;
#define INITSIZE 10
//初始化
//void InitDsqlist(DsqList *ps);
void InitDsqlist(PDsqList ps);//PDsqList == DsqList *
//销毁
void Destroy(PDsqList ps);
//清空数据
void Clear(PDsqList ps);
//查找val,找到返回下标,失败返回-1
int Search(const PDsqList ps, int val);
//判断是否为空
bool IsEmpty(const PDsqList ps);
//获取长度,有效数据个数
int GetLength(const PDsqList ps);
//获取i下标的值
//int GetElem(const PDsqList ps, int i);
bool GetElem(const PDsqList ps, int i, int* rtval);
//获取i下标的前驱
//int GetPrio(const PDsqList ps, int i);
bool GetPrio(const PDsqList ps, int i, int* rtval);
//获取i下标的后继
//int GetNext(const PDsqList ps, int i);
bool GetNext(const PDsqList ps, int i, int* rtval);
//在i下标插入数据val
bool Insert(PDsqList ps, int i, int val);
//删除i下标的值
bool DelPos(PDsqList ps, int i, int* rtval);
//删除val
bool DelVal(PDsqList ps, int val);
//输出
void Show(const PDsqList ps);
dsqlist.cpp文件
//源文件,存放具体实现
//不定长顺序表,可以扩容realloc
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include<malloc.h>
#include "dsqlist.h"//引用本项目的头文件用""
//初始化
void InitDsqlist(PDsqList ps)//PDsqList == DsqList *
{
assert(ps != NULL);
if (ps == NULL)
return;
ps->elem = (int*)malloc(INITSIZE * sizeof(int));
assert(ps->elem != NULL);
ps->length = 0;
ps->listsize = INITSIZE;
}
//销毁
void Destroy(PDsqList ps)
{
free(ps->elem);
ps->elem = NULL;//不写的话,就是野指针
ps->length = 0;
ps->listsize = 0;
//ps = NULL;//没有意义,传指针,解引用
}
//清空数据
void Clear(PDsqList ps)
{
ps->length = 0;
}
//判断是否为空
bool IsEmpty(const PDsqList ps)
{
return ps->length == 0;
}
//查找val,找到返回下标,失败返回-1
int Search(const PDsqList ps, int val)
{
//从头到尾遍历
for (int i = 0; i < ps->length; i++)
{
if (ps->elem[i] == val)
return i;
}
return -1;
}
//获取长度,有效数据个数
int GetLength(const PDsqList ps)
{
return ps->length;
}
//获取i下标的值
//int GetElem(const PDsqList ps, int i)
bool GetElem(const PDsqList ps, int i,int *rtval)//注意函数设计
{
if (i < 0 || i >= ps->length)
return false;
*rtval = ps->elem[i];
return true;
}
//获取i下标的前驱
bool GetPrio(const PDsqList ps, int i, int* rtval)
{
if (i <= 0 || i > ps->length)
return false;
*rtval = ps->elem[i-1];
return true;
}
//获取i下标的后继
bool GetNext(const PDsqList ps, int i, int* rtval)
{
if (i < 0 || i >= ps->length-1)
return false;
*rtval = ps->elem[i + 1];
return true;
}
//判满,内部使用
static bool IsFull(const PDsqList ps)
{
return ps->length == ps->listsize;
}
//扩容,将容量扩大到原来的2倍
static void Inc(PDsqList ps)
{
ps->elem = (int*)realloc(ps->elem, ps->listsize * 2 * sizeof(int));
assert(ps->elem != NULL);
//ps->length;不变
ps->listsize *= 2;
}
//在i下标插入数据val
bool Insert(PDsqList ps, int i, int val)
{
if (i<0 || i>ps->length)
return false;
if (IsFull(ps))
Inc(ps);
//移动后面的数据
for (int j = ps->length - 1; j >= i; j--)
{
ps->elem[j + 1] = ps->elem[j];
}
//插入新数据
ps->elem[i] = val;
//有效数据个数+1
++ps->length;
return true;
}
//删除i下标的值,rtval将删除的值带出
bool DelPos(PDsqList ps, int i, int* rtval)
{
//判断i是否合法
if (i < 0 || i >= ps->length)
return false;
//后面的数据往前移动
if(rtval!=NULL)//**********判空
rtval = &ps->elem[i];
for (int p = i; p + 1 < ps->length; p++)//p+1*******p<length的话会越界
{
ps->elem[p] = ps->elem[p + 1];
}
//有效数据个数-1
ps->length -= 1;
return true;
}
//删除val
bool DelVal(PDsqList ps, int val)
{
int i = Search(ps, val);
if (i < 0)
return false;
return DelPos(ps,i, NULL);
}
//输出
void Show(const PDsqList ps)
{
for (int i = 0; i < ps->length; i++)
{
printf("%d ", ps->elem[i]);
}
printf("\n\n");
}
main.cpp文件 //测试
#include "dsqlist.h"
int main()
{
DsqList ds;
int* r = {};
InitDsqlist(&ds);
for (int i = 0; i < 20; i++)
{
Insert(&ds, i, i + 1);
}
printf("最初\n");
Show(&ds);
printf("有效数据数:%d\n", GetLength(&ds));
printf("在5下标插入100\n");
Insert(&ds, 5, 100);
Show(&ds);
printf("有效数据数:%d\n", GetLength(&ds));
printf("删除100\n");
DelVal(&ds, 100);
Show(&ds);
printf("删除5下标的值\n");
DelPos(&ds,5, r);
Show(&ds);
printf("有效数据数:%d\n", GetLength(&ds));
Clear(&ds);
Show(&ds);
Destroy(&ds);
Show(&ds);
return 0;
}