1.数据结构
定义: 存储和组织数据的方式
算法对数据进行处理–>四大基本操作 (增 删 查 改)
- 不同的数据结构具有不同的操作方式,需要选择合适的数据结构,提升代码的效率
根据数据之间的逻辑结构将数据分为以下几种关系:
-
集合:数据与数据之间无明显关系
-
线性关系:每个数据有唯一的前驱和后继
-
树状结构:一对多
-
图:多对
1.5数据间的存储结构
-
顺序存储:存放元素的位置相邻
-
链式存储:元素间位置不相邻,但是可以通过上一个元素找到下一个数据
2.线性关系
顺序表:
- 顺序存储的线性表
链表/双链表
栈和队列
3.本次课内容——顺序表
在实现对数组的操作之前:
- 已经预先定义如下结构体变量
typedef struct list
{
int arr[100];
int len;//管理当前存放数据的个数
int size;//用于管理动态数组的大小
}LIST;
- 对结构体变量进行预处理,预处理的过程实际是将顺序表的长度初始化为0,包括静态数组和动态数组的初始化
void init(LIST *p)
{
p->len = 0;
p->size = 100;
}
3.1增的代码实现
- 如果顺序表还没有任何数据的情况下,增加数据的代码为:
void insertNumber1(LIST* p,int data)
{
if(p->len>p->size)return;
p->arr[p->len]=data;
p->len++;
}
- 如果顺序表已经有数据,在顺序表的尾部插入数据,代码为
void insertNumber2(LIST *p,int data)
{
if(p->len>p->size)return;
p->arr[p->len+1]=data;
p->len++;
}
3.如果顺序表已经有数据,需要在顺序表中间插入,则需要将后面的元素后移,代码为
void insertNumber3(LIST *p,int num,int data)//假设num为将要插入的位置
{
if(p->len>p->size)return;
for(int i=num;i<p->len+1;++i)
{
arr[i+1]=arr[i];
}//将num位置及其后的数据向后移动
arr[i]=data;
p->len++;//将线性表的长度扩大
}
3.2删的代码实现
线性表删除元素的方式是通过将要删除的位置n1,用后面位置n2来代替,后面依次向前挪动
void deleData(LIST* p,int data)
{
//通过循环找到要删除的数据data所在位置
for(int i=0;i<p->len;++i)
{
if(p->arr[i]==data)
{
for(int j=i;j<p->len-1;++j)
{
p->arr[j]=p->arr[j+1];
}
p->len-1;
break;
}
}
}
顺序表中的查、改操作比较简单,此处略
3.3查的代码实现
3.4改的代码实现
查找如果是有序数组,那么可以通过多种方法进行查找,如果是无序的则只能一个一个查找
4.代码实例
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
typedef struct list
{
int arr[100];
int len;//管理当前存放数据的个数
int size;//用于管理动态数组的大小
}LIST;
//顺序表初始化,对顺序表进行操作
void init(LIST *p);
//实现插入功能的函数
void insertData(LIST*p,int data);
//实现删除一个数字功能的函数
void deleData(LIST *p, int data);
//实现删除所有重复数字功能的函数
void deleData1(LIST *p, int data);
//实现查找功能
void findData(LIST *p, int data);
int main()
{
printf("以下输出用来说明对一组数插入一个数的工程:\n");
LIST mylist1;//准备一个顺序表
init(&mylist1);
srand((unsigned)time(NULL));
for (int i = 0; i < 80; ++i)
{
insertData(&mylist1, rand() % 200);
}//赋值
for (int i = 0; i < mylist1.len; ++i)
{
printf("%-4d", mylist1.arr[i]);
}//输出
printf("\n\n以下输出用来说明对一组数进行删除数字10的操作:\n");
LIST mylist2;//准备一个顺序表
init(&mylist2);
for (int i = 0; i < 80; ++i)
{
insertData(&mylist2, i);
}
printf("原始数组内容为:\n");
for (int i = 0; i < mylist2.len; ++i)
{
//if (i % 7 == 0)printf("\n");
printf("%-4d", mylist2.arr[i]);
}
deleData(&mylist2, 10);
printf("\n删除数字10 之后的数组为:\n");
for (int i = 0; i < mylist2.len; ++i)
{
//if (i % 7 == 0)printf("\n");
printf("%-4d", mylist2.arr[i]);
}
printf("\n\n以下输出用来说明对一组数进行删除重复数字10的操作:\n");
LIST mylist3;//准备一个顺序表
init(&mylist3);
for (int i = 0; i < 80; ++i)
{
insertData(&mylist3, i/7);
}
printf("原始数组内容为:\n");
for (int i = 0; i < mylist3.len; ++i)
{
if (i % 7 == 0)printf("\n");
//if (i % 7 == 0)printf("\n");
printf("%-4d", mylist3.arr[i]);
}
deleData1(&mylist3, 10);
printf("\n删除数字10 之后的数组为:\n");
for (int i = 0; i < mylist3.len; ++i)
{
if (i % 7 == 0)printf("\n");
//if (i % 7 == 0)printf("\n");
printf("%-4d", mylist3.arr[i]);
}
printf("\n\n以下内容用来查找值为3在这个数组中是否存在:\n");
//查找mylist3中数字为3的值
findData(&mylist3, 3);
getchar();
return 0;
}
void init(LIST *p)
{
p->len = 0;
p->size = 100;
}
void insertData(LIST*p,int data)
{
#if 0
//插入方式:头插、尾插、中间插入
if ( p->len == p->size) return;//防止数组越界
p->arr[p->len] =data ;
p->len++;//len管理插入数据的个数 插入一个数据 len就++一次
#else//其它插入方式
if (p->len == p->size) return;
int i = p->len;
while (i - i >= 0 && p->arr[i - 1] > data)
{
p->arr[i] = p->arr[i - 1];
--i;
}
p->arr[i] = data;
p->len++;
#endif
}
//删除元素不是正常想象的直接删除,而是将要删除元素的位置用后面元素替代
void deleData(LIST *p, int data)
{
//删除一个数据
for (int i = 0; i < p->len; ++i)
{
if (p->arr[i] == data)//找到要删除元素的下标
{
for (int j = i; j < p->len-1; ++j)//实现元素删除
{
p->arr[j] = p->arr[j+1];//j+1<len
}
p->len--;//删除之后元素个数-1
break;
}
}
}
//用于删除全部的重复数字
void deleData1(LIST *p, int data)
{
//删除一个数据
for (int i = 0; i < p->len; ++i)
{
if (p->arr[i] == data)//找到要删除元素的下标
{
for (int j = i; j < p->len - 1; ++j)//实现元素删除
{
p->arr[j] = p->arr[j + 1];//j+1<len
}
p->len--;//删除之后元素个数-1
--i;
//break;
}
}
}
//用于查找该数组中数字为3的值
void findData(LIST *p, int data)
{
for (int i = 0; i < p->len; ++i)
{
if (p->arr[i] == data)
{
printf("arr[%d]=%d\t",i,p->arr[i]);//数据少用数据结构,数据多用数据库
}
}
}