顺序表的C实现

顺序表的C实现 - myswirl - MY BLOG
 
此顺序表仅供学习研究,实际应用可能需要进一步完善,例如空间限制等。例子程序中默认元素类型为int,最大存储空间为180,可直接在VC6.0编译通过,示例代码如下:

/*************************************************************
 * 顺序表的C实现 
 * 编译工具:VC6.0
 * 文件名:seqlist.c
 * 作者:MyLee
 * 日期:2008.04.13
 *************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int ElemType;
const int MAXLISTSIZE=180;    //预设的存储空间最大容量
typedef struct seqlist
{
    ElemType *data_address; //存储空间基址
    int listlength ;        //当前长度
    int listsize;            //允许的最大存储容量(以sizeof(ElemType)为单位)
}seqlist;                    //俗称顺序表

// 基本操作接口(函数声明)
int ListInsert(seqlist *L,int pos,ElemType e);
int LocateElem(seqlist *L, ElemType e, int (*compare)(ElemType, ElemType));
int ListEmpty(seqlist *L);
int ListFull(seqlist *L);
int UpdateElem(seqlist *L,int pos,ElemType e);
int ListDelete(seqlist *L,int pos);
int ListLength(seqlist *L);
void InitList(seqlist *L);
void PrintList(seqlist *L);
void DestroyList(seqlist *L);
void ClearList(seqlist *L);
ElemType GetElem(seqlist *L,int pos);

//构造一个最大存储容量为 maxsize 的空的顺序表 L
void InitList(seqlist *L) //
{
    printf("--------Start InitList()--------\n");  
    L->data_address = (ElemType *)malloc( MAXLISTSIZE * sizeof(ElemType) );
    if( L->data_address==NULL ) 
    {
        exit(1);                //存储分配失败,程序退出
    }
    L->listsize = MAXLISTSIZE;    //该顺序表可以存储元素的最大容量
    L->listlength = 0;            //顺序表的初始长度为0
    printf("--------End InitList()--------\n");      
}

// 在顺序表L中查找第1个值与 e 满足判定条件compare()的元素,
// 若找到,则返回其在 L 中的位序,否则返回0。
int LocateElem(seqlist *L, ElemType e, int (*compare)(ElemType, ElemType))
{
    int i = 1;        // i 的初值为第1元素的位序
    ElemType *p = L->data_address;    // p 的初值为第1元素的存储位置
    while (i <= L->listlength && !(*compare)(*p++,e))
    {
        ++i;    // 依次进行判定
    }
    if (i <= L->listlength)
    {
        return i;    // 找到满足判定条件的数据元素为第 i 个元素
    }else
    {
        return 0;    // 该线性表中不存在满足判定的数据元素
    }
}// LocateElem

//获取pos位置的元素的值  
ElemType GetElem(seqlist *L,int pos)
{
    if(pos<1 || pos > L->listlength)
    {
        printf("GetElem :: pos is illegal.\n");
        exit(1);
    }
    return (L->data_address[pos-1]);
}  

//替换pos位置元素的值
int UpdateElem(seqlist *L,int pos,ElemType e)
{
    if(pos<1 || pos>L->listlength){
        printf("pos is illegal!\n");
        return 0;
    }
    L->data_address[pos-1] = e;
    return 1;
}  

//若存储空间不满且1≤pos≤Listlength(L)+1,则在顺序表L的第pos个元素之前插入新的元素e且返回1,否则返回0.
int ListInsert(seqlist *L,int pos,ElemType e)
{    
    int j;
    if (pos < 1 || pos > L->listlength+1)    // 插入位置不合法,合法位置是 (1) 至 (表长+1)
    { 
        printf("ListInsert:::Error pos\n");
        return 0;
    }
    if (L->listlength >= L->listsize)        // 当前存储空间已满,无法插入
    {    
        printf("ListInsert:::Error full of Store Space\n");
        return 0;
    }
    for ( j=L->listlength-1; j >= pos-1; --j)
    {
        L->data_address[j+1] = L->data_address[j];    // 插入位置及之后的元素右移,
        //第表长个元素L->data_address[L->listlength-1] 到 第pos个元素L->data_address[pos-1]依次向后移
    }                    
    L->data_address[pos-1] = e;        // 插入e
    ++L->listlength;                // 表长增1
    return 1;
}

//打印顺序表,十个元素一行
void PrintList(seqlist *L)
{
    int n,i;
    n = ListLength(L);
    printf("*******************************************************************\n");  
    for(i=1;i<=n;++i)
    {
        printf("%6d",GetElem(L,i));
        if((i)%10==0)
            printf("\n");
    }
    printf("\n");  
    printf("*******************************************************************\n");  
}

//求表长,返回表中元素个数
int ListLength(seqlist *L)
{     
    return(L->listlength);   
}

//判断是否相等  
int equal(int x,int y)   
{   
    if(x==y)
    {   
        return 1; 
    }else 
    { 
        return 0;   
    }
}

//清空表元素
void ClearList(seqlist *L)
{     
    L->listlength = 0;   
}

//销毁顺序表
void DestroyList(seqlist *L)
{
    free(L->data_address);   
    L->listlength = 0;
    L->listsize = 0;
}

//判断顺序表是否为空
int ListEmpty(seqlist *L)
{
    if(L->listlength == 0)
    {
        return 1;
    }else
    {
        return 0;
    }
}

//判断顺序表是否已满
int ListFull(seqlist *L)
{
    if(L->listlength==L->listsize)
    {
        return   1;
    }else
    {
        return   0;
    }
}

// 若1≤pos≤Listlength(L),则从顺序表 L 中删除第 pos 个元素且返回 1,否则返回 0
int ListDelete(seqlist *L,int pos)
{
    int i;
    if( ListEmpty(L) ){
        printf("ListDelete:::seqlist is Empty!");
        return 0;
    }
    
    if(pos<1 || pos>L->listlength)
    {
        printf("ListDelete:::pos is illegal!");
        return 0;
    }
    
    for(i=pos;i<L->listlength;++i)
    {
        L->data_address[i-1] = L->data_address[i];
    }
    L->listlength--;
    return 1;
}

// 若1≤pos≤Listlength(L),则从顺序表 L 中删除第 pos 个元素且返回 1,否则返回 0, *e为被删除元素的值
int ListDeleteE(seqlist *L,int pos,ElemType *e)
{
    int i;
    if( ListEmpty(L) ){
        printf("ListDeleteE:::seqlist is Empty!\n");
        return 0;
    }
    
    if(pos<1 || pos>L->listlength)
    {
        printf("ListDeleteE:::pos is illegal!\n");
        return 0;
    }
    i=pos;
    *e = L->data_address[i-1];//将要删除的值赋给e
    for(;i<L->listlength;++i)
    {
        //从第pos+1个元素(L->data_address[pos])到第表长个元素 (L->data_address[L->listlength-1])依次向前移
        L->data_address[i-1] = L->data_address[i]; 
    }
    L->listlength--; //表长减一
    return 1;
}
/*
已知集合 A 和 B,求两个集合的并集,使 A=A∪B,且 B 不再单独存在
将所有在线性表LB中但不在LA中的数据元素插入到 LA 中,
算法执行之后,线性表 LB 不再存在。
*/
void Union(seqlist *LA, seqlist *LB)
{
    ElemType e;
    int La_len = ListLength(LA);    //求得线性表 LA 的长度
    while (ListEmpty(LB) == 0)        //依次处理 LB 中元素直至 LB 为空表止
    {    
        ListDeleteE(LB,1,&e);        //从 LB 中删除第1个数据元素并赋给 e
        if (LocateElem(LA,e,equal) == 0)
        {
            ListInsert(LA,++La_len,e);// 当LA中不存在和 e 值相同的数据元素时进行插入
        }
    }
    DestroyList(LB);// 销毁线性表 LB 
}


