顺序表

空扰寡人 提交于 2020-01-25 16:28:03

顺序表是用一段物理地址连续的存储单元一次存储数据元素的线性结构,一般情况下采用数组存储

顺序表分为:

  • 静态顺序表(使用地工厂数组存储)
  • 动态顺序表(使用动态开辟的数组存储)

下面实现的是动态顺序表:

  1. C语言中没有这种结构,所以把它们封装成一个结构体,里面有不同类型的元素(数组、有效元素个数、数组总容量),便于管理
typedef int DataType;//给类型取别名 数组元素类型就很好变
typedef struct SeqList
{
 DataType *_array;//有效元素(动态开辟的数组)
 int _size;//有效元素个数
 int _capacity;//数组的总容量(空间总大小)
}SeqList,*PSeqList;//定义了结构体变量(把struct SeqList重命名为SeqList)
  1. 对结构体初始化
    数组的大小先设置一个初始值,不够了再扩容
void SeqListInit(PSeqList ps)
{
 assert(ps);
 //先设置一个容量(假设可以存放3个元素),在这个基础上再动态开辟
 ps->_array = (DataType*)malloc(sizeof(DataType)* 3);
 if (NULL == ps->_array)
 {
  return;
 }
 ps->_capacity = 3;
 ps->_size = 0;
 printf("初始化:  有效元素:%d; 容量:%d\n", ps->_size, ps->_capacity);
}
  1. 容量检测,看是否需要扩容,下面用的是malloc开辟新空间,relloc也可以
void CheckIsCapacity(PSeqList ps)//
{
 assert(ps);
 if (ps->_capacity == ps->_size)//容量和大小相等,需要扩容
 {
  printf("需要扩容,");
  //每次扩容的大小
  int newcapacity = ps->_capacity * 2;
  //开辟新空间
  DataType *p = (DataType*)malloc(sizeof(DataType)*newcapacity);
  if (p == NULL)
  {
   //申请失败
   printf("申请失败\n");
   assert(0);
   return;
  }
  //申请成功,拷贝元素
  printf("申请成功\n");
  memcpy(p, ps->_array, ps->_size*sizeof(DataType));
  //释放旧空间
  free(ps->_array);
  ps->_capacity = newcapacity;
  ps->_array = p;
 }
 else
 {
  printf("不需要扩容\n");
 }
}

下来就是对顺序表进行增删改查的操作了

直接看整体代码:

SeqList.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<malloc.h>
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//动态顺序表
typedef int DataType;//给类型取别名 数组元素类型就很好变
typedef struct SeqList
{
 DataType *_array;//有效元素
 int _size;//有效元素个数
 int _capacity;//数组的总容量(空间总大小)
}SeqList,*PSeqList;//定义了结构体变量(把struct SeqList重命名为SeqList)

void SeqListInit(PSeqList ps);//初始化顺序表
void SeqListDestory(PSeqList ps);//对顺序表销毁

void CheckIsCapacity(PSeqList ps);//检测是否需要扩容

void SeqListPushBack(PSeqList ps, DataType data);//尾插
void SeqListPopBack(PSeqList ps);//尾删

void SeqListPushFront(PSeqList ps, DataType data);//头插
void SeqListPopFront(PSeqList ps);//头删

void SeqListInsert(PSeqList ps, int pos, DataType data);//任意位置插入  在[0,size)之间
void SeqListErase(PSeqList ps, int pos);//任意位置删除

int SeqListFind(PSeqList ps, DataType data);// 检测data是否在顺序表中

void SeqListRemove(PSeqList ps, DataType data);// 移除顺序表中第一个值为data的元素 
void SeqListRemoveAll(PSeqList ps, DataType data);// 移除顺序表中所有值为data的元素 

void SeqListSize(PSeqList ps);//// 获取顺序表有效元素个数 
void SeqListCapacity(PSeqList ps);// 获取顺序表的容量 

int SeqListEmpty(PSeqList ps);// 检测顺序表是否为空
DataType SeqListFront(PSeqList ps);// 获取顺序表中第一个元素 
DataType SeqListBack(PSeqList ps);// 获取顺序表中最后一个元素

/////////////////////////////////////////////////////////////
void PrintSeqList(PSeqList ps);//打印

SeqList.c

