学习前提: 了解结构体,指针
学习目的:能利用顺序表实现类似通讯录的功能
数据结构:顾名思义就是数据+结构,一些数据按一定的结构管理起来,便于对数据的管理。
回顾所学我们知道我们学过的数组就是一种能够通过下标来管理储存数据。
第一个数据结构:顺序表
顺序表:其实底层逻辑就是数组,但优于数组(eg:在插入数据时不用遍历数组只需在指定位置插入即可,在增加数据时可以动态开辟空间不浪费空间)
顺序表的分类:静态顺序表,动态顺序表
静态顺序表定义:底层数组长度确定
struct SeqList {
int arr[100];//定义一个定长数组
int size;//代表数组已经使用多少
};
动态顺序表定义:底层数组长度不确定需要动态开辟
struct SeqList {
int* arr;//动态数组
int size;//记录有效数据
int capacity;//记录整个空间大小
};
总结:动态顺序表能根据需求动态开辟空间,相比静态顺序表来说可以更加节约空间,所以我们更倾向于使用动态顺序表.
先利用顺序表实现增删查改的功能:(注意:完整代码请看最后边)
项目开始首先创建一个头文件(SeqList.h),一个实现文件(SeqList.c),一个测试文件(test.c)
在SeqList.h文件中先定义一个动态顺序表结构:
//定义一个动态顺序表结构
struct SeqList {
int* arr;
int size;//有效数据的个数
int capacity;//空间大小
};
由于动态数组不一定存储整形数据,所以我们加以改变
//定义一个动态顺序表结构
typedef int SeqDataType;
typedef struct SeqList {
SeqDataType* arr;
int size;//有效数据的个数
int capacity;//空间大小
}SL;
初始化顺序表关键代码:
//初始化
void Init(SL* ps) {
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
尾插数据关键代码:
//申请结点
void SlCheckCap(SL* ps) {
if (ps->capacity == ps->size) {
int Newcapcity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tem = (SLDataType*)realloc(ps->arr, Newcapcity * sizeof(SLDataType));
ps->arr = tem;
ps->capacity = Newcapcity;
}
}
//尾插
void SeqPushBack(SL* ps, SLDataType x) {
assert(ps);
SlCheckCap(ps);
ps->arr[ps->size++] = x;
}
头插关键代码:
//头插
void SeqPushFrond(SL* ps, SLDataType x) {
assert(ps);
SlCheckCap(ps);
for (int i = ps->size - 1; i >= 0; i--) {
ps->arr[i+1] = ps->arr[i];
}
ps->arr[0] = x;
ps->size++;
}
尾删关键代码:
//尾删
void SeqDelBack(SL* ps) {
assert(ps);
ps->size--;
}
头删关键代码:
//头删
void SeqDelFrond(SL* ps) {
assert(ps);
for (int i = 0; i < ps->size; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
在指定位置插入数据:
//指定位置插入数据
void SeqInsert(SL* ps, int pos, SLDataType x) {
assert(ps);
SlCheckCap(ps);
for (int i = ps->size; i > pos; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
在指定位置删除数据:
//在指定位置删除数据
void SeqDel(SL* ps, int pos) {
assert(ps);
for (int i = pos; i < ps->size; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
查找数据:
//查找数据
int SeqFind(SL* ps, SLDataType x) {
assert(ps);
for (int i = 0; i < ps->size; i++) {
if (ps->arr[i] == x) {
return i;
}
}
return -1;
}
顺序表销毁:
//顺序表销毁
void SeqDestory(SL* ps) {
if (ps->arr) {
free(ps->arr);
}
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
完整代码
SeqLish.h文件内容
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//顺序表定义
typedef int SLDataType;
typedef struct SeqList {
SLDataType* arr;
int size;
int capacity;
}SL;
//顺序表的初始化
void Init(SL* ps);
//尾插
void SeqPushBack(SL* ps, SLDataType x);
//头插
void SeqPushFrond(SL* ps, SLDataType x);
//尾删
void SeqDelBack(SL* ps);
//头删
void SeqDelFrond(SL* ps);
//指定位置插入数据
void SeqInsert(SL* ps, int pos, SLDataType x);
//在指定位置删除数据
void SeqDel(SL* ps, int pos);
//查找数据
int SeqFind(SL* ps, SLDataType x);
//打印
void Print(SL ps);
//顺序表销毁
void SeqDestory(SL* ps);
SeqList.c文件内容
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//初始化
void Init(SL* ps) {
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
//申请结点
void SlCheckCap(SL* ps) {
if (ps->capacity == ps->size) {
int Newcapcity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tem = (SLDataType*)realloc(ps->arr, Newcapcity * sizeof(SLDataType));
ps->arr = tem;
ps->capacity = Newcapcity;
}
}
//尾插
void SeqPushBack(SL* ps, SLDataType x) {
assert(ps);
SlCheckCap(ps);
ps->arr[ps->size++] = x;
}
//头插
void SeqPushFrond(SL* ps, SLDataType x) {
assert(ps);
SlCheckCap(ps);
for (int i = ps->size - 1; i >= 0; i--) {
ps->arr[i+1] = ps->arr[i];
}
ps->arr[0] = x;
ps->size++;
}
//尾删
void SeqDelBack(SL* ps) {
assert(ps);
ps->size--;
}
//头删
void SeqDelFrond(SL* ps) {
assert(ps);
for (int i = 0; i < ps->size; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//指定位置插入数据
void SeqInsert(SL* ps, int pos, SLDataType x) {
assert(ps);
SlCheckCap(ps);
for (int i = ps->size; i > pos; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
//在指定位置删除数据
void SeqDel(SL* ps, int pos) {
assert(ps);
for (int i = pos; i < ps->size; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//查找数据
int SeqFind(SL* ps, SLDataType x) {
assert(ps);
for (int i = 0; i < ps->size; i++) {
if (ps->arr[i] == x) {
return i;
}
}
return -1;
}
//打印
void Print(SL ps) {
for (int i = 0; i < ps.size; i++) {
printf("%d ", ps.arr[i]);
}
printf("\n");
}
//顺序表销毁
void SeqDestory(SL* ps) {
if (ps->arr) {
free(ps->arr);
}
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
test.c文件内容
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void test01() {
//创建对象
SL sl;
//初始化
Init(&sl);
//尾插
SeqPushBack(&sl, 1);
SeqPushBack(&sl, 2);
SeqPushBack(&sl, 3);
SeqPushBack(&sl, 4);
Print(sl);
//头插入
SeqPushFrond(&sl, 6);
Print(sl);
SeqPushFrond(&sl, 7);
Print(sl);
SeqPushFrond(&sl, 8);
Print(sl);
SeqPushFrond(&sl, 9);
Print(sl);
//尾删
SeqDelBack(&sl);
Print(sl);
SeqDelBack(&sl);
Print(sl);
//头删
SeqDelFrond(&sl);
Print(sl);
SeqDelFrond(&sl);
Print(sl);
//指定位置插入
SeqInsert(&sl,3, 10);
Print(sl);
SeqInsert(&sl, 2, 11);
Print(sl);
//在指定位置删除数据
SeqDel(&sl, 1);
Print(sl);
SeqDel(&sl, 3);
Print(sl);
//查找数据
int pos = SeqFind(&sl,2);
if (pos<0) {
printf("没找到\n");
}
else {
printf("找到了,所在下标为:%d\n",pos);
}
//销毁
SeqDestory(&sl);
}
int main() {
test01();
}
注意:
本代码并不是很完善请各位大神指点,后续通讯录的实现在此基础上会加以实现。