整理一下王道数据结构上有关线性表之顺序表的知识和题目吧!
值得注意的地方
- 顺序表的特点是表中的逻辑顺序与其物理顺序相同
- 线性表中元素位序是从1开始的,而数组中元素的下标是从0开始的,所以如果题目说请删除第i个元素,直接上是删除 L->data[i-1]元素
- 顺序表的优点是存储密度大,不需要存放指针域。以及随机访问(也叫随机存取)。
- 顺序表的缺点是插入和删除需要移动大量的元素
顺序表的基本操作
定义顺序表结构体
注意:typedef的用法
typedef struct List{
int data[MAXSIZE]; //定义一个数组
int length; //顺序表的长度
}SqlList;
void InitList(SqlList *L); //初始化顺序表
void InitList(SqlList *L) //初始化顺序表
{
for(int i=0; i<MAXSIZE;i++){
L->data[i]=0;
L->length=0;
}
}
bool IsEmpty(SqlList *L); //判断顺序表是否为空
bool IsEmpty(SqlList *L)
{
if(L->length==0) return true;
else return false;
}
void ClearList(SqlList *L); //清空线性表
void ClearList(SqlList *L) //清空线性表
{
InitList(L);
}
GetElem(SqlList *L, int i, DataType *e); //获取第i个位置的数据
*注意: 这里的 e ,传入的是指针型变量,如果函数对传入的指针发生了改变,则会用到指针
int GetElem(SqlList *L, int i, DataType *e) //获取第i个位置的数据
{
if(i<1 || i>L->length || L->length ==0)
return -1; //异常处理
*e =L->data[i-1];
return 0;
}
int LocateElem(SqlList *L,DataType e); //查找与e相等的元素
int LocateElem(SqlList *L,DataType e) //查找与e相等的元素
{
if(L->length ==0) return 0; //表示为空表
for(int i=0 ;i<L->length; i++){
if(L->data[i]==e) return i+1; //返回位序
}
return -1; //没有找到
}
bool ListInsert(SqlList *L ,int i, DataType e);//在第i个位置插入元素
注意:插入第i个,即是在数组下标i-1的地方插入,然后将下标为i-1和后面的元素全部往后挪
bool ListInsert(SqlList *L ,int i, DataType e)//在第i个位置插入元素
{
if(i<1 || i>L->length+1 || L->length == MAXSIZE)
return false; //异常处理
for(int k=L->length;k>=i;k--){
L->data[k]=L->data[k-1];
}
L->data[i-1]=e;
L->length++;
return true;
}
bool ListDelete(SqlList *L,int i ,DataType *e);//删除在第i个位置的元素,e获取删除元素
注意:从i开始,然后对前一个进行处理,即前移
bool ListDelete(SqlList *L,int i ,DataType *e)//删除在第i个位置的元素,e获取删除元素
{
if (i<1 || i>L->length) return false;
*e = L->data[i-1];
for (int k=i;k<L->length;k++){
L->data[k-1]=L->data[k];
}
L->length--;
return true;
}
int Length(SqlList *L); //获取线性表的长度
int Length(SqlList *L) //获取线性表的长度
{
return L->length;
}
练习题
(1)从顺序表中删除具有最小值的元素(假设唯一),并由函数返回被删元素的的值,空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出执行
注意:好奇怪为啥我粘贴不了代码。。。 一定学会这种写法,大一的时候寻找数组的最小值,我是令一个数等于无穷大,然后去进行比较。。好傻,直接让指针参数等于数组第一个值就可以了。 还有就是 一定要记得是 == 不是=
(2)设计一个高效的算法,将顺序表L的所有元素逆置,要求时间复杂度为O(n),空间复杂度为O(l)
void ListReverse(SqlList *L) //逆置顺序表,就前部分元素和后半部分元素交换,
{
for(int i=0;i<(L->length)/2;i++){
int k = L->data[i]; //辅助变量,保留交换前的值
int endPos=(L->length)-1-i;
L->data[i]=L->data[endPos]; //交换
L->data[endPos]=k;
}
}
全部代码未完待续
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 50
typedef int DataType;
typedef struct List{
int data[MAXSIZE];
int length;
}SqlList;
void InitList(SqlList *L); //初始化顺序表
bool IsEmpty(SqlList *L); //判断顺序表是否为空
void ClearList(SqlList *L); //清空线性表
int GetElem(SqlList *L, int i, DataType *e); //获取第i个位置的数据
int LocateElem(SqlList *L,DataType e); //查找与e相等的元素
bool ListInsert(SqlList *L ,int i, DataType e);//在第i个位置插入元素
bool ListDelete(SqlList *L,int i ,DataType *e);//删除在第i个位置的元素,e获取删除元素
int Length(SqlList *L); //获取线性表的长度
void PrintList(SqlList *L); //遍历顺序表,打印测试结果
bool DeleteMin(SqlList *L, DataType *e); //删除最小值,并返回被删元素,被删位置由最后一个元素代替
void ListReverse(SqlList *L); //将顺序表中所有元素逆置,要求时间复杂度为n,空间复杂度为1
int main()
{
int e;
SqlList *pl= (SqlList*)malloc(sizeof(SqlList));
InitList(pl);
ListInsert(pl,1,1);
ListInsert(pl,2,2);
ListInsert(pl,3,3);
ListInsert(pl,4,4);
ListInsert(pl,5,5);
//ListInsert(pl,6,6);
PrintList(pl);
//ListDelete(pl,2,&e);
//ListDelete(pl,4,&e);
// DeleteMin(pl,&e);
ListReverse(pl);
PrintList(pl);
return 0;
}
void InitList(SqlList *L) //初始化顺序表
{
for(int i=0; i<MAXSIZE;i++){
L->data[i]=0;
L->length=0;
}
}
bool IsEmpty(SqlList *L) //判断顺序表是否为空
{
if(L->length=0){
return true;
}
else return false;
}
void ClearList(SqlList *L) //清空线性表
{
InitList(L);
}
int GetElem(SqlList *L, int i, DataType *e) //获取第i个位置的数据
{
if(i<1 || i>L->length || L->length ==0)
return -1; //异常处理
*e =L->data[i-1];
return 0;
}
int LocateElem(SqlList *L,DataType e) //查找与e相等的元素
{
if(L->length ==0) return 0; //表示为空表
for(int i=0 ;i<L->length; i++){
if(L->data[i]==e) return i+1; //返回位序
}
return -1; //没有找到
}
bool ListInsert(SqlList *L ,int i, DataType e)//在第i个位置插入元素
{
if(i<1 || i>L->length+1 || L->length == MAXSIZE)
return false; //异常处理
for(int k=L->length;k>=i;k--){
L->data[k]=L->data[k-1];
}
L->data[i-1]=e;
L->length++;
return true;
}
bool ListDelete(SqlList *L,int i ,DataType *e)//删除在第i个位置的元素,e获取删除元素
{
if (i<1 || i>L->length) return false;
*e = L->data[i-1];
for (int k=i;k<L->length;k++){
L->data[k-1]=L->data[k];
}
L->length--;
return true;
}
int Length(SqlList *L) //获取线性表的长度
{
return L->length;
}
bool DeleteMin(SqlList *L, DataType *e)
{
*e=L->data[0];
int MinLocate=0;
if(L->length==0) return false; //异常处理
for(int i=1;i<L->length;i++){
if(L->data[i]<*e){
*e = L->data[i];
MinLocate=i;
}
}
L->data[MinLocate]=L->data[(L->length)-1];
L->length--;
return true;
}
void ListReverse(SqlList *L) //逆置顺序表,就前部分元素和后半部分元素交换,
{
for(int i=0;i<(L->length)/2;i++){
int k = L->data[i]; //辅助变量,保留交换前的值
int endPos=(L->length)-1-i;
L->data[i]=L->data[endPos]; //交换
L->data[endPos]=k;
}
}
void PrintList(SqlList *L)//遍历顺序表,打印测试结果
{
if(L->length == 0){
printf("顺序表为空\n");
}
printf("============遍历顺序表如下=============\n");
for(int i = 0; i < L->length; i++)
{
printf("\tdata[%d] = %d\n", i, L->data[i]);
}
printf("============共计%d个元素=============\n", L->length);
}