线性表
线性表是最基本、最简单、也是最常用的一种数据结构,可以存储逻辑关系为线性的数据。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
包含:顺序表(数组)、链表(单向链表、单向循环链表、双向链表、双向循环链表)、栈(顺序栈、链式栈)、队列(循环队列、链式队列)逻辑结构:线性结构
存储结构:顺序存储(数组)或链式存储(通过指针)
特点:一对一,每个节点最多一个前驱和一个后继,首节点无前驱,尾节点无后继。
顺序表
顺序表存储数据的具体实现方案是:将数据全部存储到一整块内存空间中,数据元素之间按照次序挨个存放。
举个简单的例子,将 {1,2,3,4,5} 这些数据使用顺序表存储,数据最终的存储状态如下图所示:
1.顺序表的特性
逻辑结构:线性结构
存储结构:顺序存储结构
特点:内存连续
操作:增删改查
2. 操作数组
例题:
int a[100]={1,2,3,4,5,6,7,8};
函数命名规则:
下划线法:create_empty_seqlist
小驼峰法:createEmptySeqList
大驼峰法:CreateEmptySeqList
数组的增删操作:
#include <stdio.h>
/*
功能:向数组的第几个位置插数据
函数:void insetIntoA(int *p,int n, int post, int data);
参数:
int *p: 保存数组首地址
int n: 有效数据元素的个数
int post: 插入元素下标
int data: 数据
*/
void insertIntoA(int *p, int n, int post, int data) //insert插入 //p=a, n=8,post=4, data=100
{
int i;
//1.从最后一个元素到插入位置的元素向后移动一个单位
for (i = n - 1; i >= post; i--) //i=7 , 7>=4; i=6, 6>=4; i=5, 5>=4; i=4, 4>=4; i=3 3>=4(不满足退出循环)
p[i + 1] = p[i]; //p[8]=p[7]; p[7]=[6]; p[6]=p[5]; p[5]=p[4]
//2.插入新元素data到指定位置
p[post] = data; //p[4] = 100
}
/* (2)遍历数组中的有效元素
功能:遍历数组中的有效元素
函数:void showA(int *p,int n);
参数:
int *p:保存数组收地址
int n:有效数据元素的个数
*/
void showA(int *p, int n)
{
for (int i = 0; i < n; i++)
printf("%d ", p[i]);
printf("\n");
}
/* (3)删除数组元素
功能:删除数组中指定元素
函数:void deleteIntoA(int *p,int n, int post);
参数:
int *p: 保存数组首地址
int n: 有效数据元素的个数
int post: 删除元素下标
*/
void deleteIntoA(int *p, int n, int post) //delet删除 //p=a, n=9, post=4
{
int i;
//从删除位置元素的后一个元素到最后一个元素向前移动一个单位
for (i = post + 1; i < n; i++) //i = 5, i<9; i=6,6<9; i=7,i<9; i=8; i=9(出循环)
p[i - 1] = p[i]; //p[4]=p[5]; p[5]=p[6]; p[6]=p[7]; p[7]=p[8];
}
int main()
{
int a[100] = {1, 2, 3, 4, 5, 6, 7, 8};
insertIntoA(a, 8, 4, 100);
showA(a, 9);
deleteIntoA(a, 9, 4);
showA(a, 8);
}
通过添加全局变量last表示最后一个有效元素的下标:
#include <stdio.h>
int last = 7; //代表最后一个有效元素下标 last = 有效元素个数-1
/*
功能:向数组的第几个位置插数据
函数:void insetIntoA(int *p,int post, int data);
参数:
int *p: 保存数组首地址
int post: 插入元素下标
int data: 数据
*/
void insertIntoA(int *p, int post, int data) //insert插入
{
int i;
//1.从最后一个元素到插入位置的元素向后移动一个单位
for (i = last; i >= post; i--)
p[i + 1] = p[i];
//2.插入新元素data到指定位置
p[post] = data; //p[4] = 100
//3. 让last加一,因为插入一个元素,有效元素多了一个
last++;
}
/* (2)遍历数组中的有效元素
功能:遍历数组中的有效元素
函数:void showA(int *p);
参数:
int *p:保存数组收地址
*/
void showA(int *p)
{
for (int i = 0; i <= last; i++)
printf("%d ", p[i]);
printf("\n");
}
/* (3)删除数组元素
功能:删除数组中指定元素
函数:void deleteIntoA(int *p, int post);
参数:
int *p: 保存数组首地址
int post: 删除元素下标
*/
void deleteIntoA(int *p, int post) //delet删除
{
int i;
//从删除位置元素的后一个元素到最后一个元素向前移动一个单位
for (i = post + 1; i <= last; i++)
p[i - 1] = p[i];
//让last减一,因为删除了一个元素有效元素少了一个
last--;
}
int main()
{
int a[100] = {1, 2, 3, 4, 5, 6, 7, 8};
insertIntoA(a, 4, 100);
showA(a);
deleteIntoA(a, 4);
showA(a);
}
3. 顺序表编程实现
封装结构体:
#define N 10
typedef struct seqlist //封装顺序表结构体类型
{
int data[N]; //用来存数据的数组
int last; //代表数组中最后一个有效元素的下标
} seqlist_t, *seqlist_p;
//seqlist_t A; // 等同于struct seqlist A
//seqlist_p p; //等同于 struct seqlist *p;
创建空顺序表:
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct seqlist //封装顺序表结构体类型
{
int data[N]; //用来存数据的数组
int last; //代表数组中最后一个有效元素的下标
} seqlist_t, *seqlist_p;
// 创建一个空的顺序表
seqlist_p CreateEpSeqlist() //create创造 empty 空的 seqlist顺序表
{
//动态申请一块顺序表结构体大小空间
seqlist_p p = (seqlist_p)malloc(sizeof(seqlist_t));
if (NULL == p)
{
perror("malloc lost"); //perror打印上一个函数报的错误信息
return NULL; //错误情况让函数返回空指针
}
//对结构体初始化
p->last = -1;
return p;
}
//判断顺序表是否为满,满返回1,未满返回0
int IsFullSeqlist(seqlist_p p) //full满
{
return p->last + 1 == N;
}
//向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_p p, int post, int data)
{
//容错判断:判满,对post做判断
if (IsFullSeqlist(p) || post < 0 || post > p->last + 1)
{
printf("InsertIntoSeqlist err\n");
return -1; //错误返回
}
//让最后一个元素到插入位置的元素向后移动一个单位
for (int i = p->last; i >= post; i--)
p->data[i + 1] = p->data[i];
//插入数据
p->data[post] = data;
//让last加一
p->last++;
return 0;
}
//遍历顺序表sequence顺序list表
void ShowSeqlist(seqlist_p p)
{
for (int i = 0; i <= p->last; i++)
printf("%d ", p->data[i]);
printf("\n");
}
//判断顺序表是否为空,为空返回1,不为空返回0
int IsEpSeqlist(seqlist_p p)
{
return p->last == -1;
}
//删除顺序表中指定位置的数据,post为删除位置
int DeleteIntoSeqlist(seqlist_p p, int post)
{
//容错判断:判空,对post判断
if (IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("DeleteIntoSeqlist err\n");
return -1;
}
//从删除位置元素的后一个元素到最后一个元素向前移动一个单位
for (int i = post + 1; i <= p->last; i++)
p->data[i - 1] = p->data[i];
//让last减一,因为删除了一个元素有效元素少了一个
p->last--;
return 0;
}
// 修改指定位置上数据
int ChangePostSeqList(seqlist_p p, int post, int data)
{
//容错判断:判空,对post判断
if (IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("ChangePostSeqList err\n");
return -1;
}
//修改指定位置数据
p->data[post] = data;
return 0;
}
// 查找指定数据出现的位置,返回下标,未找到返回-1
int SearchDataSeqList(seqlist_p p, int data)
{
for (int i = 0; i <= p->last; i++)
{
if (p->data[i] == data)
return i;
}
return -1;
}
// 清空顺序表(清空:访问不到,但是内存中还有。销毁:内存清空)
void ClearSeqList(seqlist_p p)
{
p->last = -1;
}
int main(int argc, char const *argv[])
{
seqlist_p p = CreateEpSeqlist();
InsertIntoSeqlist(p, 0, 10);
InsertIntoSeqlist(p, 1, 20);
InsertIntoSeqlist(p, 2, 30);
ShowSeqlist(p);
DeleteIntoSeqlist(p, 1);
ShowSeqlist(p);
ChangePostSeqList(p, 0, 99);
ShowSeqlist(p);
printf("search 99:%d\n", SearchDataSeqList(p, 99));
return 0;
}
分文件编程实现:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "seqlist.h"
int main(int argc, char const *argv[])
{
seqlist_p p = CreateEpSeqlist();
InsertIntoSeqlist(p, 0, 10);
InsertIntoSeqlist(p, 1, 20);
InsertIntoSeqlist(p, 2, 30);
ShowSeqlist(p);
DeleteIntoSeqlist(p, 1);
ShowSeqlist(p);
ChangePostSeqList(p, 0, 99);
ShowSeqlist(p);
printf("search 99:%d\n", SearchDataSeqList(p, 99));
return 0;
}
seqlist.c
#include <stdio.h>
#include <stdlib.h>
#include "seqlist.h"
// 创建一个空的顺序表
seqlist_p CreateEpSeqlist() //create创造 empty 空的 seqlist顺序表
{
//动态申请一块顺序表结构体大小空间
seqlist_p p = (seqlist_p)malloc(sizeof(seqlist_t));
if (NULL == p)
{
perror("malloc lost"); //perror打印上一个函数报的错误信息
return NULL; //错误情况让函数返回空指针
}
//对结构体初始化
p->last = -1;
return p;
}
//判断顺序表是否为满,满返回1,未满返回0
int IsFullSeqlist(seqlist_p p) //full满
{
return p->last + 1 == N;
}
//向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_p p, int post, int data)
{
//容错判断:判满,对post做判断
if (IsFullSeqlist(p) || post < 0 || post > p->last + 1)
{
printf("InsertIntoSeqlist err\n");
return -1; //错误返回
}
//让最后一个元素到插入位置的元素向后移动一个单位
for (int i = p->last; i >= post; i--)
p->data[i + 1] = p->data[i];
//插入数据
p->data[post] = data;
//让last加一
p->last++;
return 0;
}
//遍历顺序表sequence顺序list表
void ShowSeqlist(seqlist_p p)
{
for (int i = 0; i <= p->last; i++)
printf("%d ", p->data[i]);
printf("\n");
}
//判断顺序表是否为空,为空返回1,不为空返回0
int IsEpSeqlist(seqlist_p p)
{
return p->last == -1;
}
//删除顺序表中指定位置的数据,post为删除位置
int DeleteIntoSeqlist(seqlist_p p, int post)
{
//容错判断:判空,对post判断
if (IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("DeleteIntoSeqlist err\n");
return -1;
}
//从删除位置元素的后一个元素到最后一个元素向前移动一个单位
for (int i = post + 1; i <= p->last; i++)
p->data[i - 1] = p->data[i];
//让last减一,因为删除了一个元素有效元素少了一个
p->last--;
return 0;
}
// 修改指定位置上数据
int ChangePostSeqList(seqlist_p p, int post, int data)
{
//容错判断:判空,对post判断
if (IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("ChangePostSeqList err\n");
return -1;
}
//修改指定位置数据
p->data[post] = data;
return 0;
}
// 查找指定数据出现的位置,返回下标,未找到返回-1
int SearchDataSeqList(seqlist_p p, int data)
{
for (int i = 0; i <= p->last; i++)
{
if (p->data[i] == data)
return i;
}
return -1;
}
// 清空顺序表(清空:访问不到,但是内存中还有。销毁:内存清空)
void ClearSeqList(seqlist_p p)
{
p->last = -1;
}
seqlist.h
#ifndef __SEQLIST_H__
#define __SEQLIST_H__
#define N 10
typedef struct seqlist //封装顺序表结构体类型
{
int data[N]; //用来存数据的数组
int last; //代表数组中最后一个有效元素的下标
} seqlist_t, *seqlist_p;
// 创建一个空的顺序表
seqlist_p CreateEpSeqlist(); //create创造 empty 空的 seqlist顺序表
//判断顺序表是否为满,满返回1,未满返回0
int IsFullSeqlist(seqlist_p p); //full满
//向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_p p, int post, int data);
//遍历顺序表sequence顺序list表
void ShowSeqlist(seqlist_p p);
//判断顺序表是否为空,为空返回1,不为空返回0
int IsEpSeqlist(seqlist_p p);
//删除顺序表中指定位置的数据,post为删除位置
int DeleteIntoSeqlist(seqlist_p p, int post);
// 修改指定位置上数据
int ChangePostSeqList(seqlist_p p, int post, int data);
// 查找指定数据出现的位置,返回下标,未找到返回-1
int SearchDataSeqList(seqlist_p p, int data);
// 清空顺序表(清空:访问不到,但是内存中还有。销毁:内存清空)
void ClearSeqList(seqlist_p p);
#endif
makefile
CC=gcc
GFLAGS=-c -g -Wall
OBJS=seqlist.o main.o
seqlist:$(OBJS)
$(CC) $^ -o $@
%.o:%.c
$(CC) $(GFLAGS) $< -o $@
.PHONY:clean
clean:
$(RM) seqlist *.o
顺序表特点:
标签:顺序,last,day03,seqlist,int,post,数据结构,data From: https://blog.csdn.net/QR70892/article/details/141336248
- 顺序表内存空间连续
- 顺序表长度固定
- 插入和删除操作效率低,修改和查找效率高。