初阶数据结构.1.顺序表.通讯录项目(只有源码和注释)

动态顺序表

SeqLest.c

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 
#include "SeqList.h"

// #2.1.顺序表初始化
void SLInit(SL* ps)
{
	// ·1.判断传址不为空
	assert(ps); // 调用assert.h
	// ·2.将数组指针初始化
	ps->arr = NULL; // 调用stdio.h
	// ·3.将整形初始化
	ps->size = 0;
	ps->capacity = 0;
}

// #2.2.顺序表的销毁
void SLDestroy(SL* ps)
{
	assert(ps);
	// ·1.确认数组指针指向不为空,后释放开辟的动态内存
	if (ps->arr)
	{
		free(ps->arr);
	}
	// ·2.释放空间后全部清零
	ps->arr = NULL; 
	ps->size = 0;
	ps->capacity = 0;
}

static void SLCheckCapacity(SL* ps);

// #2.3.尾部插入
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(ps);// 检查函数
	//·2.尾插
	ps->arr[ps->size++] = x;
}

// #2.3.分装出来的内存检查函数
static void SLCheckCapacity(SL* ps)
{
	// ·1.判断空间是否足够
	if (ps->size == ps->capacity)// 空间不足时,拓宽空间
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType)); // 调用stdlib.h
		if (tmp == NULL)// 开辟失败报错
		{
			perror("realloc fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}

// #2.4.头部插入
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	// ·1.数据从头开始后移一位
	// 由后向前
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];// arr[size] = arr[size - 1]
									// arr[1] = arr[0];
	}
	ps->arr[0] = x;
	ps->size++;
}

// #2.5.打印整个数组
void SLPrint(SL s)
{
	for (int i = 0; i < s.size; i++)
	{
		printf("%d ", s.arr[i]);
	}
	printf("\n");
}

// #2.7.尾部删除
void SLPopBack(SL* ps)
{
	assert(ps);
	//·1.判断顺序表不能为空,实际存在元素不能为0
	assert(ps->size);
	ps->size--;
}

// #2.8.头部删除
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	// ·1.整体前移一位
	// 由前向后
	for (int i = 0; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1]; // arr[0] = arr[1]
								     // arr[size-2] = arr[size-1]
	}
	ps->size--;
}

// #2.9.指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	// ·1.指定位置数据加后方数据整体后移一位
	// 由后向前
	for (int i = ps->size; i > pos ; i--)
	{
		ps->arr[i] = ps->arr[i - 1]; // arr[size] = arr[size - 1]
									 // arr[pos + 1] = arr[pos]
	}
	ps->arr[pos] = x;
	ps->size++;
}

// #2.10.指定位置删除
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	// ·1.指定位置数据加后方数据整体前移一位
	// 由前向后
	for (int i = pos ; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1]; // arr[pos] = arr[pos+1]
									 // arr[size-2] = arr[size-1]
	}
	ps->size--;
}

// #2.12.查找
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		// 成功找到返回下标
		if (ps->arr[i] == x)
		{
			return i;
		}
	}
	// 没有找到返回-1
	return -1;
}

SeqLest.h

cpp 复制代码
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
// #1. 创建动态顺序表结构体
// 数据结构中,开辟元素类型可以任意。将类型重命名有利于后期修改
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* arr;
	int size; // 现有元素个数
	int capacity; // 开辟空间大小所能存下的元素个数
}SL;

// #2.实现串口函数功能

// #2.1.顺序表初始化
void SLInit(SL* ps);
// #2.2.顺序表的销毁
void SLDestroy(SL* ps);
// #2.3.尾部插入
void SLPushBack(SL* ps, SLDataType x);
// #2.4.头部插入
void SLPushFront(SL* ps, SLDataType x);
// #2.5.打印整个数组
void SLPrint(SL s);

// #2.6.测试以上串口函数

// #2.7.尾部删除
void SLPopBack(SL* ps);
// #2.8.头部删除
void SLPopFront(SL* ps);

// #2.8.测试删除串口函数

// #2.9.指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x);
// #2.10.指定位置删除
void SLErase(SL* ps, int pos);

// #2.11.测试指定函数

// #2.12.查找
int SLFind(SL* ps, SLDataType x);

// #2.13.测试查找

动态顺序表测试 Test.c

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 
#include "SeqList.h"

// #2.6.测试
void Test01(void)
{
	SL s1;
	SLInit(&s1);

	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPrint(s1);

	SLPushFront(&s1, 5);
	SLPushFront(&s1, 6);
	SLPrint(s1);

	SLDestroy(&s1);
 
}

