顺序表及其应用

来源:互联网 发布:软件开发工程师 翻译 编辑:程序博客网 时间:2024/05/16 09:20

一、顺序表
定义:顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。线性表采用顺序存储的方式存储就称之为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

结构:将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构是顺序结构。
采用顺序存储结构的线性表简称为“ 顺序表”。顺序表的存储特点是:只要确定了起始位置,表中任一元素的地址都通过下列公式得到:LOC(ai)=LOC(a1)+(i-1)*L  1≤i≤n 其中,L是元素占用存储单元的长度。

1、定长顺序表
(1)定义:顺序表的大小就已经确定了,不能再使用的过程中各种更改
(2)结构图
        定长顺序表主要是靠数组实现,但是它这个结构会封装一些功能比如插入,删除,查找等等……在实现这些功能的时候会有一个问题,比如插入功能,我们可以无条件无休止的插入吗?不能吧。那我们什么时候才能插入呢,除去一些不合法的插入位置,我们是不是还要看看数组是不是放满了数据呢?仅仅通过数组我们是不是无法判断放了多少个数据,所以我们增加了一个变量,保存数组的有效长度,初始化的时候因为数组里面没有东西,所以就可以直接赋值为零。
       



(3)代码实现
注意:这里面有一些要返回顺序表数组里的值的函数,因为任何整数都能被存储,所以没有可以返回表示错误的特殊值,所以我们把函数的返回值定义为bool型,如果位置合法的话,则返回true,并且通过调用函数的时候传一个指针进去把值带出来,否则返回false。
#include
#include
#include "seqlist.h"
#define SIZE 10
//定义定长顺序表结构
typedef struct SeqList
{
 int elem[SIZE];       //存放数据的数组
 int length;            //有效数据个数
}SeqList,*PSeqList;

//初始化函数
void InitSeqList(PSeqList ps)
{
 assert(ps != NULL);
 if(ps  == NULL)
 {
  return ;
 }
 ps->length = 0;//没有有效数据
}

//判断是否放满了数据
因为这个只有我们自己会用,用户只管使用功能,所以把它定义为static,控制它的作用域
static bool IsFull(PSeqList ps)
{
 return ps->length == SIZE;
}
//插入,数据必须连续
bool Insert(PSeqList ps,int pos,int val)
{
 if(pos<0 || pos>ps->length || IsFull(ps))
 {
  return false;
 }
 for(int i=ps->length-1;i>=pos;i--)//移动原有数据
 {
  ps->elem[i+1] = ps->elem[i];
 }
 ps->elem[pos] = val;//插入新数据
 ps->length++;
 return true;
}
//查找,成功则返回下标,失败返回-1
int Search(PSeqList ps,int key)//todo
{
   for(int i=0;ilength;i++)
        if(ps->elem[i]==key)
           return i;
    return -1;
}
//删除
bool DeletePos(PSeqList ps,int pos)
{
 if(pos<0 || pos>=ps->length)
 {
  return false;
 }
 for(int i=pos;ilength-1;i++)
 {
  ps->elem[i] = ps->elem[i+1];
 }
 ps->length--;
 return true;
}
bool Deleteval_r(PSeqList ps,int key);
{
    int index=Search(ps,key);
    if(index>=0)
        {
             DeletePos(ps,index);
             return true;
        }
     return false;
}
int GetLength(PSeqList ps)
{
 return ps->length;
}
bool IsEmpty(PSeqList ps)
{
 return ps->length == 0;
}
//清空数据
void Clear(PSeqList ps)
{
 ps->length = 0;
}
//销毁顺序表,销毁动态内存
void Destroy(PSeqList ps)
{
     Clear(ps);
}
void Show(PSeqList ps)
{
 for(int i=0;ilength;i++)
 {
  printf("%d ",ps->elem[i]);
 }
 printf("\n");
}

2、不定长顺序表
(1)定义:顺序表的大小可以根据用户的需求而变化
(2)结构图
         与定长的顺序表相比,不定长的顺序表多了一个数据成员,那就是它的总长度;这个变量的引出和定长顺序表引出length是一样的,我们在实现函数的功能的时候,会需要判断是否满了的情况,但是由于是不定长的,我们根据一个数组指针和有效数据长度去去推测出它是否满了,所以我们需要再添加一个变量记录它的总长度



(3)代码实现

#include
#include
#include
#define INITSIZE 10
typedef struct DSeqList
{
 int *elem;                           //指向存放数据数组的地址
 int length;                        //有效数据个数
 int listsize;                      //总格子数
}DSeqList,*PDSeqList;

//初始化
void InitSeqList(PDSeqList ps)
{
 assert(ps != NULL);
 if(ps == NULL)
 {
  return ;
 }
 ps->elem = (int *)malloc(INITSIZE*sizeof(int));
 ps->length = 0;
 ps->listsize = INITSIZE;
}

//判满
static bool IsFull(PDSeqList ps)
{
 return ps->length == ps->listsize;
}


//容量扩大到原来的2倍
static void Inc(PDSeqList ps)
{
 ps->elem = (int *)realloc(ps->elem,ps->listsize*2*sizeof(int));
 ps->listsize *= 2;
 //ps->length;不变
}


//插入
bool Insert(PDSeqList ps,int pos,int val)
{
 if(pos<0 || pos>ps->length)
 {
  return false;
 }
 if(IsFull(ps))
 {
  Inc(ps);
 }
 for(int i=ps->length-1;i>=pos;i--)
 {
  ps->elem[i+1] = ps->elem[i];
 }
 ps->elem[pos] = val;
 ps->length++;
 return true;
}


//查找,成功则返回下标,失败返回-1
int Search(PDSeqList ps,int key)
{
 for(int i=0;ilength;i++)
 {
  if(ps->elem[i] == key)
  {
   return i;
  }
 }
 return -1;
}


//删除
bool DeletePos(PDSeqList ps,int pos)
{
 if(pos<0||pos>=ps->length)
 {
  return false;
 }
 for(int i=pos;ilength-1;i++)
 {
  ps->elem[i]=ps->elem[i+1];
 }
 return true;
}
bool Deleteval_r(PDSeqList ps,int key)
{
 int index=Search(ps,key);
 if(index>=0)
 {
        DeletePos(ps,index);
  return true;
 }
 return false;
}
int GetLength(PDSeqList ps)//Size
{
 return ps->length;
}
bool IsEmpty(PDSeqList ps)
{
 return ps->length==0;
}


//清空数据
void Clear(PDSeqList ps)
{
 ps->length = 0;
}


//销毁顺序表
void Destroy(PDSeqList ps)
{
 free(ps->elem);
 ps->length=0;
 ps->listsize=0;
}


void Show(PDSeqList ps)
{
 for(int i=0;ilength;i++)
 {
  printf("%d ",ps->elem[i]);
 }
 printf("\n");
}

//返回总长度
int capacity(PDSeqList ps)
{
 return ps->listsize;
}

//得到一个指定下表的值
bool at(PDSeqList ps,int pos,int *val)
{
 if(pos<0||pos>=ps->length)
 {
  return false;
 }
 *val=ps->elem[pos];
 return true;
}

//得到最后一个有效元素的值
bool pop_back(PDSeqList ps,int *val)
{
 if(IsEmpty(ps))
 {
  return false;
 }
 if(at(ps,GetLength(ps)-1,val))
 {
  return true;
  ps->length--;
 }
}

//向最后一个有效元素的后面插入一个数
bool push_back(PDSeqList ps,int val)
{
 if(Insert(ps,GetLength(ps),val))
 {
  return true;
 }
 return false;
}

二、顺序表的应用
1、求两个集合的 并集  A=A U B

    算法分析
    (1)因为我们需要求的是A和B的并集,并且要把两个的并集放在集合A中,所以我们先定义两个不定长顺序表,这样再把B的元素添加到A中的时候不会因为空间不够而失败;
    (2)遍历B,利用Search函数按值查找,如果此时B中的元素与A中相同,就不用管,如果不同的话,就利用Insert插入函数,把B中没有的元素插入到A中;

     代码实现
#include
#include
#include
#include "dseqlist.h"
//A = AUB
void Merge(PDSeqList psA,PDSeqList psB)
{
 int tmp;
 int index;
 for(int i=0;i
 {
  tmp = psB->elem[i];
  GetElem(psB,i,&tmp);
  index = Search(psA,tmp);
  if(index < 0)
  {
   Insert(psA,0,tmp);
  }
 }
}
int main()
{
 DSeqList dsA;
 DSeqList dsB;
 InitSeqList(&dsA);
 InitSeqList(&dsB);
 int i;
 for(i=0;i<10;i++)
 {
  Insert(&dsA,i,i);
 }
 for(i=0;i<10;i++)
 {
  Insert(&dsB,i,i+5);
 }
 Show(&dsA);
 Show(&dsB);
 Merge(&dsA,&dsB);
 Show(&dsA);
 Show(&dsB);
}

2、求两个集合的 交集  A=A n B
算法分析
(1)因为这个交集表示的是两个集合的相同部分,那它的处理方式就和并集的时候不一样;交集是要把A的与B中不同删除,相同留下,所以我们这次要遍历A;
(2)利用seach 函数进行查找,如果A中的元素B中有,则不做处理,如果没有则把A中的这个元素删除;
注意:
         并集遍历B是因为最后集合保存在A中,而本来在A中的元素不需要做任何处理,不管在B中有没有,都要把A中的都留下来,因为是取的并集,这时候我们需要再B中搜索所有元素,这样才能把不同的全部添加到A中;
         交集却是要遍历A中的元素,这是因为交集要留下两个集合相同的部分,并把它存储到A中,所以这时候我们需要考虑的是A中所有的元素,如果和B中相同就留下,不同就删除,并不需要对B中每个元素都做处理,所以我们遍历的是A;

代码实现

void intersection(PDSeqList psA,PDSeqList psB)
{
 
 for(int i=0;i
 {
  int tmp;
  GetElem(psA,i,&tmp);
  int index=Search(psB,tmp);
  if(index<0)
  {
   if(DeletePos(psA,i)) i--;
  }
 }
}
int main()
{
 DSeqList dsA;
 DSeqList dsB;
 InitSeqList(&dsA);
 InitSeqList(&dsB);
 int i;
 for(i=0;i<10;i++)
 {
  Insert(&dsA,i,i);
 }
 for(i=0;i<10;i++)
 {
  Insert(&dsB,i,i+5);
 }
 Show(&dsA);
 Show(&dsB);
 intersection(&dsA,&dsB);
 Show(&dsA);
 Show(&dsB);
}


原创粉丝点击