/* 已知一个"非纯集合" B,试构造一个集合 A,使 A 中只包含 B 中所有值各不相同的数据元素。
 * 构造线性表LA,使其只包含LB中所有值不相同的数据元素,算法不改变线性表LB 
 */
void Purge(seqlist *LA, seqlist *LB)
{
    int i;
    ElemType e;
    int La_len = 0;
    int Lb_len = ListLength(LB);        // 求线性表 LB 的长度
    InitList(LA);                        // 创建一个空的线性表 LA
    for (i = 1; i <= Lb_len; i++)        // 依次处理 LB 中每个元素
    {
        e = GetElem(LB, i);                // 取 LB 中第 i 个数据元素赋给 e
        if (LocateElem(LA, e, equal) == 0)
        {
            ListInsert(LA, ++La_len, e);// 当 LA 中不存在和 e 值相同的数据元素时进行插入
        }
    } 


/*
  判别两个集合是否相等。
  两个集合相等的充分必要条件是它们具有相同的元素。
  当以线性表表示集合时,两个线性表的长度应该相等,
  且表中所有数据元素都能一一对应,
  但相同的数据元素在各自的线性表中的"位序"不一定相同。
    由此,"判别两个线性表中的数据元素是否完全相同"的算法的
  基本思想为:
  首先判别两者的表长是否相等;在表长相等的前提下,
  如果对于一个表中的所有元素,都能在另一个表中找到和它相等的元素的话,
  便可得到"两个线性表表示的集合相等"的结论;
  反之,只要有一个元素在另一个表中不能找到相等元素时,便可得出"不等"的结论。
  
这个算法是否在任何情况下都正确,会不会有例外的情况?  
当然,这个算法思想还有一个前提是,已知集合符合集合论中的约定"集合中的元素都是彼此相异的"。估计你也想到了吧。  
    
如果"集合"中的元素不能保证都相异,那么这个问题的算法应如何写?   
除了判别每个 LA 中的元素在 LB 中都存在之外,还应反过来判别 LB 中每个元素都能在 LA 中找到相同者。你不妨试试写一下这个算法。      
*/


//若线性表 LA 和 LB 不仅长度相等,且所含数据元素也相同,则返回TRUE,否则返回FALSE.
int isEqual(seqlist *LA, seqlist *LB)
{
    ElemType e;
    int La_len = ListLength(LA);
    int Lb_len = ListLength(LB);
    if ( La_len != Lb_len )
    {
        return 0; // 两表的长度不等
    }else
    {
        int i = 1;
        while ( i<= La_len )
        {
            e = GetElem( LA, i);    // 取得 LA 中一个元素
            if ( LocateElem(LB, e, equal) != 0 )
            {
                i++;    // 依次处理下一个
            }else
            {
                return 0;    // LB中没有和该元素相同的元素
            }
        } 
        return 1;
    } 
}


//主程序体
void main()
{
    int i;
    seqlist L;
    ElemType e;
    InitList(&L);                    //初始化顺序表
    srand((unsigned int)time(0));    //srand(seed)用于给rand()函数设定种子。
    for(i=1;i<=30;++i)
    {
        ListInsert(&L,i,rand()%30);    //插入50个元素
    }
    
    PrintList(&L);
    printf("length:%d, listSize:%d \n",L.listlength,L.listsize);

//  DestroyList(&L);
//     PrintList(&L);
//  printf("length:%d, listSize:%d \n",L.listlength,L.listsize);

    if(LocateElem(&L,0,equal) == 0)
    {
        printf("此顺序表中没有元素值为0 \n");
    }else
    {
        printf("第一个值为0的元素位置: %d \n",LocateElem(&L,0,equal));
    }  
    
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值