C语言手撕通讯录(静态、动态双版本)——万字实战详解

简介: 正片开始👀这里为了方便对照,我搬出整个程序的前后修改版本,并分别作为静态和动态版本,实际差距并不大,提供出来只供君参考🤔🤔动机🤔🤔为什么要写一个通讯录?

正片开始👀

这里为了方便对照,我搬出整个程序的前后修改版本,并分别作为静态和动态版本,实际差距并不大,提供出来只供君参考


🤔🤔动机🤔🤔


为什么要写一个通讯录?

1.当然是一部分原因是看了b站上的资源自己比较感兴趣


2.其次就是在C语言实际应用上可以深化和巩固,其实都看得出来我中间断更了好久的数据结构与算法的博客,主要想法还是想把C语言从里到外不遗余力的杀穿,又走了一遍底层原理,不过我相信费时是值得的


3.在学习数据结构和算法这板块,需要C语言基础高度的掌握,所以这部分算对前边理论部分的一个实战项目,数据结构数据结构,无非就是数据的增删查改,这里我们提前热身一下也不错。


静态版本👏

头文件( phonebook.h)

我们这里依旧使用之前写扫雷的分装思想,将这个通讯录分为 头文件,接口,功能三个部分。


首先我们写出头文件,就是我们需要用到什么,给他整出来,我们简单粗暴给命名为“ phonebook.h ”,展示为下面三个部分:

#pragma once
# define _CRT_SECURE_NO_WARNINGS 
# include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define max 1000
#define x 30
#define y 30
#define z 20
typedef struct num
{
  char name[x];
  int age;
  char sex[y];
  char addr[y];
  char num[z];
}num;
typedef struct book
{
  num data[max];
  int count;
}book;
enum conmenu
{
  退出,
  增添,
  删减,
  查找,
  修改,
  排序,
  全览,
};
void start(book* p); //初始化通讯录
void add(book* p);//增添信息
void show(const book* p);//展示信息
void delete(book* p);//删除信息
int search(book* p,char name[]);//库中搜寻要查找信息
void find(book* p);//查找信息
void modify(book* p);//修改信息
void sort(book* p);//排序信息

整个一坨掰成三瓣就是为了方便理解,从上到下分别是菜单(展示必要),自定义类型变量(结构体,枚举类型),需要实现的功能函数名。


为什么结构体变量有两个,book结构体是我们整个通讯录的骨骼,包含count(成员数量)和data(成员数据),这里就相当于模拟了一个数组出来,更方便管理; num 结构体则是存放各个成员数据的细节成分(姓名,年龄,性别……)。


接口(test.c)

设置接口的目的就相当于是设置了一个大门,就是一个统揽全局的作用,我们把菜单,和功能模块在这里作展示作用,代码的实现我们会放在功能板块实现。

#include"phonebook.h"
void menu()
{
  printf("-----------------------------\n");
  printf("----    欢迎使用通讯录   ----\n");
  printf("-----------------------------\n");
  printf("----- 1.增添  |   2.删减-----\n");
  printf("----- 3.查找  |   4.修改-----\n");
  printf("----- 5.排序  |   6.全览-----\n");
  printf("-----       0.退出      -----\n");
  printf("-----------------------------\n");
}
int main()
{
  int input;
  book con;
  start(&con);
  do
  { 
    menu();
    printf("请选择:\n");
    scanf("%d", &input);
    switch (input)
    {
    case 增添:
      add(&con);
      break;
    case 删减:
      delete(&con);
      break;
    case 查找:
      find(&con);
      break;
    case 修改:
      modify(&con);
      break;
    case 排序:
      sort(&con);
      break;
    case 全览:
      show(&con);
      break;
    case 退出:
      break;
    default:
      printf("錯誤输入!\n");
      return 0;
    }
  } while (input);
  return 0;
}     

抛开菜单部分,do-while 语句就是对应了菜单给出的功能遥控器,需要什么点什么。