// #2.8.测试
void Test02(void)
{
	SL s1;
	SLInit(&s1);

	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushFront(&s1, 5);
	SLPushFront(&s1, 6);
	SLPopBack(&s1);
	SLPopFront(&s1);
	SLPrint(s1);

	SLDestroy(&s1);
}

// #2.11.测试
void Test03(void)
{
	SL s1;
	SLInit(&s1);

	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4);
	SLPushBack(&s1, 5);
	SLInsert(&s1, 3, 88);
	SLPrint(s1);

	SLErase(&s1, 2);
	SLPrint(s1);

	SLDestroy(&s1);
}

// #2.13.测试
void Test04(void)
{
	SL s1;
	SLInit(&s1);

	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4);
	SLPushBack(&s1, 5);
	int ret1 = SLFind(&s1, 3);
	if (ret1 == -1)
	{
		printf("没有找到\n");
	}
	else
	{
		printf("找到了下标是%d\n", ret1);
	}

	int ret2 = SLFind(&s1, 10);
	if (ret2 == -1)
	{
		printf("没有找到\n");
	}
	else
	{
		printf("找到了下标是%d\n", ret2);
	}

	SLDestroy(&s1);
}


int main()
{
//	Test01();
//	Test02();
//	Test03();
	
	Test04();
	return 0;
}

通讯录项目

通讯录本质就是顺序表,于上方顺序表不同点在于,一个是int 一个是struct

Seqlest.c

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 
#include "SeqList.h"

// #2.1.顺序表初始化
void SLInit(SL* ps)
{
	// ·1.判断传址不为空
	assert(ps); // 调用assert.h
	// ·2.将数组指针初始化
	ps->arr = NULL; // 调用stdio.h
	// ·3.将整形初始化
	ps->size = 0;
	ps->capacity = 0;
}

// #2.2.顺序表的销毁
void SLDestroy(SL* ps)
{
	assert(ps);
	// ·1.确认数组指针指向不为空,后释放开辟的动态内存
	if (ps->arr)
	{
		free(ps->arr);
	}
	// ·2.释放空间后全部清零
	ps->arr = NULL; 
	ps->size = 0;
	ps->capacity = 0;
}

static void SLCheckCapacity(SL* ps);

// #2.3.尾部插入
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(ps);// 检查函数
	//·2.尾插
	ps->arr[ps->size++] = x;
}

// #2.3.分装出来的内存检查函数
static void SLCheckCapacity(SL* ps)
{
	// ·1.判断空间是否足够
	if (ps->size == ps->capacity)// 空间不足时,拓宽空间
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType)); // 调用stdlib.h
		if (tmp == NULL)// 开辟失败报错
		{
			perror("realloc fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}

// #2.4.头部插入
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	// ·1.数据从头开始后移一位
	// 由后向前
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];// arr[size] = arr[size - 1]
									// arr[1] = arr[0];
	}
	ps->arr[0] = x;
	ps->size++;
}

// #2.5.打印整个数组
//void SLPrint(SL s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}

// #2.7.尾部删除
void SLPopBack(SL* ps)
{
	assert(ps);
	//·1.判断顺序表不能为空,实际存在元素不能为0
	assert(ps->size);
	ps->size--;
}

// #2.8.头部删除
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	// ·1.整体前移一位
	// 由前向后
	for (int i = 0; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1]; // arr[0] = arr[1]
								     // arr[size-2] = arr[size-1]
	}
	ps->size--;
}

// #2.9.指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	// ·1.指定位置数据加后方数据整体后移一位
	// 由后向前
	for (int i = ps->size; i > pos ; i--)
	{
		ps->arr[i] = ps->arr[i - 1]; // arr[size] = arr[size - 1]
									 // arr[pos + 1] = arr[pos]
	}
	ps->arr[pos] = x;
	ps->size++;
}

// #2.10.指定位置删除
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	// ·1.指定位置数据加后方数据整体前移一位
	// 由前向后
	for (int i = pos ; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1]; // arr[pos] = arr[pos+1]
									 // arr[size-2] = arr[size-1]
	}
	ps->size--;
}

// #2.12.查找
//int SLFind(SL* ps, SLDataType x)
//{
//	assert(ps);
//	int i = 0;
//	for (i = 0; i < ps->size; i++)
//	{
//		// 成功找到返回下标
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	// 没有找到返回-1
//	return -1;
//}

Seqlest.h

cpp 复制代码
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "Contact.h"
// #1. 创建动态顺序表结构体
// 数据结构中,开辟元素类型可以任意。将类型重命名有利于后期修改
typedef PeoInfo SLDataType;

typedef struct SeqList
{
	SLDataType* arr;
	int size; // 现有元素个数
	int capacity; // 开辟空间大小所能存下的元素个数
}SL;

// #2.实现串口函数功能

