线性表
线性表的存储结构有顺序存储结构(顺序表)和链式存储结构(链表)两种
几点关于线性表的概念:
1.一个数据元素可以由若干个数据项组成,在这种情况下,常把数据元素称为记录,含有大量记录的线性表又称文件。
2.线性表中的数据元素可以是多种多样的,但同一线性表中的元素必定具有相同特性,即属同一数据对象,相邻数据元素之间存在着需偶关系。
3.线性表中元素的的个数n(n>=0)定义为线性表的长度,n=0时称为空表。
顺序表:线性表的顺序表示指的是用一组连续的存储单元依次存储线性表的数据元素,通常用数组来描述数据结构中的顺序存储结构
下面我们来学习顺序表,顺序表是最常用且最简单的一种数据结构。
有以下特点:
1.简单,但不实用。
2.存在惟一的一个被称做“第一个”的数据元素。
3.存在惟一的一个被称为“最后一个”的数据元素。
4.除第一个以外,集合中的每个元素均只有一个前驱。
5.除最后一个以外,集合中的每个元素均只有一个后继。
一些文件类型及其作用的说明:
(1)头文件
关于项目中头文件的说明:
用户创建一个属于自己的头文件:
以下为以定长顺序表为例子,以.h结尾
头文件:存放结构定义和函数的声明.需要提供给用户,对外提供接口,也必须有一些函数或者是变量提供给外部文件进行调用。
(2)源文件
关于项目中源文件的说明:
源文件:存放函数的实现.可以提供给用户,也可以不提供
若提供则为开源,不提供则为不开源
1.定长顺序表的定义与实现:
(1)头文件
代码实现:
//头文件:存放结构定义和函数的声明。需要提供给用户
//定长的顺序表,简单,不实用
#pragma once//预防头文件被重复使用
#define SIZE 10
typedef struct SeqList
{
int elem[SIZE];//存放数据的数组
int length;//有效数据个数
}SeqList,*PSeqList; //PSeqList == SeqList *
//typedef SeqList *PSeqList;//*PSeqList == SeqList *
void InitSeqList(PSeqList ps);//初始化
static bool IsFull(PSeqList ps);//判满
bool Insert(PSeqList ps,int pos,int val);//在ps的pos下标插入val
int Search(PSeqList ps,int key);//在ps中查找第一个key,找到返回下标,失败返回-1
bool Delete(PSeqList ps,int key);//删除ps中第一个key
bool Deletepos(PSeqList ps,int pos);//删除ps中pos位置的值
int Getprio(PSeqList ps,int key);//获取ps中第一个key的前驱下标
int Getnext(PSeqList ps,int key);//获取ps中第一个key的后继下标
int GetLength(PSeqList ps);//获取长度(有效数据个数)
bool IsEmpty(PSeqList ps);//判空
void Clear(PSeqList ps);//清空数据
void Destroy(PSeqList ps);//销毁数据
void Show(PSeqList ps);//打印数据
(2)源文件:
代码实现:
//源文件:存放函数的实现。可以提供给用户,也可以不提供
//提供则为开源,不提供则为不开源
#include <stdio.h>
#include <assert.h>
#include "seqlist.h"
void InitSeqList(PSeqList ps)//初始化
{
assert(ps!=NULL);
if (ps == NULL)
{
return;
}
ps->length = 0;
}
static bool IsFull(PSeqList ps)
{
return ps->length == SIZE;
}
bool Insert(PSeqList ps,int pos,int val)//在ps的pos下标插入val
{
if (pos<0 ||pos>ps->length||IsFull(ps))
{
return false;
}
int i;
for (i=ps->length-1; i>=pos; i--)//数据后移
{
ps->elem[i+1] = ps->elem[i];
}
ps->elem[pos] = val;
ps->length++;
return true;
}
int Search(PSeqList ps,int key)//在ps中查找第一个key,找到返回下标,失败返回-1
{
for (int i=0; i<ps->length; i++)
{
if (ps->elem[i] == key)
{
return i;
}
}
return -1;
}
bool Delete(PSeqList ps,int key)//删除ps中第一个key
{
int index = Search(ps,key);
return Deletepos(ps,index);
}
bool Deletepos(PSeqList ps,int pos)//删除ps中pos位置的值
{
if (pos<0 ||pos>=ps->length)
{
return false;
}
for (int i=pos; i<ps->length-1; i++)
{
ps->elem[i] = ps->elem[i+1];
}
ps->length--;
return true;
}
int Getprio(PSeqList ps,int key)//获取ps中第一个key的前驱下标
{
return Search(ps,key) - 1;
}
int Getnext(PSeqList ps,int key)//获取ps中第一个key的后继下标
{
int index = Search(ps,key);
if (index<0 ||(index == ps->length-1))
{
return -1;
}
return index + 1;
}
int GetLength(PSeqList ps)//获取长度(有效数据个数)
{
return ps->length;
}
bool IsEmpty(PSeqList ps)//判空
{
return ps->length == 0;
}
void Clear(PSeqList ps)//清空数据
{
ps->length = 0;
}
void Destroy(PSeqList ps)//销毁数据
{
Clear(ps);
}
void Show(PSeqList ps)//打印数据
{
for (int i=0; i<ps->length; i++)
{
printf("%d \n",ps->elem[i]);
}
}
测试用例:
1.插入,初始化及打印数据
2.查找(查找5号数字的下标)
3.获取ps中第一个key的前驱下标(测试一下边界问题)
4.获取ps中第一个key的后继下标
5.删除ps中第一个key(删除key为7)
6.删除ps中pos位置的值(删除2号位置的值)
7.获取长度,因为删除了两个,所以有效长度为8
8.清空数据
9.销毁ps