为什么我们需要一个枚举类型,其原因就是为了对应上面菜单中的功能(枚举类型成员在未赋值情况下,第一个成员默认值为 0 ,其下依次递增,从而实现一一对应),我们作为设计者,主要是为了方便我们自己写代码,switch-case 语句中,case 条件我们一眼瞄过去如果是 1,2,3 的数字,我们在完善时就可能云里雾里,还要去查目录,就很麻烦,所以我们用枚举类型来避免这种小尴尬。


功能板块(phonebook.c)

我们在通讯录中需要达到的目的有基本的增删查改,以及作为称得上完美通讯录的全览,排序和退出,下面我们 一 一 实现:


1. 初始化:

void start(book* p)
{
  assert(p);
  p->count = 0;
  memset(p->data, 0, sizeof(p->data));
}

初识化首先就要避免空指针和随机数,所以这里安排一手 assert 和 置0 就够了。

2. 增添

void add(book* p)
{
  assert(p);
  if (p->count == max)
  {
    printf("已满,请先进行删除\n");
    return;
  }
  else
  {
    printf("请输入姓名:");
    scanf("%s", p->data[p->count].name);
    printf("请输入年龄:");
    scanf("%d", &(p->data[p->count].age));
    printf("请输入性别(F\\M):");
    scanf("%s", p->data[p->count].sex);
    printf("请输入地址:");
    scanf("%s", p->data[p->count].addr);
    printf("请输入电话:");
    scanf("%s", p->data[p->count].num);
    p->count++;
    printf("\n增添成功!\n");
  }
}

增添数据我们要对应好结构体中的类型,因为年龄比较特殊,它是 %d 的形式,输入类型不是字符串,所以我们要进行取地址操作

3.查找

void find(book* p)
{
  assert(p);
  if (p->count == 0)
    printf("\n目录为空!\n");
  else
  {
    char name[max] = { 0 };
    printf("请输入查找对象:\n");
    scanf("%s", &name);
    int i = search(p, name);
    if (i != -1)
    {
      printf("联系人存在,在第%d位\n", i + 1);
    }
    else
    {
      printf("联系人不存在!\n");
    }
  }
}

注意在开始要判断一下现在通讯录状态是否为空,空就无法查找,注意要在库中寻找我们的查找对象,我们还要需要一个对信息进行筛选比对的函数来找出该对象,因此我们引入 search 函数:

int search(book* p, char name[])
{
  for (int i = 0; i < p->count; i++)
  {
    if (strcmp(name , p->data[i].name)==0)
    {
      return i;
    }
    else
    {
      return -1;
    }
  }
}

4.删除

void delete(book* p)
{
  assert(p);
  if (p->count == 0)
  {
    printf("\n为空,无法删除!\n");
    return;
  }
  else
  {
    printf("请输入删除对象:\n");
    char name[max] = {0};
    scanf("%s", &name);
    int f = search(p,name);
    if (f == -1)
    {
      printf("该对象不存在!\n");
    }
    else
    {
      for (int j = f; j < p->count-1; j++)
      {
        p->data[j] = p->data[j + 1];
      }
      p->count--;
      printf("\n删除成功!\n");
    }
  }
}

注意在开始要判断一下现在通讯录状态是否为空,空就无法删除;确定不为空再找到删除对象,我们所谓的删除本质就是用后面的数据进行依次覆盖,最后让数组大小 count -1 即可。

5.修改

void modify(book* p)
{
  assert(p);
  if (p->count == 0)
  {
    printf("为空,无法删除!\n");
    return;
  }
  else
  {
    printf("请输入对象姓名:\n");
    char name[max] = { 0 };
    scanf("%s", &name);
    int i = search(p,name);
    if(i!=-1)
    {
      printf("该对象存在\n");
      printf("请输入修改内容:\n");
      printf("请输入姓名:\n");
      scanf("%s", p->data[i].name);
      printf("请输入年龄:\n");
      scanf("%d", &(p->data[p->count].age));
      printf("请输入性别(F\M):\n");
      scanf("%c", &(p->data[p->count].sex));
      printf("请输入地址:\n");
      scanf("%s", p->data[p->count].addr);
      printf("请输入电话:\n");
      scanf("%s", p->data[p->count].num);
      printf("\n修改成功!\n");
    }
    else
    {
      printf("该对象不存在!\n");
      return 0;
    }
  }
}

