代码(c语言)实现顺序表头尾插入删除(实现菜单)

简介: 代码(c语言)实现顺序表头尾插入删除(实现菜单)



动态顺序表

       相较于静态顺序表的好处在于其能够根据需要动态地调整存储空间的大小。

以下是动态顺序表的优势:

1. 空间利用更高效:动态顺序表可以根据数据量的增长动态增加容量,避免了因预先分配过大空间而造成的浪费。

2. 灵活性更强:动态顺序表在数据量增大时可以自动扩容,而在数据量减少时可以缩小容量,这种灵活性使得它更加适用于数据规模变化较大的场景。

3. 避免内存泄漏:虽然静态顺序表不存在内存泄漏问题,但动态顺序表通过合理的内存管理(如使用malloc和free函数)也可以避免内存泄漏的风险。

       动态顺序表提供了更加灵活和高效的内存管理方式,尤其适合处理数据规模不确定或变化较大的情况。而静态顺序表则在数据规模较小且确定的情况下更为简单和方便。在实际应用中,应根据具体需求选择合适的顺序表类型。

 

代码实现:

头文件

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
//增强程序的可维护性
typedef int SQDataType;
//动态的
typedef struct SeqList
{
  SQDataType* a;
  int size;   //有效数据的个数
  int capacity; //容量
}SL;
//增删查改等接口函数
void SeqListInit(SL* ps);
void SeqListPrint(SL* ps);
void SeqListDestroy(SL* ps);
//头插 尾插 头删 尾删
void SeqListPushFront(SL* ps, SQDataType x);
void SeqListPushBack(SL* ps, SQDataType x);
void SeqListPopBack(SL* ps);
void SeqListPopFront(SL* ps);
void SeqListInsert(SL* ps, int pos, SQDataType x);
void SeqListErase(SL* ps, int pos);
//查找 修改
int  SeqListFind(SL* ps, SQDataType x);
void SeqListModify(SL* ps, int pos, SQDataType x);

源文件

#include"SeqListTest.h"
void SeqListInit(SL* ps)
{
  //可以开始给空间ps->a = malloc
  ps->a = NULL;
  ps->size = 0;
  ps->capacity = 0;
}
void SeqListCheckCapacity(SL* ps)
{
  if (ps->size == ps->capacity)
  {
    //满了就要扩容,一般满了扩容两倍,如果一直扩容一个的话,需要一直扩容
    int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
    //realloc如果刚开始为空则malloc一个空间
    SQDataType* tmp = (SQDataType*)realloc(ps->a, newcapacity * sizeof(SQDataType));
    if (tmp == NULL)
    {
      printf("realloc fail\n");
      exit(-1);
    }
    else
    {
      ps->a = tmp;
      ps->capacity = newcapacity;
    }
  }
}
void SeqListDestroy(SL* ps)
{
  free(ps->a);
  ps->a = NULL;
  ps->capacity = ps->size = 0;
}
//头插 尾插 头删 尾删
void SeqListPushBack(SL* ps, SQDataType x)
{
  //SeqListCheckCapacity(ps);
  //ps->a[ps->size] = x;
  //ps->size++;
  SeqListInsert(ps, ps->size, x);
}
void SeqListPushFront(SL* ps, SQDataType x)
{
  //SeqListCheckCapacity(ps);
  1、初始条件
  2、结束条件
  3、迭代过程
  //int end = ps->size - 1;
  //while (end >= 0)
  //{
  //  ps->a[end + 1] = ps->a[end];
  //  --end;
  //}
  //ps->a[0] = x;
  //ps->size++;
  SeqListInsert(ps, 0, x);
}
void SeqListPopBack(SL* ps)
{
  //assert(ps->size > 0);
  //ps->size--;
  SeqListErase(ps, ps->size - 1);
}
void SeqListPopFront(SL* ps)
{
  assert(ps->size > 0);
  //int start = 1;
  //while (start < ps->size)
  //{
  //  ps->a[start - 1] = ps->a[start];
  //  ++start;
  //}
  //ps->size--;
  SeqListErase(ps, 0);
}
void SeqListInsert(SL* ps, int pos, SQDataType x)
{
  assert(pos <= ps->size);
  SeqListCheckCapacity(ps);
  int end = ps->size - 1;
  while (end >= pos)
  {
    ps->a[end + 1] = ps->a[end];
    --end;
  }
  ps->a[pos] = x;
  ps->size++;
}
void SeqListErase(SL* ps, int pos)
{
  assert(pos < ps->size);
  int start = pos + 1;
  while (start < ps->size)
  {
    ps->a[start - 1] = ps->a[start];
    ++start;
  }
  ps->size--;
}
int  SeqListFind(SL* ps, SQDataType x)
{
  for (int i = 0; i < ps->size; i++)
  {
    if (ps->a[i] == x)
    {
      return i;
    }
  }
  return -1;
}
void SeqListModify(SL* ps, int pos, SQDataType x)
{
  assert(pos < ps->size);
  ps->a[pos] = x;
}
void SeqListPrint(SL* ps)
{
  for (int i = 0; i < ps->size; ++i)
  {
    printf("%d ", ps->a[i]);
  }
  printf("\n");
}

