【数据结构】顺序存储线性表C语言实现

* 文件名:顺序存储的线性表

* 基本操作:

* InitList(&L) //构造一个空的线性表L

* DestoryList(&L) //删除一个线性表

* ClearList(&L) //将线性表重置为空表

* ListEmpty(L) //线性表的探空操作

* ListLength(L) //返回L中元素的个数

* GetElem(L, i, &e) //查找并返回第i个元素

* LocateElem(L, e, compare()) //线性表中第一个满足compare的元素

* PriorElem(L, cur_e, &pre_e) //若cur_e是线性表中元素且不是第一个,则用pre_e返回它的前驱

* NextElem(L, cur_e, &next_e) //若cur_e是线性表中元素且不是最后一个,则用pre_e返回它的后继

* ListInsert(&L, i, e) //在第i个元素之前(i-2)插入新元素e

* ListDelete(&L, i, &e) //删除L的第i个元素,并用e返回其值

* ListTraverse(L, visit()) //对每个元素用visit()进行遍历

* 下面的两个操作是书上对线性表应用的举例

* union(&La, Lb) //将Lb中不属于La的元素插入La中

* MergeList(La, Lb, &Lc) //假设La和Lb都有序,将他们归并成Lc并且也有序

* 特点:

* 顺序结构的线性表可以直接访问某个位置的元素

* 但是如果内存空间不够的话需要重新分配内存,比较麻烦

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef  int  ElemType;   //这一行用来定义数据类型
typedef  int  Status;     //用来返回操作状态,成功返回1,失败返回0

#define OK  1
#define FAILED 0
#define TRUE 1
#define FALSE 0

#define LIST_INIT_SIZE  100 //线性表存储空间的初始分配量
#define LIST_INC  10        //线性表存储空间每次增加的空间数量

typedef struct {
    ElemType    *elem;  //存储空间基址
    int         length; //当前长度(元素个数)
    int         listsize;   //当前分配的存储容量
}List, *L;

//构造一个新的线性表
Status InitList(List &L){
    L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if(!L.elem){
        printf("malloc failed\n");
        return FAILED;
    }
    L.length = 0;   //当前链表中没有元素
    L.listsize = LIST_INIT_SIZE;    //链表长度赋初值
    return OK;
}//InitList

//删除一个线性表
Status DestoryList(List &L){
    free(&L);
    return OK;
}//DestoryList

//将线性表变成一个空表
//将所有单元初始化为0
Status ClearList(List &L){
    for(int idx = 0; idx < L.length; idx++){
        L.elem[idx] = 0;
    }
    return OK;
}

//线性表的探空操作
Status ListEmpty(List L){
    if(L.length == 0){
        return TRUE;    //线性表是空的
    } else if(L.length == 1){
        return FALSE;   //线性表不是空的
    }
}

//返回L中元素的个数
int ListLength(List L){
    return L.length;
}

//返回链表中下标为i的元素
ElemType GetElem(List L, int i){
    if(L.length < i){
        printf("Get error\n");
        return -1;
    }
    return L.elem[i];
}

//查找线性表中第一个和e相等的元素,并且返回其下标号
//如果没有找到就返回-1
int LocateElem(List L, ElemType e){
    if(ListEmpty(L) == TRUE){
        //线性表是空的
        printf("the list is empty\n");
        return -1;
    }
    for(int idx = 0; idx<L.length; idx++){
        if(L.elem[idx] == e){
            return idx;
        }
    }
    printf("can not find e in list\n");
    return -1;
}

//找e的前驱元素,如果存在则返回其下标
//如果不存在则返回-1
int PriorElem(List L, ElemType e){
    if(ListEmpty(L) == TRUE){
        printf("ths list is empty\n");
        return -1;
    }
    for(int idx = 0; idx<L.length; idx++){
        if(L.elem[idx] == e){
            if(idx == 0){
                printf("e has no prior in ths list\n");
            } else {
                return (idx-1);
            }
        }
    }
    printf("can not find prior of e\n");
    return -1;
}