// #2.1.顺序表初始化
void SLInit(SL* ps);
// #2.2.顺序表的销毁
void SLDestroy(SL* ps);
// #2.3.尾部插入
void SLPushBack(SL* ps, SLDataType x);
// #2.4.头部插入
void SLPushFront(SL* ps, SLDataType x);
// #2.5.打印整个数组
void SLPrint(SL s);

// #2.6.测试以上串口函数

// #2.7.尾部删除
void SLPopBack(SL* ps);
// #2.8.头部删除
void SLPopFront(SL* ps);

// #2.8.测试删除串口函数

// #2.9.指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x);
// #2.10.指定位置删除
void SLErase(SL* ps, int pos);

// #2.11.测试指定函数

// #2.12.查找
int SLFind(SL* ps, SLDataType x);

// #2.13.测试查找

Contact.h

cpp 复制代码
#pragma once
#include <string.h>

// #3.1.创建通讯录结构体类型,将顺序表中类型更改
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100

typedef struct PersonInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

// #3.2.声明属性表结构体更名
typedef struct SeqList Contact;

// #4.实现通讯录功能的串口函数
// #4.1.通讯录的初始化
void ContactInit(Contact* con);
// #4.2.通讯录的销毁
void ContactDesTroy(Contact* con);
// #4.3.通讯录添加数据
void ContactAdd(Contact* con);
// #4.4.展示通讯录数据
void ContactShow(Contact* con);

// #4.5.测试

// #4.6.通讯录删除数据
void ContactDel(Contact* con);

// #4.7.测试

// #4.8.通讯录的修改
void ContactModify(Contact* con);

// #4.9.测试
 
// #4.10.通讯录查找
void A_ContactFind(Contact* con);

// #4.10.测试

Contact.c

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 
#include "Contact.h"
#include "SeqList.h"

// #4.1.通讯录的初始化
void ContactInit(Contact* con)
{
	SLInit(con);
}

// #4.2.通讯录的销毁
void ContactDesTroy(Contact* con)
{
	SLDestroy(con);
}

// #4.3.通讯录添加数据
void ContactAdd(Contact* con)
{
	assert(con);
	// ·1.创建一个暂存数据点
	PeoInfo tmp;

	printf("请输入联系人的姓名\n");
	scanf("%s", tmp.name);

	printf("请输入联系人的性别\n");
	scanf("%s", tmp.gender);

	printf("请输入联系人的年龄\n");
	scanf("%d", &tmp.age);

	printf("请输入联系人的电话\n");
	scanf("%s", tmp.tel);

	printf("请输入联系人的地址\n");
	scanf("%s", tmp.addr);

	// ·2.头插尾插任选一种
	SLPushBack(con,tmp);
}

// #4.4.展示通讯录数据
void ContactShow(Contact* con)
{
	assert(con);
	//表头:姓名  性别 年龄 电话  地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%s %s %d %s %s\n", con->arr[i].name,
								con->arr[i].gender,
								con->arr[i].age,
								con->arr[i].tel,
								con->arr[i].addr);
	}
}

int ContactFind(Contact* con, char name[NAME_MAX]);

