【数据结构】顺序表的基本操作——定长顺序表(C语言实现)

线性表的顺序存储结构:指的是用用一段地址连续的存储单元依次存储线性表的数据元素。

线性表的顺序结构示意图如下:

顺序表(SeqList)的基本特征为:元素在内部存储时是一个接一个在存储单元中按顺序存储的,所以只要知道"起始元素的存储地址"--称为顺序表的基地址以及顺序表中任何元素的位置(即它是第几个元素),就能直接定位到该元素的地址,从而直接访问到该元素的值。

顺序表的优点:可以快速地存取表中任一位置的元素。

顺序表的缺点:

1、插入和删除操作需要移动大量元素;

2、当线性表长度变化较大时,难以确定存储空间的容量;

顺序表分为两种:

①定长顺序表

②不定长顺序表(可扩容)

顺序存储结构:

#define MAXSIZE    20

typedef  struct   SeqList

{

        int data[MAXSIZE];      //数组存储数据元素,最大值为MAXSIZE

        int length;                     //线性表当前长度

}SeqList,*PSeqList;

数据长度与线性表长度的区别

数组长度:指存放线性表的存储空间的长度,存储分配后一般不变。(分配的数组空间要大于当前线性表的长度)

线性表长度:指线性表中数据元素的个数,随着线性表插入和删除操作的进行,量改变。

顺序表的插入:

1、判断插入位置是否合理;

2、判断线性表的长度大于等于数组长度;

3、从最后一个元素开始遍历到第i个位置,分别将它们都向后移动一个位置;

4、将插入的元素插入位置i处;

5、表长+1;

顺序表的删除:

1、判断删除位置是否合理;

2、取出删除值;

3、从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;

4、表长-1。

 插入和删除的时间复杂度分析:

//插入
bool Insert(PSeqList plist,int pos,int val)
{
    assert(plist != NULL);
    if(pos<0 || pos>plist->length || plist->length==SIZE)
    {
	return false;
    }
    //移动pos后面的数据
    //从最后一个元素开始遍历到第i个位置,分别将它们都向后移动一个位置;
    for(int i=plist->length-1;i>=pos;i--)
    {
	plist->elem[i+1] = plist->elem[i];
    }
    
    //插入新数据
    plist->elem[pos] = val;
    
    //更新有效数据个数
    plist->length++;

    return true;
}
//删除位置值
//rtval:输出参数,保存删除成功的数据
bool DeletePos(PSeqList plist,int pos,int *rtval)
{
   assert(plist != NULL);
   if(pos<0 || pos>=plist->length)
   {
	return false;
   }
   
   if(rtval != NULL)
   {
	*rtval = plist->elem[pos];
   }

   //移动数据
   for(int i=pos;i<plist->length-1;i++)
   {
	plist->elem[i] = plist->elem[i+1];
   }

   
   plist->length--;

   return true;
}

 最好情况:

元素要插入到最后一个位置或者删除最后一个元素,时间复杂度为O(1)

最坏情况:

元素要插入到第i个位置或者删除第i个元素,需要移动n-i个元素,为(n-1)/2,时间复杂度为O(n).

.h文件

//定长顺序表
#pragma once
#include <stdbool.h>

#define SIZE 10

typedef struct SeqList
{
    int elem[SIZE];//保存数据
    int length;//有效数据个数
}SeqList;

typedef SeqList *PSeqList;
/*
typedef struct SeqList
{
	int elem[SIZE];
	int length;
	
}SeqList ,*PSeqList;
*/

//初始化函数
void InitSeqList(PSeqList plist);//PSeqList == SeqList*

//往plist的pos位置插入数据val
bool Insert(PSeqList plist,int pos,int val);

//打印
void Show(PSeqList plist);

//判空
bool IsEmpty(PSeqList plist);

//查找,找到了返回下标,没有找到返回-1
int Search(PSeqList plist,int key);


//删除
bool DeleteVal(PSeqList plist,int key);

//删除位置值
//rtval:输出参数,保存删除成功的数据
bool DeletePos(PSeqList plist,int pos,int *rtval);

//获取pos下标存储的数据
bool GetVal(PSeqList plist,int pos,int *rtval);

//修改pos下标的数据
bool SetVal(PSeqList plist,int pos,int newval);

//获取val的前趋值
bool GetPriVal(PSeqList plist,int key,int *rtval);

//获取val的后继值
bool GetNextVal(PSeqList plist,int key,int *rtval);

//长度,即有效数据个数
int GetLength(PSeqList plist);

//清除所有数据
void Clear(PSeqList plist);

//销毁
void Destroy(PSeqList plist);

seqlist.c文件

#include "seqlist.h"
#include <stdio.h>
#include <assert.h>

//初始化函数
void InitSeqList(PSeqList plist)//PSeqList == SeqList*
{
    assert(plist != NULL);

    plist->length = 0;//当前无有效数据
}

//往plist的pos位置插入数据val
bool Insert(PSeqList plist,int pos,int val)
{
    assert(plist != NULL);
    if(pos<0 || pos>plist->length || plist->length==SIZE)
    {
	return false;
    }
    //移动pos后面的数据
    //从最后一个元素开始遍历到第i个位置,分别将它们都向后移动一个位置;
    for(int i=plist->length-1;i>=pos;i--)
    {
	plist->elem[i+1] = plist->elem[i];
    }
    
    //插入新数据
    plist->elem[pos] = val;
    
    //更新有效数据个数
    plist->length++;

    return true;
}

//打印
void Show(PSeqList plist)
{
    assert(plist != NULL);

    for(int i=0;i<plist->length;i++)
    {
	printf("%d ",plist->elem[i]);
    }
    printf("\n");
}

//判空
bool IsEmpty(PSeqList plist)
{
    return plist->length == 0;
}

static bool IsFull(PSeqList plist)
{
    return plist->length == SIZE;
}
//

//查找,找到了返回下标,没有找到返回-1
int Search(PSeqList plist,int key)
{
    assert(plist != NULL);
    for(int i=0;i<plist->length;i++)
    {
	if(plist->elem[i] == key)
	{
	    return i;
	}
    }

    return -1;
}


//删除
bool DeleteVal(PSeqList plist,int key)
{
    int i = Search(plist,key);
    if(i == -1)
    {
	return false;
    }
    return DeletePos(plist,i,NULL);
}

//删除位置值
//rtval:输出参数,保存删除成功的数据
bool DeletePos(PSeqList plist,int pos,int *rtval)
{
   assert(plist != NULL);
   if(pos<0 || pos>=plist->length)
   {
	return false;
   }
   
   if(rtval != NULL)
   {
	*rtval = plist->elem[pos];
   }

   //移动数据
   for(int i=pos;i<plist->length-1;i++)
   {
	plist->elem[i] = plist->elem[i+1];
   }

   
   plist->length--;

   return true;
}

//获取pos下标存储的数据
bool GetVal(PSeqList plist,int pos,int *rtval)
{
    if(pos<0 || pos>=plist->length)
    {
	return false;
    }

    if(rtval != NULL)
    {
	*rtval = plist->elem[pos];
    }

    return true;
}

//修改pos下标的数据
bool SetVal(PSeqList plist,int pos,int newval)
{
    if(pos<0 || pos>=plist->length)
    {
	return false;
    }

    plist->elem[pos] = newval;

    return true;
}

//获取val的前趋值
bool GetPriVal(PSeqList plist,int key,int *rtval)
{
    int i = Search(plist,key);
    if(i <= 0)
    {
	return false;
    }

    if(rtval != NULL)
    {
	*rtval = plist->elem[i-1];
    }

    return true;
}

//获取val的后继值
bool GetNextVal(PSeqList plist,int key,int *rtval);

//长度,即有效数据个数
int GetLength(PSeqList plist)
{
    return plist->length;
}

//清除所有数据
void Clear(PSeqList plist)
{
    plist->length = 0;
}

//销毁
void Destroy(PSeqList plist)
{
    Clear(plist);
}

main.c 文件

#include <stdio.h>
#include "seqlist.h"
int main()
{
    SeqList seq;
    InitSeqList(&seq);

    for(int i=0;i<20;i++)
    {
	Insert(&seq,i,i);
    }
    
    DeleteVal(&seq,5);

    Show(&seq);

    Insert(&seq,3,30);
    Show(&seq);

    Clear(&seq);
    Show(&seq);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/like_that/article/details/84332245