6.排序


int compare(const void* a, const void* b)
{
  return strcmp(((book*)a)->data->name , ((book*)b)->data->name);
}
int compare2(const void* a, const void* b)
{
  return strcmp(((book*)b)->data->name, ((book*)a)->data->name);
}
void sort(book* p)
{
  printf("请选择:\n");
  printf("-----------------------------\n");
  printf("----- 1.顺序  |   2.逆序-----\n");
  printf("-----------------------------\n");
  int in;
  scanf("%d", &in);
  switch (in)
  {
  case 1:
    qsort(p->data, p->count, sizeof(p->data[0]), compare);
  case 2:
    qsort(p->data, p->count, sizeof(p->data[0]), compare2);
  }
  printf("\n 排序完成!\n");
}

排序我细分为了顺序和逆序两种,基本思想就是 qsort 函数一步到胃,不再赘述。

7.全览

void show(book* p)
{
  assert(p);
  int i = 0;
  printf("%10s %5s %5s %10s %13s\n","姓名","年龄","性别","地址","电话");
  for (i = 0; i < p->count; i++)
  {
    printf("%10s %5d %5s %10s %13s\n", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].addr, p->data[i].num);
  }
}

就是全部打印出来即可,注意信息之间的间隔调整,读者可自主更改其大小。

到这里我们所有功能就算实现完了,来康康实际效果如何(仅展示其中几个):

image.png

image.png

静态版全部代码

为了方便读者查看与创作,我把三个部分的代码全部贴出来:

test.c(接口)

#include"phonebook.h"
void menu()
{
  printf("-----------------------------\n");
  printf("----    欢迎使用通讯录   ----\n");
  printf("-----------------------------\n");
  printf("----- 1.增添  |   2.删减-----\n");
  printf("----- 3.查找  |   4.修改-----\n");
  printf("----- 5.排序  |   6.全览-----\n");
  printf("-----       0.退出      -----\n");
  printf("-----------------------------\n");
}
int main()
{
  int input;
  book con;
  start(&con);
  do
  { 
    menu();
    printf("请选择:\n");
    scanf("%d", &input);
    switch (input)
    {
    case 增添:
      add(&con);
      break;
    case 删减:
      delete(&con);
      break;
    case 查找:
      find(&con);
      break;
    case 修改:
      fix(&con);
      break;
    case 排序:
      sort(&con);
      break;
    case 全览:
      show(&con);
      break;
    case 退出:
      break;
    default:
      printf("錯誤输入!\n");
      return 0;
    }
  } while (input);
  return 0;
}     

phonebook.h(头文件)

#pragma once
# define _CRT_SECURE_NO_WARNINGS 
# include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define max 1000
#define x 30
#define y 30
#define z 20
typedef struct num
{
  char name[x];
  int age;
  char sex[y];
  char addr[y];
  char num[z];
}num;
typedef struct book
{
  num data[max];
  int count;
  int capacity;
}book;
enum conmenu
{
  退出,
  增添,
  删减,
  查找,
  修改,
  排序,
  全览,
};
void start(book* p);
void add(book* p);
void show(const book* p);
void delete(book* p);
int search(book* p,char name[]);
void find(book* p);
void fix(book* p);
void sort(book* p);

phonebook.c(功能)

