您的位置:首页 > 理论基础 > 数据结构算法

(数据结构第二章)线性表的实现

2015-04-10 22:22 309 查看
///顺序表:::
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define ERROR -1
#define bool char
#define ture 1
#define false 0
#define OVERFLOW -2
#define OK 1
#define LIST_INIT_SIZE 100 ///线性表存储空间的初始分配量
#define LISTINCREMENT 10 ///线性表存储空间分配增量
///说明开始向全用c写,太鸡巴麻烦了,还是换c++吧
typedef struct
{
    int *elem;      /// 存储空间基址
    int length;     /// 当前长度
    int listsize;   /// 当前分配的存储容量(以sizeof(int)为单位)
}SqList;
bool InitList_Sq(SqList* L) /// 构造一个空的线性表L
{
    (*L).elem = (int *)malloc(LIST_INIT_SIZE * sizeof(int));
    if(!(*L).elem) exit(OVERFLOW);     /// 存储分配失败
    (*L).length = 0;                   /// 当前长度,当前为空表,0
    (*L).listsize = LIST_INIT_SIZE;    /// 初始化存储容量
    return OK;
}//InitList_Sq
void Scanf_Sq(SqList &L,int n)
{
    /// 输入n个值放入顺序表
    printf("请输入顺序表:");
    for(int i=0;i<n;i++)
        scanf("%d",&L.elem[i]);
    L.length = n;
    return ;
}
void Printf_Sq(SqList &L)
{
    /// 输出整个顺序表,用2个空格隔开
    printf("顺序表为:");
    for(int i=0;i<L.length;i++)
        printf("%d  ", L.elem[i]);
    printf("\n");
}
void DestroyList(SqList &L)
{
    /// 销毁线性表
    if(L.elem)      /// 如果L.elem里分配了值的话
        free(L.elem);
    L.elem = NULL;
    return;
}
void ClearList(SqList &L)
{
    /// 将L置为空表
    if(L.length)
    L.length = 0;
    return ;
}
bool ListEmpty(SqList L)
{
    /// 判空
    /// 若L为空表,返回true,否则返回false
    return !L.length;
}
int ListLength(SqList L)
{
    /// 返回L中数据元素的个数
    return L.length;
}
bool GetElem(SqList L,int i,int &e)
{
    /// 1<=i<=ListLength(L)
    /// 用e返回L中的第i个数据元素
    if( 1 <= i || i <= L.length){
        e = L.elem[i-1];
        return OK;
    }
    else return false;
}
bool ListInsert_Sq(SqList &L, int i, int e)
{
    ///在顺序线性表L中第i个位置之前插入新的元素e
    ///i的合法值为1<=i<=ListLength_Sq(L)+1
    if(i < 1 || i > L.length + 1) return ERROR;     ///i值不合法
    if(L.length >= L.listsize){     /// 当前存储空间已满增加分配
        int *newbase = (int *)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(int) );
        if(!newbase) exit(OVERFLOW);    ///存储分配失败
        L.elem = newbase;   ///新基址
        L.listsize += LISTINCREMENT;    ///增加存储容量
    }
    int *q = &(L.elem[i-1]); ///注意,顺序表和数组一样,i个元素是L.elem[i-1]
    for(int *p = &(L.elem[L.length-1]); p>=q ;p--) *(p+1) = *p;
                            /// 插入位置级及后的元素右移
    *q = e; /// 插入e
    L.length += 1; /// 表长增长1
    return OK;
}
bool PriorElem(SqList L, int cur_e, int & pre_e)
{
    /// 返回cur_e的前趋
    /// 若cur_e是L的数据元素,且不是第一个,用pre_e返回它的前驱
    for(int i=1;i<L.length;i++)
    if(L.elem[i] == cur_e) {
        pre_e = L.elem[i-1];
        return OK;
    }
    return false;
}
bool NextElem(SqList L, int cur_e, int & next_e)
{
    /// 返回cur_e的前趋
    /// 若cur_e是L的数据元素,且不是最后一个,用pre_e返回它的后继
    for(int i=0;i<L.length-1;i++)
    if(L.elem[i] == cur_e) {
        next_e = L.elem[i+1];
        return OK;
    }
    return false;
}
bool ListDelete_Sq(SqList &L, int i, int &e)
{
    /// 在顺序线性表L中删除第i个元素,并用e返回其值
    /// i的合法范围1<=i<=ListLength_Sq(L)
    if(i < 1 || i > L.length) return ERROR; /// i值不合法
    int *p = &(L.elem[i-1]);    ///     p为被删除元素的位置
    e = *p;                     ///     被删除元素的值赋给e
    int *q = L.elem + L.length -1;     ///  表尾元素的位置
    for( p++ ; p<=q ;p++) *(p-1) = *p; ///  被删除之后的元素左移
    L.length--; /// 表长减1
    return OK;
}
bool compare(int a,int b){ return a>b; }
int LocateElem_Sq(SqList &L, int e, bool (* compare)(int ,int ) )
{
    /// 在顺序表L中查找第一个值与e满足compare()的元素的位序
    /// 若找到返回位序,否则返回0
    int i = 1;  ///i的初值,为第一个元素的位序
    int * p = L.elem; /// p的初值为第一个元素的存储位置
    while (i <= L.length && !(* compare)(*p++,e))  ++i;
    if(i <= L.length) return i;
    return 0;
}// LocateElem_Sq

