一、数据结构介绍
二、顺序表
三、通讯录的实现
数据结构介绍
数据结构是由‘数据’和‘结构’组成。
数据:一些包含特定信息的图片、文字、视频等。比如教务管理系统里保存的用户信息(姓名、性别、年龄、学历)、购物平台中的衣服、裤子、首饰、鞋子等文字。
结构:将一些包含数据的变量组合在一起,形成的特定结构。
数据结构:它是计算机存储、组织数据的方式,是指一些有关联的数据的集合,而且各数据之间通过特定的方式连结所形成的结构(小编对数据结构不是特别明白,这是在别人的基础上通过自己的理解拷贝别人的)
数据结构的特点:1.数据的空间大小可以自由改变 2.存储的数据可以包含任意类型 3.存储的数据能够方便查找
顺序表
1.线性表:它是一些相同特性的数据元素的有序排列方式。线性表是在实际应用中非常广泛的数据结构,例如:顺序表、链表、栈、字符串......
2.线性表逻辑:它的逻辑是线性结构,各个数据是相连的,但储存的位置不一定相连。
3.顺序表与数组的差别:顺序表的底层结构是数组,对数组的封装,实现了增查改删等功能。就比如下面的通讯录。
#include"Sequence.h"//这里是用来测试功能是否可以正常使用
int main()
{
SQL s1;
DataInit(&s1);//初始化
AddFront(&s1, 5);//头插
ShowData(&s1);//打印
AddBack(&s1, 6);//尾插
ShowData(&s1);//打印
AddAnywhere(&s1, 2);//任意位置添加数据
ShowData(&s1);//打印
int i = FindData(&s1, 2);//查找
if (i)
{
printf("它的下标是%d\n", i);
}
DeleteAnywhere(&s1, 2);//任意位置删除
ShowData(&s1);//打印
DestroyData(&s1);//销毁数据
return 0;
}
这里是一些头文件的包含,大家在实现某项目时,会涉及很多的方法,将这些方法申明用一个头文件包含,到时候在有主函数main的文件中只要包含头文件就可以使用函数了。
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//#define TYPE_MEMBER int //这里定义储存的数据类型,用于其他类型时,便于修改
typedef int TYPE_MEMBER;
typedef struct SequenceList
{
TYPE_MEMBER* data;//用指针指向动态内存,便于增加可用数据空间
int size;//有效数据大小
int capacity;//可用空间大小
}SQL;
//数据初始化
void DataInit(SQL* data);
//数据销毁
void DestroyData(SQL* data);
//扩容
void DataExpand(SQL* data);
//在数据最前面添加数据
void AddFront(SQL* data, TYPE_MEMBER n);
//在数据后面添加数据
void AddBack(SQL* data, TYPE_MEMBER n);
//在空间内任意点添加数据
void AddAnywhere(SQL* data, TYPE_MEMBER n);
//在有效数据点内任意位置删除数据
void DeleteAnywhere(SQL* data, TYPE_MEMBER n);
//打印数据
void ShowData(SQL* data);
//查找数据
int FindData(SQL* data, TYPE_MEMBER n);
这里便是定义函数的源文件了,将这些定义写在一个源文件或者多个源文件中可以很方便查找我们要使用的函数原型
#include"Sequence.h"
//先将数据初始化
void DataInit(SQL* data)//
{
data->data = (TYPE_MEMBER*)malloc(sizeof(TYPE_MEMBER) * 4);
data->size = 0;
data->capacity = 4;
}
//数据销毁
void DestroyData(SQL* data)
{
assert(data->data);//看看data->data是否为空指针
free(data->data);
data->size = data->capacity = 0;
}
//扩容
void DataExpand(SQL* data)
{
TYPE_MEMBER* new = data->data;
if (data->capacity == data->size)//添加数据前先判断空间是否足够
{
new = (TYPE_MEMBER*)realloc(data->data, data->capacity * 2);//将原来的空间扩大两倍
if (new == NULL)
{
perror("realloc");
return;
}
else
data->data = new;
data->capacity *= 2;
}
}
//在最前面添加数据
void AddFront(SQL* data, TYPE_MEMBER n)
{
DataExpand(data);//先判断是否要扩容
for (int i = data->size; i >= 1; i--)
{
data->data[i] = data->data[i - 1];//将有效数据向后移动一位
}
data->data[0] = n;
data->size += 1;
}
//在最后面添加数据
void AddBack(SQL* data, TYPE_MEMBER n)
{
DataExpand(data);//先判断是否要扩容
data->data[data->size] = n;
data->size += 1;
}
//在有效据内任意点插入数据
void AddAnywhere(SQL* data, TYPE_MEMBER n)
{
DataExpand(data);//先判断是否要扩容
int size;
printf("请输入你要添加的位置\n"); scanf("%d", &size);
if (size >= 0 || size < data->size)
{
for (int i = data->size; i >= size; i--)
{
data->data[i] = data->data[i - 1];//将有效数据向后移动一位
}
data->data[size - 1] = n;
data->size += 1;
}
else
printf("位置错误\n");
}
//在有效数据点内任意位置删除数据
void DeleteAnywhere(SQL* data, TYPE_MEMBER n)
{
int size;
printf("请输入你要删除的位置\n"); scanf("%d", &size);
if (size >= 0 || size < data->size)
{
for (int i = size - 1; i < data->size - 1; i++)
{
data->data[i] = data->data[i + 1];//将有效数据向后移动一位
}
data->size -= 1;
}
else
printf("位置错误\n");
}
//打印数据
void ShowData(SQL* data)
{
int i;
for (i = 0; i < data->size; i++)
{
printf("%d ", data->data[i]);
}
printf("\n");
}
//查找数据
int FindData(SQL* data, TYPE_MEMBER n)
{
int i;
for (i = 0; i < data->size; i++)
{
if (data->data[i] == n)
{
printf("找到了\n");
return i;
}
}
printf("没找到\n");
return 0;
}
通讯录的实现
下面的通讯录是建立在顺序表的基础之上,有地方还是有所改动。不过,逻辑还是和顺序表一样,实现它并不是很难。
#include"Contact.h"
void menu()
{
printf("**************** 通讯录 ***************\n");
printf("*********1.头插 2.尾插************\n");
printf("*********3.任意位置插 4.任意位置删除****\n");
printf("*********5.查找数据 6.打印数据********\n");
printf("*********0.退出 7.销毁数据********\n");
}int main()
{
int input;
SQL s1;
DataInit(&s1);//初始化
menu();
do //这里用循环和选择实现功能的重复操作
{
printf("请输入你要执行的操作\n");
scanf("%d", &input);
switch (input)
{
case 0:break;
case 1:AddFront(&s1); break;
case 2:AddBack(&s1); break;
case 3:AddAnywhere(&s1); break;
case 4:DeleteAnywhere(&s1); break;
case 5:FindData(&s1); break;
case 6:ShowData(&s1); break;
case 7:DestroyData(&s1); break;
default:printf("输入错误\n"); break;
}
} while (input);
return 0;
}
头文件包含的函数申明以及结构类型
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//这里定义储存的数据类型,用于其他类型时,便于修改
typedef struct CONTACT
{
char name[20];
char gander[10];
char tel[20];
char addr[20];
int age;
}TYPE_MEMBER;//申明
typedef struct SequenceList
{
TYPE_MEMBER* data;//用指针指向动态内存,便于增加可用数据空间
int size;//有效数据大小
int capacity;//可用空间大小
}SQL;//数据初始化
void DataInit(SQL* data);
//数据销毁
void DestroyData(SQL* data);
//扩容
void DataExpand(SQL* data);
//在数据最前面添加数据
void AddFront(SQL* data);
//在数据后面添加数据
void AddBack(SQL* data);
//在空间内任意点添加数据
void AddAnywhere(SQL* data);
//在有效数据点内任意位置删除数据
void DeleteAnywhere(SQL* data);
//打印数据
void ShowData(SQL* data);
//查找数据
int FindData(SQL* data);
这里的函数实现方法有改动,写的时候不能直接照着顺序表直接抄
#include"Sequence.h"
//先将数据初始化
void DataInit(SQL* data)//
{
data->data = (TYPE_MEMBER*)malloc(sizeof(TYPE_MEMBER) * 4);
data->size = 0;
data->capacity = 4;
}
//数据销毁
void DestroyData(SQL* data)
{
assert(data->data);//看看data->data是否为空指针
free(data->data);
data->size = data->capacity = 0;
}
//扩容
void DataExpand(SQL* data)
{
TYPE_MEMBER* new = data->data;
if (data->capacity == data->size)//添加数据前先判断空间是否足够
{
new = (TYPE_MEMBER*)realloc(data->data, data->capacity * 2);//将原来的空间扩大两倍
if (new == NULL)
{
perror("realloc");
return;
}
else
data->data = new;
data->capacity *= 2;
}
}
//在最前面添加数据
void AddFront(SQL* data)
{
DataExpand(data);//先判断是否要扩容
TYPE_MEMBER s1 = { 0 };
printf("请输入名字\n"); scanf("%s", s1.name);
printf("请输入性别\n"); scanf("%s", s1.gander);
printf("请输入电话\n"); scanf("%s", s1.tel);
printf("请输入住址\n"); scanf("%s", s1.addr);
printf("请输入年龄\n"); scanf("%d", &s1.age);
for (int i = data->size; i >= 1; i--)
{
data->data[i] = data->data[i - 1];//将有效数据向后移动一位
}
data->data[0] = s1;//将输入好的联系人复制到数据结构中
data->size += 1;
}
//在最后面添加数据
void AddBack(SQL* data, TYPE_MEMBER n)
{
DataExpand(data);//先判断是否要扩容
TYPE_MEMBER s1 = { 0 };
printf("请输入名字\n"); scanf("%s", s1.name);
printf("请输入性别\n"); scanf("%s", s1.gander);
printf("请输入电话\n"); scanf("%s", s1.tel);
printf("请输入住址\n"); scanf("%s", s1.addr);
printf("请输入年龄\n"); scanf("%d", &s1.age);
data->data[data->size] = s1;
data->size += 1;
}
//在有效据内任意点插入数据
void AddAnywhere(SQL* data)
{
DataExpand(data);//先判断是否要扩容
int size;
printf("请输入你要添加的位置\n"); scanf("%d", &size);
if (size > 0 && size <= data->size)
{
for (int i = data->size; i >= size; i--)
{
data->data[i] = data->data[i - 1];//将有效数据向后移动一位
}
TYPE_MEMBER s1 = { 0 };
printf("请输入名字\n"); scanf("%s", s1.name);
printf("请输入性别\n"); scanf("%s", s1.gander);
printf("请输入电话\n"); scanf("%s", s1.tel);
printf("请输入住址\n"); scanf("%s", s1.addr);
printf("请输入年龄\n"); scanf("%d", &s1.age);
data->data[size - 1] = s1;
data->size += 1;
}
else
printf("位置错误\n");
}
//在有效数据点内任意位置删除数据
void DeleteAnywhere(SQL* data)
{
assert(data->data);
int size;
printf("请输入你要删除的位置\n"); scanf("%d", &size);
if (size > 0 && size <= data->size)
{
for (int i = size - 1; i < data->size - 1; i++)
{
data->data[i] = data->data[i + 1];//将该点后的有效数据向前移动一位
}
data->size -= 1;
}
else
printf("位置错误\n");
}
//打印数据
void ShowData(SQL* data)
{
int i;
printf("姓名 性别 电话 住址 年龄\n");
for (i = 0; i < data->size; i++)
{
printf("%s %s %s %s %d\n",
data->data[i].name, data->data[i].gander, data->data[i].tel, data->data[i].addr, data->data[i].age);
}
printf("\n");
}
//查找数据
int FindData(SQL* data)
{
int i;
char name[20];
printf("请输入你要查找的名字\n"); scanf("%s", name);
for (i = 0; i < data->size; i++)
{
if (strcmp(name, data->data[i]) == 0)
{
printf("找到了,它的下标是%d\n", i);
return i;
}
}
printf("没找到\n");
return 0;
}
数据结构应用非常广泛,而且难度也开始逐渐上升了,不过我们还是要保持平静、乐观的心态去学习。欲速则不达,行稳才能致远。