# define _CRT_SECURE_NO_WARNINGS 
#include"phonebook.h"
void start(book* p)
{
  assert(p);
  p->count = 0;
  memset(p->data, 0, sizeof(p->data));
}
void add(book* p)
{
  assert(p);
  if (p->count == max)
  {
    printf("已满,请先进行删除\n");
    return;
  }
  else
  {
    printf("请输入姓名:");
    scanf("%s", p->data[p->count].name);
    printf("请输入年龄:");
    scanf("%d", &(p->data[p->count].age));
    printf("请输入性别(F\\M):");
    scanf("%s", p->data[p->count].sex);
    printf("请输入地址:");
    scanf("%s", p->data[p->count].addr);
    printf("请输入电话:");
    scanf("%s", p->data[p->count].num);
    p->count++;
    printf("\n增添成功!\n");
  }
}
void show(book* p)
{
  assert(p);
  int i = 0;
  printf("%10s %5s %5s %10s %13s\n","姓名","年龄","性别","地址","电话");
  for (i = 0; i < p->count; i++)
  {
    printf("%10s %5d %5s %10s %13s\n", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].addr, p->data[i].num);
  }
}
int search(book* p, char name[])
{
  for (int i = 0; i < p->count; i++)
  {
    if (strcmp(name , p->data[i].name)==0)
    {
      return i;
    }
    else
    {
      return -1;
    }
  }
}
void delete(book* p)
{
  assert(p);
  if (p->count == 0)
  {
    printf("\n为空,无法删除!\n");
    return;
  }
  else
  {
    printf("请输入删除对象:\n");
    char name[max] = {0};
    scanf("%s", &name);
    int f = search(p,name);
    if (f == -1)
    {
      printf("该对象不存在!\n");
    }
    else
    {
      for (int j = f; j < p->count-1; j++)
      {
        p->data[j] = p->data[j + 1];
      }
      p->count--;
      printf("\n删除成功!\n");
    }
  }
}
void find(book* p)
{
  assert(p);
  if (p->count == 0)
    printf("\n目录为空!\n");
  else
  {
    char name[max] = { 0 };
    printf("请输入查找对象:\n");
    scanf("%s", &name);
    int i = search(p, name);
    if (i != -1)
    {
      printf("联系人存在,在第%d位\n", i + 1);
    }
    else
    {
      printf("联系人不存在!\n");
    }
  }
}
void fix(book* p)
{
  assert(p);
  if (p->count == 0)
  {
    printf("为空,无法删除!\n");
    return;
  }
  else
  {
    printf("请输入对象姓名:\n");
    char name[max] = { 0 };
    scanf("%s", &name);
    int i = search(p,name);
    if(i!=-1)
    {
      printf("该对象存在\n");
      printf("请输入修改内容:\n");
      printf("请输入姓名:\n");
      scanf("%s", p->data[i].name);
      printf("请输入年龄:\n");
      scanf("%d", &(p->data[p->count].age));
      printf("请输入性别(F\M):\n");
      scanf("%c", &(p->data[p->count].sex));
      printf("请输入地址:\n");
      scanf("%s", p->data[p->count].addr);
      printf("请输入电话:\n");
      scanf("%s", p->data[p->count].num);
      printf("\n修改成功!\n");
    }
    else
    {
      printf("该对象不存在!\n");
      return 0;
    }
  }
}
int compare(const void* a, const void* b)
{
  return strcmp(((book*)a)->data->name , ((book*)b)->data->name);
}
int compare2(const void* a, const void* b)
{
  return strcmp(((book*)b)->data->name, ((book*)a)->data->name);
}
void sort(book* p)
{
  printf("请选择:\n");
  printf("-----------------------------\n");
  printf("----- 1.顺序  |   2.逆序-----\n");
  printf("-----------------------------\n");
  int in;
  scanf("%d", &in);
  switch (in)
  {
  case 1:
    qsort(p->data, p->count, sizeof(p->data[0]), compare);
  case 2:
    qsort(p->data, p->count, sizeof(p->data[0]), compare2);
  }
  printf("\n 排序完成!\n");
}

动态版😎

动态版的区别就在于他的内存是活的,按需索取,要多少拿多少,绝不少给也绝不浪费空间,在空间上做出了质的优化,原理就是动态内存分配。