// #4.6.通讯录删除数据
void ContactDel(Contact* con)
{
	assert(con);
	// ·1.查询
	char name[NAME_MAX];
	printf("请输入要删除联系人的姓名\n");
	scanf("%s", name);
	
	int find = ContactFind(con, name);
	if (find < 0)
	{
		printf("删除的联系人不存在\n");
		exit(1);
	}
	SLErase(con, find);
	printf("删除成功\n");
}
// #4.6.分装出来的查找函数
int ContactFind(Contact* con, char name[NAME_MAX])
{
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

// #4.8.通讯录的修改
void ContactModify(Contact* con)
{
	assert(con);
	
	char name[NAME_MAX];
	printf("请输入你要修改的联系人姓名\n");
	scanf("%s", name);

	int find = ContactFind(con, name);
	if (find < 0)
	{
		printf("你要修改的联系人不存在\n");
		exit(1);
	}
	
	printf("请输入你要修改的姓名\n");
	scanf("%s", con->arr[find].name);

	printf("请输入你要修改的性别\n");
	scanf("%s", con->arr[find].gender);

	printf("请输入你要修改的年龄\n");
	scanf("%d", &con->arr[find].age);

	printf("请输入你要修改的电话\n");
	scanf("%s", con->arr[find].tel);

	printf("请输入你要修改的地址\n");
	scanf("%s", con->arr[find].addr);

	printf("修改成功\n");
}

// #4.10.通讯录查找
void A_ContactFind(Contact* con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名\n");
	scanf("%s", name);

	int find = ContactFind(con, name);
	if (find < 0)
	{
		printf("你要查找的联系人不存在\n");
		exit(1);
	}

	printf("%s %s %s %s %s \n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%s %s %d %s %s \n", con->arr[find].name, con->arr[find].gender, con->arr[find].age, con->arr[find].tel, con->arr[find].addr);
}

通讯录测试文件 Test.c

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 
#include "SeqList.h"

// #2.6.测试
//void Test01(void)
//{
//	SL s1;
//	SLInit(&s1);
//
//	SLPushBack(&s1, 1);
//	SLPushBack(&s1, 2);
//	SLPushBack(&s1, 3);
//	SLPrint(s1);
//
//	SLPushFront(&s1, 5);
//	SLPushFront(&s1, 6);
//	SLPrint(s1);
//
//	SLDestroy(&s1);
// 
//}

// #2.8.测试
//void Test02(void)
//{
//	SL s1;
//	SLInit(&s1);
//
//	SLPushBack(&s1, 1);
//	SLPushBack(&s1, 2);
//	SLPushBack(&s1, 3);
//	SLPushFront(&s1, 5);
//	SLPushFront(&s1, 6);
//	SLPopBack(&s1);
//	SLPopFront(&s1);
//	SLPrint(s1);
//
//	SLDestroy(&s1);
//}

// #2.11.测试
//void Test03(void)
//{
//	SL s1;
//	SLInit(&s1);
//
//	SLPushBack(&s1, 1);
//	SLPushBack(&s1, 2);
//	SLPushBack(&s1, 3);
//	SLPushBack(&s1, 4);
//	SLPushBack(&s1, 5);
//	SLInsert(&s1, 3, 88);
//	SLPrint(s1);
//
//	SLErase(&s1, 2);
//	SLPrint(s1);
//
//	SLDestroy(&s1);
//}

// #2.13.测试
//void Test04(void)
//{
//	SL s1;
//	SLInit(&s1);
//
//	SLPushBack(&s1, 1);
//	SLPushBack(&s1, 2);
//	SLPushBack(&s1, 3);
//	SLPushBack(&s1, 4);
//	SLPushBack(&s1, 5);
//	int ret1 = SLFind(&s1, 3);
//	if (ret1 == -1)
//	{
//		printf("没有找到\n");
//	}
//	else
//	{
//		printf("找到了下标是%d\n", ret1);
//	}
//
//	int ret2 = SLFind(&s1, 10);
//	if (ret2 == -1)
//	{
//		printf("没有找到\n");
//	}
//	else
//	{
//		printf("找到了下标是%d\n", ret2);
//	}
//
//	SLDestroy(&s1);
//}

// #4.5.测试
void Test05()
{
	Contact con;
	ContactInit(&con);
	ContactAdd(&con);
	ContactShow(&con);
	ContactDesTroy(&con);
}

// #4.7.测试
void Test06()
{
	Contact con;
	ContactInit(&con);

	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	ContactShow(&con);

	ContactDel(&con);
	ContactShow(&con);

	ContactDesTroy(&con);
}

// #4.9.测试
void Test07()
{
	Contact con;
	ContactInit(&con);

	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	ContactShow(&con);

	ContactModify(&con);
	ContactShow(&con);

	ContactDesTroy(&con);
}


// #4.10.测试
void Test08()
{
	Contact con;
	ContactInit(&con);

	ContactAdd(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	A_ContactFind(&con);

	ContactDesTroy(&con);
}


int main()
{
//	Test01();
//	Test02();
//	Test03();
// 	Test04();
//	Test05();
//	Test06();
//	Test07();
	Test08();
	return 0;
}
相关推荐
Emilia486.9 小时前
八大排序算法
算法·排序算法
blammmp9 小时前
算法专题十九:记忆化搜索(暴搜->记忆化搜索)
算法·深度优先·记忆化搜索
MicroTech202510 小时前
边缘智能的创新:MLGO微算法科技推出基于QoS感知的边缘大模型自适应拆分推理编排技术
科技·算法·ai
王哈哈^_^11 小时前
【数据集】【YOLO】目标检测游泳数据集 4481 张,溺水数据集,YOLO河道、海滩游泳识别算法实战训练教程。
人工智能·算法·yolo·目标检测·计算机视觉·分类·视觉检测
巴里巴气12 小时前
第73题 矩阵置零
线性代数·算法·矩阵
voice67012 小时前
密码学实验二
算法·密码学·哈希算法
Blossom.11813 小时前
把AI“编”进草垫:1KB决策树让宠物垫自己报「如厕记录」
java·人工智能·python·算法·决策树·机器学习·宠物
寂静山林13 小时前
UVa 10989 Bomb Divide and Conquer
算法
兮山与14 小时前
算法23.0
算法