数据结构 顺序表 曲一

准备

  • 分工合作(增加代码可读性,代码不冗余,多个.cw文件使用)
  1. 声明 SeqList.h
  2. 调用文件 main.c
  3. 实现接口 SeqList.h

初始化

  • 接口:SeqListInit
  • 作用初始化
  • 为什么要初始化???
  • 应为不初始化是随机值
  • 且一定要传指哟,为什么要传指?(应为函数传值是原数据的一份零时拷贝,他们俩个长的一样内在却不一样)
void SeqListNotInit(SLN*ps)//初始化
{
    
    
    ps->data=NULL;
    ps->capacity=0;
    ps->size=0;
}

开辟空间

  • 可以说这个是核心了,没有我就没有顺序表哈哈哈
  • sz是数组现有元素个数,capacity为现数组大小
void SeqListNotSpace(SLN*ps)//开辟空间
{
    
    
    if(ps->size==ps->capacity)
    {
    
    
        int newcapacity=ps->capacity==0?4:ps->capacity*2;
        ps->data=(Value*)malloc(sizeof(Value)*newcapacity);
        ps->capacity=newcapacity;
    }
}

//分解这段代码
  int newcapacity=ps->capacity==0?4:ps->capacity*2;
----------------------------------------------------
int newcapacity=0;
if(ps->capacity==0)
{
    
    
newcapacity=4;
}
else
{
    
    
capacity*=2;
}

  • 数组中的元素和要找的元素对比,找到返回下标
  • 找不到返回负数,应为数组下标是从零开始的
  • 如图所示
    在这里插入图片描述
int  SeqListNotFind(SLN*ps,int num)//查
{
    
    
    for(int i =0;i<ps->size;i++)
    {
    
    
        if(num==ps->data[i])
        {
    
    
            return i;
        }
    }
    return -1;
}

头插入

  • 头插比较麻烦,有一下俩种情况
  1. 空数组之间插 复杂度O(1)
  2. 数组内多个元素 复杂度O(N)
  3. 如图所示(多个元素的情况)
    在这里插入图片描述
void SeqListNotPushFront(SLN*ps,int num)//头插
{
    
    
    //防止满了或者没有的情况
    SeqListNotSpace(ps);
    for (int i = 0; i <ps->size ; ++i)
    {
    
    
        ps->data[ps->size+1]=ps->data[ps->size];
    }
    ps->data[0]=num;
    ps->size++;
}

尾插入

  • 插比较容易找ps->sz,直接插入即可
  • 如图
    在这里插入图片描述
int SeqListNotPushBack(SLN*ps,int num)//尾插
{
    
    

    SeqListNotSpace(ps);//开辟空间
    ps->data[ps->size]=num;
    ps->size++;
}

任意位置插入

  • 通过查找SeqListNotFind查找接口进行操作
  • pos为需要置换位置的下标
    在这里插入图片描述
void SeqListNotPushInsert(SLN*ps,int find,int num)//任意位置插入
{
    
    
    //防止满了或者没有的情况
    int count=ps->size-find;
    int tail=ps->size;
     while(count--)
     {
    
    
         ps->data[tail+1]=ps->data[tail];
         tail--;
     }
     ps->size++;
}

  • 这么删?
  • 效率怎么样

头删

  • 其实就是和头插的逻辑相反
  • 他是吧数据往前移
void SeqListNotPopFront(SLN*ps,int num)//头删
{
    
    
    //防止满了或者没有的情况
     assert(ps->size&&ps->capacity);
    for (int i = 0; i <ps->size ; ++i)
    {
    
    
        ps->data[i]=ps->data[i+1];
    }
    ps->size--;
}

尾删

  • 尾删比较容易找ps->sz-1(数组现有元素个数减一,应为下标从零开始),直接插入即可


    ⚠️:注意
  • 判断数组是不是空如果是空那就删啥,删空气吗
void SeqListNotPopBack(SLN*ps,int num)//尾删
{
    
    
    assert(ps->size==0&&ps->capacity==0);
    ps->size--;
}

任意位删

  • 和任意位置插的思路基本一样,但是逻辑是相反的
void SeqListNotPopInsert(SLN*ps,int find,int num)//任意位置删
{
    
    

   int trade=find;
   int count=ps->size-find-1;
    while(count--)
    {
    
    
       ps->data[trade]=ps->data[trade+1];
       trade++;
    }
    ps->size--;
}

从上面删除数据可以看出,删除数据是在覆盖,而不是置换,应为你存入数据是数字,把他置为0或者别的数,如过他本来也是这个数,那么不是本末倒置了

释放

void SeqListNotDestroy(SLN*ps)//销毁
{
    
    
    free(ps->data);
    ps->data=NULL;
    ps->data=0;
    ps->size=0;
}

总结

  • 顺序表尾插尾删比较方便 复杂度O(1)
  • 头插的效率却低下 复杂度O(N)
  • 且他也会造成一定的空间浪费

猜你喜欢

转载自blog.csdn.net/Legwhite/article/details/119548784
今日推荐