typedef struct book
{
  num data[max];
  int count;
  int capacity;
}book;

首先我们在 book 定义的结构体中引入一个 capacity 变量,意为容量,它就相当于一个空间使用的指标变量。

动态初始化:

void start(book* p)
{
  assert(p);
  num* container = (num*)malloc(DEFAULT * sizeof(num));
  if (container != NULL)
  {
    p->data = container;
    p->count = 0;
    p->capacity = DEFAULT;
  }
  else
  { 
    printf("%s\n", strerror(errno));
    return;
  }
}

重点是这里不再使用死板的数组,改用 malloc 函数先开辟一块默认大小,这个大小我们随意设置但避免浪费我们要尽量往小了设置。注意空指针,我们后面设置一个查看错误类型方便排空(注意引<errno.h>头文件) 。

扩容函数

则扩容的关键就在于我们的 capa_city 函数:

void capa_city(book* p)
{
  num* container = (num*)realloc(p->data, sizeof(book) * (p->capacity + 2));
  if (container != NULL)
  {
    p->data = container;
    p->capacity += 2 ;
    printf("增容成功!\n");
  }
  else
  {
    printf("%s\n", strerror(errno));
    return;
  }
}

我们为了体现空间利用的得当,我们每次扩容控制在 +2 数据空间即可。

接下来不用变动即可实现动态版本了,我直接上代码:

动态版全部代码

test.c

#include"phonebook.h"
void menu()
{
  printf("-----------------------------\n");
  printf("----    欢迎使用通讯录   ----\n");
  printf("-----------------------------\n");
  printf("----- 1.增添  |   2.删减-----\n");
  printf("----- 3.查找  |   4.修改-----\n");
  printf("----- 5.排序  |   6.全览-----\n");
  printf("-----       0.退出      -----\n");
  printf("-----------------------------\n");
}
int main()
{
  int input;
  book con;
  start(&con);
  do
  { 
    menu();
    printf("请选择:\n");
    scanf("%d", &input);
    switch (input)
    {
    case 增添:
      add(&con);
      break;
    case 删减:
      delete(&con);
      break;
    case 查找:
      find(&con);
      break;
    case 修改:
      fix(&con);
      break;
    case 排序:
      sort(&con);
      break;
    case 全览:
      show(&con);
      break;
    case 退出:
      break;
    default:
      printf("錯誤输入!\n");
      return 0;
    }
  } while (input);
  return 0;
}  

phonebook.h

#pragma once
# define _CRT_SECURE_NO_WARNINGS 
# include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#define max 1000
#define x 30
#define DEFAULT 50
#define z 20
typedef struct num
{
  char name[x];
  int age;
  char sex[x];
  char addr[x];
  char num[z];
}num;
typedef struct book
{
  num* data;
  int count;
  int capacity;
}book;
enum conmenu
{
  退出,
  增添,
  删减,
  查找,
  修改,
  排序,
  全览,
};
void start(book* p);
void add(book* p);
void show(const book* p);
void delete(book* p);
int search(book* p,char name[]);
void find(book* p);
void fix(book* p);
void sort(book* p);
void capa_city(book* p);

phonebook.c

# define _CRT_SECURE_NO_WARNINGS 
#include"phonebook.h"
void capa_city(book* p)
{
  num* container = (num*)realloc(p->data, sizeof(book) * (p->capacity + 2));
  if (container != NULL)
  {
    p->data = container;
    p->capacity += 2 ;
    printf("增容成功!\n");
  }
  else
  {
    printf("%s\n", strerror(errno));
    return;
  }
}
void start(book* p)
{
  assert(p);
  num* container = (num*)malloc(DEFAULT * sizeof(num));
  if (container != NULL)
  {
    p->data = container;
    p->count = 0;
    p->capacity = DEFAULT;
  }
  else
  { 
    printf("%s\n", strerror(errno));
    return;
  }
}
void add(book* p)
{
  if (p->capacity == p->count)
  {
    capa_city(p);
  }
  assert(p);
  if (p->count == max)
  {
    printf("已满,请先进行删除\n");
    return;
  }
  else
  {
    printf("请输入姓名:");
    scanf("%s", p->data[p->count].name);
    printf("请输入年龄:");
    scanf("%d", &(p->data[p->count].age));
    printf("请输入性别(F\\M):");
    scanf("%s", p->data[p->count].sex);
    printf("请输入地址:");
    scanf("%s", p->data[p->count].addr);
    printf("请输入电话:");
    scanf("%s", p->data[p->count].num);
    p->count++;
    printf("\n增添成功!\n");
  }
}
void show(book* p)
{
  assert(p);
  if (p->capacity == p->count)
  {
    capa_city(p);
  }
  int i = 0;
  printf("%10s %5s %5s %10s %13s\n","姓名","年龄","性别","地址","电话");
  for (i = 0; i < p->count; i++)
  {
    printf("%10s %5d %5s %10s %13s\n", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].addr, p->data[i].num);
  }
}
int search(book* p, char name[])
{
  for (int i = 0; i < p->count; i++)
  {
    if (strcmp(name , p->data[i].name)==0)
    {
      return i;
    }
    else
    {
      return -1;
    }
  }
}
void delete(book* p)
{
  assert(p);
  if (p->count == 0)
  {
    printf("\n为空,无法删除!\n");
    return;
  }
  else
  {
    printf("请输入删除对象:\n");
    char name[max] = {0};
    scanf("%s", &name);
    int f = search(p,name);
    if (f == -1)
    {
      printf("该对象不存在!\n");
    }
    else
    {
      for (int j = f; j < p->count-1; j++)
      {
        p->data[j] = p->data[j + 1];
      }
      p->count--;
      printf("\n删除成功!\n");
    }
  }
}
void find(book* p)
{
  assert(p);
  if (p->count == 0)
    printf("\n目录为空!\n");
  else
  {
    char name[max] = { 0 };
    printf("请输入查找对象:\n");
    scanf("%s", &name);
    int i = search(p, name);
    if (i != -1)
    {
      printf("联系人存在,在第%d位\n", i + 1);
    }
    else
    {
      printf("联系人不存在!\n");
    }
  }
}
void fix(book* p)
{
  assert(p);
  if (p->count == 0)
  {
    printf("为空,无法删除!\n");
    return;
  }
  else
  {
    printf("请输入对象姓名:\n");
    char name[max] = { 0 };
    scanf("%s", &name);
    int i = search(p,name);
    if(i!=-1)
    {
      printf("该对象存在\n");
      printf("请输入修改内容:\n");
      printf("请输入姓名:\n");
      scanf("%s", p->data[i].name);
      printf("请输入年龄:\n");
      scanf("%d", &(p->data[p->count].age));
      printf("请输入性别(F\M):\n");
      scanf("%c", &(p->data[p->count].sex));
      printf("请输入地址:\n");
      scanf("%s", p->data[p->count].addr);
      printf("请输入电话:\n");
      scanf("%s", p->data[p->count].num);
      printf("\n修改成功!\n");
    }
    else
    {
      printf("该对象不存在!\n");
      return 0;
    }
  }
}
int compare(const void* a, const void* b)
{
  return strcmp(((book*)a)->data->name , ((book*)b)->data->name);
}
int compare2(const void* a, const void* b)
{
  return strcmp(((book*)b)->data->name, ((book*)a)->data->name);
}
void sort(book* p)
{
  printf("请选择:\n");
  printf("-----------------------------\n");
  printf("----- 1.顺序  |   2.逆序-----\n");
  printf("-----------------------------\n");
  int in;
  scanf("%d", &in);
  switch (in)
  {
  case 1:
    qsort(p->data, p->count, sizeof(p->data[0]), compare);
  case 2:
    qsort(p->data, p->count, sizeof(p->data[0]), compare2);
  }
  printf("\n 排序完成!\n");
}
相关文章
|
4月前
|
存储 C语言 开发者
C语言实战 | Flappy Bird游戏
【7月更文挑战第4天】Flappy Bird是由越南开发者制作的简单却极具挑战性的游戏,玩家需控制小鸟穿越水管障碍。游戏涉及角色初始化、显示和更新。小鸟和水管结构体存储数据,使用变量和数组。初始化小鸟和水管,显示背景、小鸟和水管,更新小鸟位置及碰撞检测。代码示例展示了小鸟和水管的状态管理,当小鸟与管道碰撞或触地时,游戏结束。游戏的成功在于其独特的虐心体验。
79 0
C语言实战 | Flappy Bird游戏
|
1月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
19 2
|
2月前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
384 8
|
1月前
|
存储 C语言
手把手教你用C语言实现通讯录管理系统
手把手教你用C语言实现通讯录管理系统
|
2月前
|
存储 算法 C语言
C语言手撕实战代码_二叉排序树(二叉搜索树)_构建_删除_插入操作详解
这份二叉排序树习题集涵盖了二叉搜索树(BST)的基本操作,包括构建、查找、删除等核心功能。通过多个具体示例,如构建BST、查找节点所在层数、删除特定节点及查找小于某个关键字的所有节点等,帮助读者深入理解二叉排序树的工作原理与应用技巧。此外,还介绍了如何将一棵二叉树分解为两棵满足特定条件的BST,以及删除所有关键字小于指定值的节点等高级操作。每个题目均配有详细解释与代码实现,便于学习与实践。
|
2月前
|
存储 算法 C语言
C语言手撕实战代码_二叉树_构造二叉树_层序遍历二叉树_二叉树深度的超详细代码实现
这段代码和文本介绍了一系列二叉树相关的问题及其解决方案。其中包括根据前序和中序序列构建二叉树、通过层次遍历序列和中序序列创建二叉树、计算二叉树节点数量、叶子节点数量、度为1的节点数量、二叉树高度、特定节点子树深度、判断两棵树是否相似、将叶子节点链接成双向链表、计算算术表达式的值、判断是否为完全二叉树以及求二叉树的最大宽度等。每道题目均提供了详细的算法思路及相应的C/C++代码实现,帮助读者理解和掌握二叉树的基本操作与应用。
|
2月前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
|
2月前
|
算法 C语言 开发者
C语言手撕实战代码_单链表
本文档详细介绍了使用C语言实现单链表的各种基本操作和经典算法。内容涵盖单链表的构建、插入、查找、合并及特殊操作,如头插法和尾插法构建单链表、插入元素、查找倒数第m个节点、合并两个有序链表等。每部分均配有详细的代码示例和注释,帮助读者更好地理解和掌握单链表的编程技巧。此外,还提供了判断子链、查找公共后缀等进阶题目,适合初学者和有一定基础的开发者学习参考。
|
3月前
|
SQL 缓存 自然语言处理
实战案例1:基于C语言的Web服务器实现。
实战案例1:基于C语言的Web服务器实现。
191 15
|
3月前
|
存储 编译器 数据处理
【编程秘籍】解锁C语言数组的奥秘:从零开始,深入浅出,带你领略数组的魅力与实战技巧!
【8月更文挑战第22天】数组是C语言中存储同类型元素的基本结构。本文从定义出发,详述数组声明、初始化与访问。示例展示如何声明如`int numbers[5];`的数组,并通过下标访问元素。初始化可在声明时进行,如`int numbers[] = {1,2,3,4,5};`,编译器自动计算大小。初始化时未指定的元素默认为0。通过循环可遍历数组,数组名视为指向首元素的指针,方便传递给函数。多维数组表示矩阵,如`int matrix[3][4];`。动态数组利用`malloc()`分配内存,需用`free()`释放以避免内存泄漏。掌握这些技巧是高效数据处理的基础。
71 2