void MergeList_Sq(SqList La, SqList Lb, SqList &Lc)
{
    /// 已知顺序表La和Lb的元素按值非递减排列
    /// 归并La和Lb得到的新的顺序表Lc,Lc的元素也是按非递减排列的
    int *pa = La.elem, *pb = Lb.elem;
    Lc.listsize = Lc.length = La.length + Lb.length;
    int *pc = Lc.elem = (int *)malloc(Lc.listsize*sizeof(int));
    if(!Lc.elem) exit(OVERFLOW);    /// 存储分配失败
    int *pa_last = La.elem + La.length -1;
    int *pb_last = Lb.elem + Lb.length -1;
    while(pa <= pa_last && pb <= pb_last){  /// 归并
        if(*pa <= *pb) *pc++ = *pa++;
        else *pc++ = *pb++;
    }
    while(pa <= pa_last) *pc++ = *pa++; /// 插入La中的剩余元素
    while(pb <= pb_last) *pc++ = *pb++; /// 插入Lb中的剩余元素
    return ;
}// MergeList_Sq
bool visit(int &x)
{
    x+=1;
    return OK;
}
bool ListTraverse(SqList L, bool visit(int & x))
{
    /// 依次对L的每个数据元素调用visit(),一旦visit()调用失败,操作失败
    /// 我写的是对每个元素进行+1操作
    for(int i=0;i<L.length;i++)
        if( !(* visit )( L.elem[i] ) ) return false;
    return OK;

}
bool Equal(int a,int b){ return a== b; }
void union_Sq(SqList &La, SqList Lb)
{
    /// 将所有线性表Lb中的但不在La中的数据元素插入到La中
    int cur_e=0;
    int La_len = ListLength(La), Lb_len = ListLength(Lb);   ///求线性表的长度
    for(int i=1;i<=Lb_len;i++){
        GetElem(Lb,i,cur_e);        /// 驱Lb中第i个元素赋给e
        if(!LocateElem_Sq(La,cur_e,Equal)) ListInsert_Sq(La, ++La_len,cur_e);
                                    /// La中不存在和e相同的数据元素,则插入
    }
}//union
void MergeList(SqList La, SqList Lb, SqList &Lc)
{
    /// 已知线性表La和Lb中的元素按非递减排列
    /// 归并La和Lb得到新的线性表Lc,Lc的数据元素也按非递减排列
    InitList_Sq(&Lc);
    int i = 1,j = 1, k = 0;
    int ai =0, bj = 0;
    int La_len = ListLength(La), Lb_len = ListLength(Lb);
    while( (i<=La_len) && (j <= Lb_len) ){ /// La和Lb均为非空
        GetElem(La,i,ai); GetElem(Lb,j,bj);
        if(ai <= bj) { ListInsert_Sq(Lc, ++k, ai); ++i; }
        else { ListInsert_Sq(Lc, ++k, bj); ++j; }
    }
    while(i <= La_len) {
        GetElem(La,i,ai);
        ListInsert_Sq(Lc, ++k, ai); ++i;
    }
    while(j <= Lb_len) {
        GetElem(Lb,j,bj);
        ListInsert_Sq(Lc, ++k, bj); ++j;
    }
}//MergeList
int main()
{
    SqList L; /// 定义一个顺序表
    InitList_Sq(&L); ///初始化顺序表L
    printf("请输入需要输入顺序表的个数n:");
    int n;
    scanf("%d",&n);///
    Scanf_Sq(L,n);///  从0开始读入n个顺序表
    Printf_Sq(L); /// 输出当前的顺序表
    printf("\n");

    /// 测试插入
    ListInsert_Sq(L,6,6);
    Printf_Sq(L);
    printf("\n");

    /// 测试删除
    int e;
    ListDelete_Sq(L,6,e);
    Printf_Sq(L);
    printf("被删除的元素是:%d\n",e);
    printf("\n");

    /// 测试第一个与e大或者小的数,返回其位序
    printf("请输入要判断位序的e:");
    scanf("%d",&e);
    printf("%d\n",LocateElem_Sq(L,e,compare) );
    printf("\n");

    ///测试归并
    SqList Lc,Lb;
    InitList_Sq(&Lb);
    InitList_Sq(&Lc);
    printf("请输入需要输入顺序表Lb的个数n:");
    scanf("%d",&n);
    Scanf_Sq(Lb,n);
    MergeList_Sq(L,Lb,Lc);
    Printf_Sq(Lc);
    DestroyList(Lb);
    DestroyList(Lc);
    printf("\n");

    ///测试前驱,后继
    int pre_e,next_e,cur_e;
    printf("请输入要判断前驱后继的cur_e:");
    scanf("%d",&cur_e);
    if( PriorElem(L,cur_e,pre_e) ) printf("%d的前驱是:%d\n",cur_e,pre_e);
    else printf("该元素没有前驱\n");
    if( NextElem(L,cur_e,next_e) ) printf("%d的后继是:%d\n",cur_e,next_e);
    else printf("该元素没有后继\n");

    /// 测试visit()
    ListTraverse(L, visit);
    Printf_Sq(L);

    ///测试Clear和Empty和Length和GetElem
    int i;
    printf("请输入i:");
    scanf("%d",&i);
    if( GetElem(L,i,e) ) printf("第%d个元素是%d\n",i,e);
    else printf("该角标%d不在范围内\n",i);
    printf("当前表长度为:%d\n",ListLength(L));

      ///测试union
    InitList_Sq(&Lb);
    printf("输入集合B的个数n:\n");
    scanf("%d",&n);
    Scanf_Sq(Lb,n);
    union_Sq(L,Lb);
    Printf_Sq(L);
    printf("\n");

    /// 测试MergeList
    MergeList(L, Lb, Lc);
    Printf_Sq(Lc);

    ///清空表
    printf("下面进行清空表操作\n");
    ClearList(L);
    if(ListEmpty(L)) printf("L为空表\n");
    else printf("L不是空表\n");
    printf("\n");

    DestroyList(L);

    printf("TO BE END\n");
    return 0;
}
///调试过程中出现了Bug
///DestroyList(Lb)和DestroyList(Lc)都出现了错误
///找了一番竟然是没有初始化,但是没初始化竟然能用,就是销毁的时候错了
///没初始化,L.elem里应该没有值吧,那就是越界访问了,if(L.elem)怎么又能进去呢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: