线性表
顺序表
每种结构都有它存在意义
线性表的顺序存储实现指的是用一组连续的存储单元存储线性表的数据元素。
概念
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性表,一般情况下采用数组存储。在数组上完成数据的增查改删。
逻辑结构:线性结构
物理结构:顺序存储结构
线性表的特点:一对一,每个节点最多一个前驱和一个后继,首尾节点特殊:首节点无前驱,尾节点无后继
顺序表前言
操作:
1.创建一个空的顺序表
2.向顺序表的指定位置插入数据
3.删除顺序表指定位置的数据
命名法则:
大驼峰:InsertInto
小驼峰: insertinto
加下划线: insert_into
见名知意;
练习1:
int buf[32] = {1,996,520,4,5,6,7,8}; // 8 个最后一个下标 7 n-1
1 996 520 100 4 5 6 7 8
(1)向数组的第几个位置插入数据
int *p //保存的数组的首地址
int n //n代表的是数组中有效的元素个数(非数组的长度size 100)
int post; //位置代表的是第几个位置(数组元素下标),数组元素下标 位置的编号从0开始 position
int data; //插入到数组中的数据
int InsertInto(int *p,int n,int post,int data);
(2)遍历数组中的有效元素
int *p //保存的数组的首地址
int n //n代表的是数组中有效的元素个数(非数组的长度size 100)
void Show(int *p,int n)
int main()
{
int buf[32] = {1,996,520,4,5,6,7,8}; // 8 个最后一个下标 7 n-1
InsertInto(buf,8,3, 100); // 1 996 520 100 4 5 6 7 8
Show(buf,9);//1 996 520 100 4 5 6 7 8
return 0;
}
#include <stdio.h>
int InsertInto(int *p,int n,int post,int data);
void Show(int *p,int n);
int main(int argc, const char *argv[])
{
int buf[32] = {1,996,520,4,5,6,7,8};
InsertInto(buf,8,3,100);
Show(buf,9);
return 0;
}
int InsertInto(int *p,int n,int post,int data)
{
int i;
if(post < 0 || post > n)
{
printf("InsertInto error\n");
return -1;
}
for(i = n -1; i >= post; i--)
{
p[i+1] = p[i];
}
p[post] = data;
return 0;
}
void Show(int *p,int n)
{
int i;
for(i = 0; i < n; i++)
{
printf("%d ",p[i]);
}
putchar(10);
}
1 996 520 100 4 5 6 7 8
练习2:
修改成last版本后
前提条件:
全局变量:last :始终表示最后一个有效元素的下标
#include <stdio.h>
int InsertInto(int *p,int post,int data);
void DeletPost(int *p,int post);
void Show(int *p);
//始终表示数组中最后一个有效元素的下标(全局变量)
int last = 7;
int main(int argc, const char *argv[])
{
int buf[32] = {1,996,520,4,5,6,7,8};
InsertInto(buf,3,100);
Show(buf);
DeletPost(buf,3);
Show(buf);
return 0;
}
int InsertInto(int *p,int post,int data)
{
int i;
if(post < 0 || post > last+1)
{
printf("InsertInto error\n");
return -1;
}
for(i = last; i >= post; i--)
{
p[i+1] = p[i];
}
p[post] = data;
last++;
return 0;
}
void DeletPost(int *p,int post)
{
if(post < 0 || post > last)
{
printf("DeletPost error\n");
}
int i;
#if 0
for(i = post; i < last; i++)
{
p[i] = p[i+1];
//p[last] = p[last+1]
}
#endif
#if 1
for(i = post +1; i <= last; i++)
{
p[i-1] = p[i];
//p[last -1] = p[last]
}
#endif
last--;
}
void Show(int *p)
{
int i;
for(i = 0; i <= last; i++)
{
printf("%d ",p[i]);
}
putchar(10);
}
1 996 520 100 4 5 6 7 8
1 996 520 4 5 6 7 8
顺序表:Sequeue
List
顺序表操作函数
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#include <stdio.h>
#include <stdlib.h>
// 1. 定义操作顺序表的结构体
#define N 5 // 定长数组的大小
typedef int DataType; // 顺序表数据类型
typedef struct seq
{
DataType data[N];
int last;//last始终代表数组中最后一个有效元素的下标
}SL;
//1.创建一个空的顺序表
SL *CreateEpSeqlist();//返回的是申请空间的首地址
//2.向顺序表的指定位置插入数据
int InsertIntoSeqlist(SL *p, int post,DataType data);//post第几个位置,data插入的数据
//3.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(SL *p);
//4.判断顺序表是否为满,满返回1 未满返回0
int IsFullSeqlist(SL *p);
//5.判断顺序表是否为空
int IsEpSeqlist(SL *p);
//6.删除顺序表中指定位置的数据post删除位置
int DeletePostSeqlist(SL *p, int post);
//7.清空顺序表
void ClearSeqList(SL *p)
//8.修改指定位置的数据
int ChangePostSeqList(SL *p,int post,DataType data);//post被修改的位置,data修改成的数据
//9.查找指定数据出现的位置
int SearchDataSeqList(SL *p,DataType data);//data代表被查找的数据
#endif
为了后续方便需改表中数据的数据类型,我们可以typedef
一个新的数据类型叫做DataType
顺序表数据类型。
为了让在定义结构体变量或结构体指针时使用更方便,我们同样可以将struct SeqList
重定义为SL
。
此时SL == struct SeqList
- 创建
seqlist.h
函数声明头文件 - 创建
seqlist.c
函数实现源文件 - 创建
main.c
用来测试顺序表接口
定义操作顺序表的结构体
// 1. 定义操作顺序表的结构体
#define N 5 // 定长数组的大小
typedef int DataType; // 顺序表数据类型
typedef struct seq
{
DataType data[N];
int last;//last始终代表数组中最后一个有效元素的下标
}SL;
all:
gcc main.c seqlist.c -o seqlist
创建空顺序表
SL *CreateEpList()
{
SL *p = (SL*)malloc(sizeof(SL));
if(NULL == p)//NULL == p; NULL = p;p = NULL;
{
printf("malloc error\n");
return NULL;
}
//int last = -1;
p->last = -1;
return p;
}
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#include <stdlib.h>
#include <stdio.h>
#define N 5
typedef int datatype;
typedef struct seq
{
datatype data[N];
int last;
//last始终代表数组中最后一个有效元素的下标
}SL;
//创建一个表(表首地址返回)
SL *CreateEpList();
//2.向顺序表的指定位置插入数据
#endif
#include "seqlist.h"
int main(int argc, const char *argv[])
{
SL *p = CreateEpList();
return 0;
}
插入
post
不能小于0
post
不能大于last + 1
- 表不能溢出
last+1
不能大于N
//2.向顺序表的指定位置插入数据
int InsertIntoSeqlist(SL *p, int post,datatype data)//post第几个位置,data插入的数据
{
if(IsFullSeqlist(p) || post < 0 || post > p->last+1)
{
printf("InsertIntoSeqlist error\n");
return -1;
}
int i;
for(i = p->last; i >= post; i--)
{
p->data[i+1] = p->data[i];
}
p->data[post] = data;
p->last++;
return 0;
}
//3.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(SL *p)
{
int i;
for(i = 0; i <= p->last; i++)
{
printf("%d ",p->data[i]);
}
putchar(10);
}
//4.判断顺序表是否为满,满返回1 未满返回0
int IsFullSeqlist(SL *p)
{
return p->last == N -1;
//真(1) 假(0)
}
99 88 77
99 66 88 77
打印
//3.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(SL *p)
{
int i;
for(i = 0; i <= p->last; i++)
{
printf("%d ",p->data[i]);
}
putchar(10);
}
查找
查找指定数据出现的位置下标
思路:自变量为顺序表下标[0, last]
,for
循环进行遍历访问,如果相等返回下标。
缺陷:无法返回重复出现数据的位置下标
解决办法:不做要求。
//9.查找指定数据出现的位置
int SearchDataSeqList(SL *p,datatype data)//data代表被查找的数据
{
if(IsEpSeqlist(p))
{
printf("SearchDataSeqList error\n");
return -1;
}
int i;
for(i = 0; i <= p->last; i++)
{
if(p->data[i] == data)
return i;
}
return -1;
}
修改
修改顺序表指定位置的数据。
参数:
- 结构体指针
P
- 修改的位置
post
- 期望的数据
data
步骤:
- 容错判断
[0, last]
- 直接修改
P->data[post] = data
//8.修改指定位置的数据
int ChangePostSeqList(SL *p,int post,datatype data)//post被修改的位置,data修改成的数据
{
if(IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("ChangePostSeqList error\n");
return -1;
}
p->data[post] = data;
return 1;
}
删除
删除顺序表中指定位置的数据
参数:
- 结构体指针
P
- 删除的位置
post
步骤:
- 容错判断 同修改接口
[0, last]
post+1~last
向前移动
5.判断顺序表是否为空
int IsEpSeqlist(SL *p)
{
return p->last == -1;
}
//6.删除顺序表中指定位置的数据post删除位置
int DeletePostSeqlist(SL *p, int post)
{
if(IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("DeletePostSeqlist error\n");
return -1;
}
int i;
#if 0
for(i = post; i < p->last; i++)
{
p->data[i] = p->data[i+1];
}
#endif
#if 1
for(i = post+1; i <= p->last; i++)
{
p->data[i-1] = p->data[i];
}
#endif
p->last--;
return 0;
}
#include "seqlist.h"
int main(int argc, const char *argv[])
{
SL *p = CreateEpList();
InsertIntoSeqlist(p,0,99);
InsertIntoSeqlist(p,1,88);
InsertIntoSeqlist(p,2,77);
ShowSeqlist(p);
InsertIntoSeqlist(p,1,66);
ShowSeqlist(p);
DeletePostSeqlist(p,1);
ShowSeqlist(p);
return 0;
}
99 88 77
99 66 88 77
99 88 77