1、线性表的基本概念
(1)线性结构是简单而且常用的数据结构,而线性表则是一种典型的线性结构。
(2)线性表:是具有相同数据类型的n个数据元素的有限序列
(3)线性表的存储结构:顺序存储结构:顺序表 链式存储结构:链表
操作数据结构的思路:创销——针对表、增删改查——针对数据
2、顺序表 逻辑顺序和物理结构一致
1.数据结构是计算机存储,管理数据的方式。
2.数据结构研究的就是这种数据的存储结构(物理结构)和数据的逻辑结构。
3.数据逻辑结构
(1)集合 元素之间没有任何逻辑关系
(2)线性结构 元素之间存在一对一
(3)树型结构 元素之间存在一对多
(4)图形结构 元素之间存在多对多
4.数据存储结构
(1)顺序存储 (逻辑顺序和存储顺序一致)
(2)链式存储 (逻辑顺序和存储顺序不在乎一致)
(3)索引存储
(4)散列存储
5.线性表:具有相同数据类型的n个有限序列组成
逻辑结构:线性结构
存储结构:顺序存储====>顺序表 链式存储====>链表线性表的特点:围绕一对一关系的描述
6.顺序表:
(1)常用操作:创建、销毁、增删改查
1.创建顺序表结构体类型—需要用户自定义
顺序表的实现方式:1.通过数组 2.通过指针顺序表的特点:
(1)顺序表的元素是按顺序进行存储的
(2)顺序表比较擅长随机访问和遍历
(3)不擅长动态删除增加,需要移动大量元素7.顺序表和数组进行对比
1、数组是一种特殊的顺序表
2、顺序表是通过数组来实现的,顺序表的元素存储在一块连续的存储空间里
3、数组的长度是不可变的,顺序表的长度是可以改变的
2.1、项目练习: 通过数组创建顺序表结构体类型
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//1.创建顺序表结构体类型
#define MAX_SIZE 100
typedef int elementType;//将int类型重命名为elementType
typedef struct OrderList {//1.通过数组创建
elementType data[MAX_SIZE];//存放顺序表元素的数组
int length;//存放顺序表元素的个数
}OrderList;//声明函数
void print_menu(void);
OrderList* create_list();
void printf_list(OrderList* List);
void append_list(OrderList* List,elementType val);
void insert_list(OrderList* List, int index, elementType val);
void delete_List(OrderList* List, int index);
void change_List(OrderList* List, int index, elementType val);
void destroy_List(OrderList** List);
int main() {
print_menu();//调用菜单函数
int order=0;//接收用户操作的指令
elementType val = 0;//数组中的元素
int index = 0;//数组的索引下标//定义顺序表结构体指针
OrderList* List = NULL; //内存动态分配,需要手动释放while (1) {
printf("请输入您的操作指令:");
scanf("%d", &order);
switch (order) {
case 1:
//创建顺序表
List = create_list();
break;
case 2:
//打印顺序表
printf_list(List);
break;
case 3:
//追加一个节点 从尾部追加
printf("请输入您要追加的元素:");
scanf("%d", &val);
append_list(List,val);
break;
case 4:
//插入一个节点 随机插入(从0开始)
printf("请输入您要插入的位置:");
scanf("%d", &index);
printf("请输入您要插入的元素:");
scanf("%d", &val);
insert_list(List,index,val); //三个参数分别为表、插入位置、插入的数据
break;
case 5:
//删除一个节点 用户输入删除的索引,默认从0开始
printf("请输入您要删除的位置:");
scanf("%d", &index);
delete_List(List, index);
break;
case 6:
//修改顺序表元素 用户输入修改的索引,默认从0开始
printf("请输入您要修改的位置:");
scanf("%d", &index);
printf("请输入修改后的元素:");
scanf("%d", &val);
change_List(List, index, val);
break;
case 7:
//销毁顺序表
destroy_List(&List); //传地址
break;
case 8:
//退出
return;
default:
printf("输入指令有误,请重新输入!\n");
}
}
return 0;
}//打印菜单
void print_menu(void) {
system("cls");//系统函数 用于屏幕清空
printf("操作指令说明:\n");
printf("1:创建顺序表\n2:打印顺序表\n");
printf("3:追加一个节点\n4:插入一个节点\n");
printf("5:删除一个节点\n6:修改顺序表元素\n");
printf("7:销毁顺序表\n8:退出\n");
}//1.创建顺序表的函数
OrderList* create_list() {
OrderList* List = (OrderList*)malloc(sizeof(OrderList));//动态创建顺序表
//申请失败
if (List == NULL) {
printf("创建失败!\n");
return NULL;
}
//申请成功 先清0//memset() 一般用于数组清0,需引入memory.h/string.h
memset(List, 0, sizeof(OrderList));
List->length = 0;
printf("初始化成功\n");
return List;
}//2.打印顺序表的函数
void printf_list(OrderList* List) {
//判断顺序表是否存在
if (List == NULL) {
printf("顺序表不存在,请先创建!\n");
return;
}
//判断顺序表是否为空
if (!List->length) {
printf("顺序表为空,无法打印!\n");
return;
}
//正常打印
for (int i = 0;i < List->length;i++) {
printf("%d ", List->data[i]);
}
printf("\n");
}//3.追加一个节点 从索引0开始
void append_list(OrderList* List, elementType val) {
//判断顺序表是否存在
if (List == NULL) {
printf("顺序表不存在,请先创建!\n");
return;
}
//判断是否内存是否占满
if (List->length >= MAX_SIZE) {
printf("内存已满,无法追加\n");
return;
}
//正常追加
List->data[List->length] = val; //将数据存放在数组的最后
List->length++;
printf("数据追加成功!\n");
}//4.插入一个节点 从索引0开始
void insert_list(OrderList* List, int index, elementType val) {
//判断顺序表是否存在
if (List == NULL) {
printf("顺序表不存在,请先创建!\n");
return;
}
//判断是否内存是否占满
if (List->length >= MAX_SIZE-1) {
printf("内存已满,无法追加\n");
return;
}
//正常插入数据
for (int i = List->length;i >= index;i--) {
List->data[i + 1] = List->data[i];
}
List->data[index] = val;
List->length++;
printf("数据插入成功!\n");
}//5.删除一个节点 从索引0开始
void delete_List(OrderList* List, int index) {
//判断顺序表是否存在
if (List == NULL) {
printf("顺序表不存在,请先创建!\n");
return;
}
//判断输入的位置即索引值是否合法
if (index<0 || index>= List->length) {
printf("输入的位置不合法!\n");
return;
}
//正常删除
for (int i = index;i < List->length;i++) {
List->data[i] = List->data[i + 1];
}
List->length--;
printf("数据删除成功!\n");
}//6.修改顺序表元素 从索引0开始
void change_List(OrderList* List, int index, elementType val) {
//判断顺序表是否存在
if (List == NULL) {
printf("顺序表不存在,请先创建!\n");
return;
}
//正常修改
List->data[index] = val;
printf("数据修改成功!\n");
}//7.销毁 注意:形参是二级指针
void destroy_List(OrderList** List) {
free(*List);
*List = NULL;
printf("顺序表已销毁!\n");
}
2.2、指针实现顺序表
2.2.1、mian.c
#include <stdio.h>
#include "03.h"
int main() {
fn2();
return 0;
}
2.2.2、03.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
//顺序表的指针实现方式
//定义结构体
typedef int ElemenT;
typedef struct OrderListPtr {
ElemenT* datap;//元素类型指针 用于申请内存后存放数组元素
int length;//存放数组元素的个数
}ODP;void fn2(void);
void create_List(ODP* List);
void printf_menu(void);
void append_List(ODP* List, ElemenT val);
void printf_List(ODP List);
void insert_List(ODP* List, int index, ElemenT val);
void delete_List(ODP* List, int index);
void edit_List(ODP* List, int index, ElemenT val);
void destory_List(ODP* List);
2.2.3、03.c
#include "03.h"
#define MAX_SIZE 100
void fn2(void) {int order = 0;//存储操作指令
printf_menu();//调用菜单函数
ODP List = {NULL,0}; //定义结构体变量
ElemenT val = 0;
int index = 0;
while (1) {
printf("请输入操作指令:");
scanf("%d", &order);
switch (order) {
case 1:
//创建空表
create_List(&List);//分配一块连续的空间
break;
case 2:
//打印顺序表
printf_List(List);
break;
case 3:
//追加一个节点
printf("请输入要追加的元素");
scanf("%d", &val);
append_List(&List, val);
break;
case 4:
//插入一个节点
printf("请输入要插入的位置:");
scanf("%d", &index);
printf("请输入要插入的元素");
scanf("%d", &val);
insert_List(&List, index, val);//表,位置,插入的是谁
break;
case 5:
//删除一个节点
printf("您要删除位置:");
scanf("%d", &index);
delete_List(&List, index);
break;
case 6:
//修改顺序表元素
printf("请输入要修改的元素位置");
scanf("%d", &index);
printf("请输入修改后的新值:");
scanf("%d", &val);
edit_List(&List, index, val);
break;
case 7:
//销毁顺序表
destory_List(&List);//传地址
break;
case 8:
//退出
return;
default:
printf("输入指令有误,请重新输入\n");
}
}}
//打印菜单
void printf_menu(void) {
system("cls");//系统函数 用于屏幕清空
printf("操作指令说明:\n");
printf("1:创建顺序表\n2:打印顺序表\n");
printf("3:追加一个节点\n4:插入一个节点\n");
printf("5:删除一个节点\n6:修改顺序表元素\n");
printf("7:销毁顺序表\n8:退出\n");
}//初始化一个空表
void create_List(ODP* List) {
//申请内存空间
List->datap = (ElemenT*)malloc(sizeof(ElemenT) * MAX_SIZE);
if (!List->datap) {
printf("内存申请失败\n");
return;
}
//清0操作
memset(List->datap, 0, sizeof(ElemenT) * MAX_SIZE);
List->length = 0;
printf("初始化成功!\n");
}
//追加函数
void append_List(ODP* List, ElemenT val) {
//判断是否建过表
if (!List->datap) {
printf("请先建表\n");
return;
}
//判断表是否满
if (List->length >= MAX_SIZE) {
printf("表已满,无法追加!\n");
return;
}
//正常追加
*(List->datap + List->length) = val;//追加方法二
//List->datap[List->length] = val;
List->length++;
printf("追加成功\n");
}//打印顺序表
void printf_List(ODP List) {
//判断是否建过表
if (!List.datap) {
printf("请先建表\n");
return;
}
if (List.length == 0) {
printf("空表,无法打印\n");
return;
}
for (int i = 0;i < List.length;i++) {
printf("%d ", List.datap[i]);//数组
//printf("%d ", *(List.datap+i));//指针
}
printf("\n");
}
//插入操作
void insert_List(ODP* List, int index, ElemenT val) {
//判断是否建过表
if (!List->datap) {
printf("请先建表\n");
return;
}
//判断表是否满
if (List->length >=MAX_SIZE) {
printf("表已满,无法追加\n");
return;
}//正常插入 从index倒序遍历,位置后移
//判断插入的位置是否合法
if (index<0 || index>List->length - 1) {
printf("插入位置不合法\n");
return;
}
for (int i = List->length - 1;i >= index;i--) {
List->datap[i + 1] = List->datap[i];
}
//数组
List->datap[index] = val;
//指针
//*(List->datap + index) = val;
List->length++;
printf("插入成功!\n");
}
//删除函数
void delete_List(ODP* List, int index) {
//判断是否建过表
if (!List->datap) {
printf("请先建表\n");
return;
}
if (List->length == 0) {
printf("空表,无法删除\n");
return;
}
//判断要删除的元素位置是否合法
int ind = index - 1;//要删除的元素索引
if (ind<0 || ind>List->length - 1) {
printf("您要删除的元素不存在\n");
return;
}
//正常删除 从ind+1开始,所有的元素前移
for (int i = ind;i < List->length;i++) {
List->datap[i] = List->datap[i + 1];
}
List->length--;
printf("删除成功!\n");
}//修改函数
void edit_List(ODP* List, int index, ElemenT val) {
//判断是否建过表
if (!List->datap) {
printf("请先建表\n");
return;
}
if (List->length == 0) {
printf("空表,无法修改\n");
return;
}
//判断要修改的元素位置是否合法
int ind = index - 1;//要修改的元素索引
if (ind<0 || ind>List->length - 1) {
printf("您要修改的元素不存在\n");
return;
}
//正常修改
List->datap[ind] = val;
// *(List->datap + ind) = val;
printf("修改成功!\n");
}//销毁 注意:形参是二级指针
void destory_List(ODP* List) {
free(List->datap);//释放内存空间
List->datap = NULL;//销毁前要置空
List->length = 0;//元素置0
printf("销毁成功!\n");
}