测试文件

#include"SeqListTest.h"
void TestSeqList1()
{
  SL sl;
  SeqListInit(&sl);
  SeqListPushBack(&sl, 1);
  SeqListPushBack(&sl, 2);
  SeqListPushBack(&sl, 3);
  SeqListPushBack(&sl, 4);
  SeqListPushBack(&sl, 5);
  SeqListPushBack(&sl, 6);
  printf("头插\n");
  SeqListPrint(&sl);
}
void TestSeqList2()
{
  SL sl;
  SeqListInit(&sl);
  SeqListPushFront(&sl, 1);
  SeqListPushFront(&sl, 2);
  SeqListPushFront(&sl, 3);
  SeqListPushFront(&sl, 4);
  SeqListPushFront(&sl, 5);
  SeqListPushFront(&sl, 6);
  printf("尾插\n");
  SeqListPrint(&sl);
}
void TestSeqList3()
{
  SL sl;
  SeqListInit(&sl);
  SeqListPushFront(&sl, 1);
  SeqListPushFront(&sl, 2);
  SeqListPushFront(&sl, 3);
  SeqListPushFront(&sl, 4);
  SeqListPushFront(&sl, 5);
  SeqListPushFront(&sl, 6);
  printf("尾删\n");
  SeqListPrint(&sl);
  SeqListPopBack(&sl);
  SeqListPrint(&sl);
}
void TestSeqList4()
{
  SL sl;
  SeqListInit(&sl);
  SeqListPushFront(&sl, 1);
  SeqListPushFront(&sl, 2);
  SeqListPushFront(&sl, 3);
  SeqListPushFront(&sl, 4);
  SeqListPushFront(&sl, 5);
  SeqListPushFront(&sl, 6);
  printf("头删\n");
  SeqListPrint(&sl);
  SeqListPopFront(&sl);
  SeqListPrint(&sl);
}
void TestSeqList5()
{
  SL sl;
  SeqListInit(&sl);
  SeqListPushFront(&sl, 1);
  SeqListPushFront(&sl, 2);
  SeqListPushFront(&sl, 3);
  SeqListPushFront(&sl, 4);
  SeqListPushFront(&sl, 5);
  SeqListPushFront(&sl, 6);
  printf("指定位置插入,在下标为1的位置插入了值为20的数\n");
  SeqListPrint(&sl);
  SeqListInsert(&sl, 1, 20);
  SeqListPrint(&sl);
}
void TestSeqList6()
{
  SL sl;
  SeqListInit(&sl);
  SeqListPushFront(&sl, 1);
  SeqListPushFront(&sl, 2);
  SeqListPushFront(&sl, 3);
  SeqListPushFront(&sl, 4);
  SeqListPushFront(&sl, 5);
  SeqListPushFront(&sl, 6);
  printf("指定位置删除,删除了下标为1的位置的数\n");
  SeqListInsert(&sl, 1, 20);
  SeqListPrint(&sl);
  SeqListErase(&sl, 1);
  SeqListPrint(&sl);
}
void menu()
{
  printf("****************************************************\n");
  printf("1.尾插数据   2.头插数据\n");
  printf("3.尾删数据   4.头删数据\n");
  printf("5.打印数据   -1.退出\n");
  printf("****************************************************\n");
  printf("  请输入你要操作的选项 :");
}
int main()
{ /*TestSeqList1();
  TestSeqList2();
  TestSeqList3();
  TestSeqList4();
  TestSeqList5();
  TestSeqList6();*/
  //操作已经测试,无问题, 可以复用insert和erase接口
  SL s;
  SeqListInit(&s);
  int option = 0;
  int x = 0;
  while (option != -1)
  {
    menu();
    scanf("%d", &option);
    switch (option)
    {
    case 1:
      printf("请输入你要尾插的数据,以-1结束\n");
      do {
        scanf("%d", &x);
        if (x != -1)
        {
          SeqListPushBack(&s, x);
        }
      } while (x != -1);
      break;
    case 2:
      printf("请输入你要头插的数据,以-1结束\n");
      do {
        scanf("%d", &x);
        if (x != -1)
        {
          SeqListPushFront(&s, x);
        }
      } while (x != -1);
      break;
    case 3:
      printf("请输入你要尾删几个数据,以-1结束\n");
      do {
        scanf("%d", &x);
        if (x != -1)
        {
          for (int i = 0; i < x; i++)
          {
            SeqListPopBack(&s);
          }
        }
      } while (x != -1);
      break;
    case 4:
      printf("请输入你要头删几个数据,以-1结束\n");
      do {
        scanf("%d", &x);
        if (x != -1)
        {
          for (int i = 0; i < x; i++)
          {
            SeqListPopFront(&s);
          }
        }
      } while (x != -1);
      break;
    case 5:
      SeqListPrint(&s);
      break;
    case 6:
      printf("请输入你要查找的数据,以-1结束\n");
      do {
        scanf("%d", &x);
        if (x != -1)
        {
          printf("所查找到数据的下标为:");
          SeqListFind(&s, x);
        }
      } while (x != -1);
      break;
    default:
      break;
    }
  }
  SeqListDestroy(&s);
  return 0;
}

