顺序表实现

动态扩容版本

  • 定义顺序表数据结构

    • 为了实现类似数组的动态数组的功能,首先要定义一种新的结构类型

      typedef int data_type; // 定义元素的数据类型
      typedef struct {
          data_type* pdata;
          int capacity;
          int size;
      } vector;
    • 类型初始化

      vector* init() {
          vector* ret = (vector*)malloc(sizeof(vector));
          if (ret == NULL)
              return NULL; // C++则可以使用throw抛出异常
          ret->pdata = NULL;
          ret->size = 0;
          ret->capacity = 0;
          return ret;
      }

    注:

    • 示例代码初始化后,在堆区创建一个**vector*的指针维护这个顺序表**
    • 新初始化的类型中,元素个数、容量初始化为0,维护的内存指针新建为NULL
  • 销毁函数

      void destory(vector* ptr) {
          // C++则可以使用throw抛出异常
          assert(ptr && ptr->pdata);
    
          free(ptr->pdata);
          free(ptr);
      }

    其中涉及到两种错误类型判断:

    • ptr传参非法,处理方法:使用assert()
    • ptr中记录的内存指针ptr->pdata非法,处理方法:使用assert()
  • 实现接口

    • 扩容函数

      static void check_capacity(vector* ptr) {
          // 检查容量是否足够,并自动增容
          assert(ptr);
      
          if (ptr->capacity == ptr->size) {
              int newcapacity = (ptr->capacity == 0) ? 4 : ptr->capacity * 2;
              data_type* ptmp = (data_type*)realloc(ptr->pdata, newcapacity * sizeof(data_type));
              if (ptmp == NULL)
                  exit(0);
              else {
                  ptr->pdata = ptmp;
                  ptr->capacity = newcapacity;
              }
          }
      }

      其中涉及到两种错误类型判断:

      • ptr传参非法,处理方法:使用assert()
      • realloc()开辟内存失败,处理方法:判空,错误时exit(0)

      扩容后,维护的内存空间变大了,并把capacity记录的容量增加了

    • insert()

      void insert(vector* ptr, int pos, data_type data) {
          assert(pos <= ptr->size);
          check_capacity(ptr);
      
          // 将最后一个元素至pos位置(含pos)的元素全部后移一位
          int i = 0;
          for (i = ptr->size - 1; i >= pos; --i)
              ptr->pdata[i + 1] = ptr->pdata[i];
          ptr->pdata[pos] = data;
          ptr->size++;
      }
    • erase()

      void erase(vector* ptr, int pos) {
          assert(pos < ptr->size && pos >= 0);
      
          // 将pos位置(不含pos)至最后位置的的元素全部前移一位并覆盖
          int i = 0;
          for (i = pos; i <= (ptr->size - 2); ++i)
              ptr->pdata[i] = ptr->pdata[i + 1];
          ptr->size--;
      }
    • 尾插、头插、尾删、头删

      void push_back(vector* ptr, data_type data) {
          insert(ptr, ptr->size, data);
      }
      
      void push_front(vector* ptr, data_type data) {
          insert(ptr, 0, data);
      }
      
      void pop_back(vector* ptr) {
          erase(ptr, ptr->size - 1);
      }
      
      void pop_front(vector* ptr) {
          erase(ptr, 0);
      }
    • 查找

      data_type at(vector* ptr, int pos) {
          // 按索引查找
          return ptr->pdata[pos];
      }
      
      int find(vector* ptr, data_type target) {
          // 按值查找,找不到返回-1
          int i = 0;
          for (i = 0; i < ptr->size; i++)
              if (ptr->pdata[i] == target)
                  return i;
          return -1;
      }

      注:按值查找时,涉及到元素判断相等,若涉及到自定义的类型作为数据结构的元素,则需要重写这部分的代码

    • 其他接口

      bool empty(vector* ptr) {
          // 判空
          return ptr->size == 0;
      }
      
      int size(vector* ptr) {
          // 元素个数
          return ptr->size;
      }

静态数组版本

const int N = 1e5 + 10; // 数据范围
int arr[N], arr_size; // 顺序表、元素个数

void clear() {
    arr_size = 0;
}

void insert(int pos, int x) {
    // 将最后一个元素至pos位置(含pos)的元素全部后移一位
    for (int cur = arr_size; cur >= pos; --cur)
        arr[cur + 1] = arr[cur];
    arr[pos] = x;
    arr_size++;
}

void erase(int pos) {
    // 将pos位置(不含pos)至最后位置的的元素全部前移一位并覆盖
    for (int cur = pos; cur <= arr_size; cur++)
        arr[cur] = arr[cur + 1];
    arr_size--;
}

void push_back(int x) {
    insert(arr_size + 1, x);
}

void push_front(int x) {
    insert(1, x);
}

void pop_back() {
    erase(arr_size);
}

void pop_front() {
    erase(1);
}

int at(int pos) {
    return arr[pos];
}

int find(int data) {
    // 按值查找,找不到返回-1
    for (int i = 1; i <= arr_size; ++i)
        if (data == arr[i])
            return i;
    return -1;
}

void change(int pos, int data) {
    arr[pos] = data;
}
« 散列表 ← 返回列表 链表实现 »