#include "SeqList.h"
void SeqListInit(PSeqList ps)
{
 assert(ps);
 //先设置一个容量(假设可以存放3个元素),在这个基础上再动态开辟
 ps->_array = (DataType*)malloc(sizeof(DataType)* 3);
 if (NULL == ps->_array)
 {
  return;
 }
 ps->_capacity = 3;
 ps->_size = 0;
 printf("初始化:  有效元素:%d; 容量:%d\n", ps->_size, ps->_capacity);
}

void CheckIsCapacity(PSeqList ps)//
{
 assert(ps);
 //用malloc进行扩容
 if (ps->_capacity == ps->_size)//容量和大小相等,需要扩容
 {
  printf("需要扩容,");
  //每次扩容的大小
  int newcapacity = ps->_capacity * 2;
  //开辟新空间
  DataType *p = (DataType*)malloc(sizeof(DataType)*newcapacity);
  if (p == NULL)
  {
   //申请失败
   printf("申请失败\n");
   assert(0);
   return;
  }
  //申请成功,拷贝元素
  printf("申请成功\n");
  memcpy(p, ps->_array, ps->_size*sizeof(DataType));
  //释放旧空间
  free(ps->_array);
  ps->_capacity = newcapacity;
  ps->_array = p;
 }
 else
 {
  printf("不需要扩容\n");
 } 
}

void SeqListPushBack(PSeqList ps, DataType data)//尾插
{
 assert(ps);
 CheckIsCapacity(ps);
 ps->_array[ps->_size] = data;
 ps->_size++;
 
 //SeqListInsert(ps, ps->_size, data);//方法二 调用任意位置插入的函数
}

void SeqListPopBack(PSeqList ps)//尾删
{
 assert(ps);
 if (ps->_size == 0)
  return;
 ps->_size--;
//SeqListErase(ps, ps->_size-1);//方法二调用任意位置删除函数 
}

void SeqListPushFront(PSeqList ps, DataType data)//头插
{
 assert(ps);
 //方法1
 CheckIsCapacity(ps);
 for (int i = ps->_size; i > 0; i--)
 {
  ps->_array[i] = ps->_array[i-1];
 }
 ps->_array[0] = data;
 ps->_size++;//插完有效元素个数也要加+1
 
 //方法2
 //SeqListInsert(ps, 0,data);//写完任意位置的插入后,可以直接调这个函数
}

void SeqListPopFront(PSeqList ps)//头删
{
 assert(ps);
 if (ps->_size == 0)
  return;
  //i 元素被搬移到位置的下标
 for (int i = 0; i < ps->_size-1; i++)
 {
  ps->_array[i] = ps->_array[i + 1];
 }
 ps->_size--;
 
 //SeqListErase(ps, 0);//方法二 调用任意位置删除函数
}

void SeqListInsert(PSeqList ps, int pos, DataType data)//任意位置插入
{
 assert(ps);
 if (pos<0 || pos > ps->_size)//范围[0,size)
 {
  printf("插入位置有误\n");
  return;
 }
 CheckIsCapacity(ps);
 for (int i = ps->_size; i > pos; i--)
 {
  ps->_array[i] = ps->_array[i - 1];
 }
 ps->_array[pos] = data;
 ps->_size++;
}

void SeqListErase(PSeqList ps, int pos)//任意位置删除
{
 assert(ps);
 if (pos<0 || pos>ps->_size)
 {
  printf("删除位置非法,无法删除\n");
  return;
 }
 for (int i = pos; i < ps->_size-1; i++)
 {
  ps->_array[i] = ps->_array[i + 1];
 }
 ps->_size--;
}

int SeqListFind(PSeqList ps, DataType data)//检测data是否在顺序表中
{
 assert(ps);
 if (ps->_size == 0)
 {
  printf("顺序表为空,无法检测\n");
  return 0;
 }
 for (int i = 0; i < ps->_size; i++)
 {
  if (ps->_array[i] == data)
  {
   printf("%d在顺序表中:", data);
   return i;
  }
 }
 printf("%d不在顺序表中:", data);
 return -1;
}

void SeqListRemove(PSeqList ps, DataType data)// 移除顺序表中第一个值为data的元素
{
 assert(ps);
 if (ps->_size == 0)
 {
  printf("顺序表为空,无法移除\n");
  return;
 }
 for (int i = 0; i < ps->_size; i++)
 {
  if (ps->_array[i] == data)
  {
   for (int j = i; j < ps->_size - 1; j++)
   {
    ps->_array[j] = ps->_array[j + 1]; 
   }
   ps->_size--;
   return; 
  }
 }
}