//找e的后继元素
int NextElem(List L, ElemType e){
    if(ListEmpty(L) == TRUE){
        printf("ths list is empty\n");
        return -1;
    }
    for(int idx = 0; idx<L.length; idx++){
        if(L.elem[idx] == e){
            if(idx+1 >= L.length){  //这里其实只要等于就行了
                printf("e has no next in ths list\n");
            } else {
                return (idx+1);
            }
        }
    }
    printf("can not find next of e\n");
    return -1;
}

//插入元素
//在位置i插入元素,并且将i及i后的所有元素后移一位
Status ListInsert(List &L, ElemType e, int i){
    if(i > L.length){   //插入位置太后面了,必须按照顺序来
        printf("insert error\n");
        return FAILED;
    }
    if(L.length >= L.listsize){ //内存空间不够,需要重新分配内存
        ElemType* newBase = (ElemType *)realloc(L.elem, (L.listsize+LIST_INC)*sizeof(ElemType));
        if(!newBase){
            printf("realloc failed\n");
            return FAILED;
        }
        L.elem = newBase;
        L.listsize += LIST_INC;
    }
    if(i == L.length){  //如果是插入在最后一个位置,那么直接插入就行了
        L.elem[i] = e;
        return OK;
    }
    for(int idx = L.length-1; idx>=i; idx--){
        L.elem[idx] = L.elem[idx+1];
    }
    L.elem[i] = e;
    L.length++;
    return OK;
}

//删除下标为i的元素,并用e返回
//后面元素前移一格
Status ListDelete(List &L, int i, ElemType &e){
    if(i >= L.length){
        printf("there is no such elem\n");
        return FAILED;
    }
    e = L.elem[i];
    for(int idx = i+1; idx<L.length; idx++){
        L.elem[idx] = L.elem[i-1];
    }
    L.elem[L.length-1] = 0;
    L.length--;
    return OK;
}

//遍历线性表中所有元素
Status ListTraverse(List L){
    if(L.length == 0){
        printf("there is no elem in the list\n");
        return FAILED;
    }
    for(int idx = 0; idx<L.length; idx++){
        if(idx != 0){
            printf(" ");
        }
        printf("%d", L.elem[idx]);
    }
    printf("\n");
    return OK;
}

//将Lb中不属于La的元素插入La中
Status ListUnion(List &La, List Lb){
    int La_len = ListLength(La);
    int Lb_len = ListLength(Lb);
    for(int i = 0; i < Lb_len; i++){
        ElemType e = GetElem(Lb, i);
        if(LocateElem(La, e) != -1){    //在线性表La中没有这个元素
            //则将e插入线性表中
            ListInsert(La, e, La_len);
        }
    }
    return OK;
}

//假设La和Lb都有序,将他们归并成Lc并且也有序
//假设是按照递增的顺序排序的
Status MergeList(List La, List Lb, List &Lc){
    InitList(Lc);   //初始化Lc
    int La_len = ListLength(La);
    int Lb_len = ListLength(Lb);
    int i=0, j=0;
    int idx = 0;    //这是Lc线性表的指针
    while((i<La_len) && (j<Lb_len)){    //La和Lb均非空
        ElemType ea = GetElem(La, i);
        ElemType eb = GetElem(Lb, j);
        if(ea < eb){
            ListInsert(Lc, ea, idx++);
            i++;
        } else {
            ListInsert(Lc, eb, idx++);
            j++;
        }
    }
    while(i<La_len){
        ElemType ea = GetElem(La, i);
        ListInsert(Lc, ea, idx++);
        i++;
    }
    while(j<Lb_len){
        ElemType eb = GetElem(Lb, j);
        ListInsert(Lc, eb, idx++);
        j++;
    }
    return OK;
}
发布了130 篇原创文章 · 获赞 151 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/haohulala/article/details/94828340