运行结果

(模块测试)

(菜单实现)
尾插:

头插:

尾删:

头删:

退出:

 

希望对你有帮助,加油!!

目录
相关文章
|
3月前
|
NoSQL 编译器 程序员
【C语言】揭秘GCC:从平凡到卓越的编译艺术,一场代码与效率的激情碰撞,探索那些不为人知的秘密武器,让你的程序瞬间提速百倍!
【8月更文挑战第20天】GCC,GNU Compiler Collection,是GNU项目中的开源编译器集合,支持C、C++等多种语言。作为C语言程序员的重要工具,GCC具备跨平台性、高度可配置性及丰富的优化选项等特点。通过简单示例,如编译“Hello, GCC!”程序 (`gcc -o hello hello.c`),展示了GCC的基础用法及不同优化级别(`-O0`, `-O1`, `-O3`)对性能的影响。GCC还支持生成调试信息(`-g`),便于使用GDB等工具进行调试。尽管有如Microsoft Visual C++、Clang等竞品,GCC仍因其灵活性和强大的功能被广泛采用。
125 1
|
3月前
|
存储 C语言
【C语言】基础刷题训练4(含全面分析和代码改进示例)
【C语言】基础刷题训练4(含全面分析和代码改进示例)
|
1月前
|
存储 搜索推荐 C语言
深入C语言指针,使代码更加灵活(二)
深入C语言指针,使代码更加灵活(二)
|
1月前
|
存储 程序员 编译器
深入C语言指针,使代码更加灵活(一)
深入C语言指针,使代码更加灵活(一)
|
1月前
|
C语言
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
|
2月前
|
安全 C语言
在C语言中,正确使用运算符能提升代码的可读性和效率
在C语言中,运算符的使用需要注意优先级、结合性、自增自减的形式、逻辑运算的短路特性、位运算的类型、条件运算的可读性、类型转换以及使用括号来明确运算顺序。掌握这些注意事项可以帮助编写出更安全和高效的代码。
50 4
|
1月前
|
C语言
C语言练习题代码
C语言练习题代码
|
2月前
|
存储 算法 C语言
数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解
本文详细介绍了单链表的理论知识,涵盖单链表的定义、优点与缺点,并通过示例代码讲解了单链表的初始化、插入、删除、查找等核心操作。文中还具体分析了按位序插入、指定节点前后插入、按位序删除及按值查找等算法实现,并提供了尾插法和头插法建立单链表的方法,帮助读者深入理解单链表的基本原理与应用技巧。
528 6
|
2月前
|
存储 C语言 C++
数据结构基础详解(C语言) 顺序表:顺序表静态分配和动态分配增删改查基本操作的基本介绍及c语言代码实现
本文介绍了顺序表的定义及其在C/C++中的实现方法。顺序表通过连续存储空间实现线性表,使逻辑上相邻的元素在物理位置上也相邻。文章详细描述了静态分配与动态分配两种方式下的顺序表定义、初始化、插入、删除、查找等基本操作,并提供了具体代码示例。静态分配方式下顺序表的长度固定,而动态分配则可根据需求调整大小。此外,还总结了顺序表的优点,如随机访问效率高、存储密度大,以及缺点,如扩展不便和插入删除操作成本高等特点。
196 5
|
2月前
|
存储 C语言
数据结构基础详解(C语言): 栈与队列的详解附完整代码
栈是一种仅允许在一端进行插入和删除操作的线性表,常用于解决括号匹配、函数调用等问题。栈分为顺序栈和链栈,顺序栈使用数组存储,链栈基于单链表实现。栈的主要操作包括初始化、销毁、入栈、出栈等。栈的应用广泛,如表达式求值、递归等场景。栈的顺序存储结构由数组和栈顶指针构成,链栈则基于单链表的头插法实现。
378 3