void SeqListRemoveAll(PSeqList ps, DataType data)// 移除顺序表中所有值为data的元素
{
 assert(ps);
 if (ps->_size == 0)
 {
  printf("顺序表为空,无法移除\n");
  return;
 }
 int i = 0;
 while (i < ps->_size)
 {
  if (ps->_array[i] == data)
  {
   for (int j = i; j < ps->_size-1; j++)
   {
    ps->_array[j] = ps->_array[j + 1];
   }
   ps->_size--;
   continue;//继续判断这个位置上是不是要删除的
  }
  i++;//不是指针就向后移
 } 
}

void SeqListSize(PSeqList ps)// 获取顺序表有效元素个数 
{
 assert(ps);
 printf("顺序表中的有效元素个数为: %d : ",ps->_size);
 //return ps->_size;
}

void SeqListCapacity(PSeqList ps)// 获取顺序表的容量
{
 assert(ps);
 printf("顺序表中的容量为:%d \n", ps->_capacity);
}

int SeqListEmpty(PSeqList ps)//检测顺序表是否为空
{
 assert(ps);
 if (ps->_size == 0)
 {
  printf("顺序表为空\n");
  return 0;
 }
 else
 {
  printf("顺序表不为空\n");
  return 1;
 }
}

DataType SeqListFront(PSeqList ps)// 获取顺序表中第一个元素
{
 assert(ps);
 printf("顺序表中第一个元素为:%d\n", ps->_array[0]);
 return ps->_array[0];
}

DataType SeqListBack(PSeqList ps)// 获取顺序表中最后一个元素
{
 assert(ps);
 printf("顺序表中最后一个元素为:%d\n", ps->_array[ps->_size - 1]);
 return ps->_array[ps->_size];
}

void SeqListDestory(PSeqList ps)
{
 assert(ps);
 if (ps->_array)
 {
  free(ps->_array);
  ps->_array = NULL;
  ps->_capacity = 0;
  ps->_size = 0;
  printf("销毁成功\n");
 }
}

/////////////////////////////////////////////////////////////////
//test
void PrintSeqList(PSeqList ps)
{
 assert(ps);
 for (int i = 0; i < ps->_size; i++)
 {
  printf("%d ", ps->_array[i]);
 }
 printf("\n");
}

test.c

#include "SeqList.h"
int main()
{
 SeqList s;
 //初始化
 SeqListInit(&s);
 //尾插
 SeqListPushBack(&s, 1);
 SeqListPushBack(&s, 2);
 SeqListPushBack(&s, 2);
 SeqListPushBack(&s, 3);
 SeqListPushBack(&s, 3);
 SeqListPushBack(&s, 2);
 SeqListPushBack(&s, 2);
 SeqListPushBack(&s, 3);
 SeqListPushBack(&s, 4);
 PrintSeqList(&s);
 //尾删
 SeqListPopBack(&s);
 PrintSeqList(&s);
 //头插
 SeqListPushFront(&s, 0);
 PrintSeqList(&s);
 //头删
 SeqListPopFront(&s);
 PrintSeqList(&s);
 //任意位置插入
 SeqListInsert(&s, 2, 5);
 PrintSeqList(&s);
 //任意位置删除
 SeqListErase(&s, 2);
 PrintSeqList(&s);
 //检测data是否在顺序表中
 SeqListFind(&s, 5);
 PrintSeqList(&s);
 // 移除顺序表中第一个值为data的元素
 SeqListRemove(&s, 2);
 PrintSeqList(&s);
 // 移除顺序表中所有值为data的元素
 SeqListRemoveAll(&s, 2);
 PrintSeqList(&s);
 
 // 获取顺序表有效元素个数 
 SeqListSize(&s);
 PrintSeqList(&s);
 // 获取顺序表的容量 
 SeqListCapacity(&s);
 
 SeqListEmpty(&s);//检测顺序表是否为空
 SeqListFront(&s);// 获取顺序表中第一个元素 
 SeqListBack(&s);// 获取顺序表中最后一个元素
 
 //销毁
 SeqListDestory(&s);
 system("pause");
 return 0;
}

运行结果如下:
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!