【数据结构】01顺序表

语言:C语言

IED:VS Code

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

#define TRUE 1
#define FALSE 0
#define INIT_SIZE 10
#define INCREMENT_SIZE 5
#define OK 1
#define ERROR 0

typedef int Elemtype;
typedef int Status;

/* 顺序表存储结构 */
typedef struct{
    Elemtype *elem;     //存储空间基地址
    int length; //当前长度
    int size;   // 当前分配的表长大小
}SqList;

/* 初始化一个空的顺序表 基地址 分配空间*/
Status InitList(SqList *L){
    L->elem = (Elemtype *) malloc(INIT_SIZE * sizeof(Elemtype));
    if(!L->elem){
        return ERROR;
    }
    L->length = 0;
    L->size = INIT_SIZE;
    return OK;
}

/* 销毁顺序表 */
Status DestroyList(SqList *L){
    free(L->elem);
    L->length = 0;
    L->size = 0;
    return OK;
}


/* 清空顺序表 表长置为0 */
Status ClearList(SqList *L){
    L->length = 0;
    return OK;
}

/* 判断顺序表是否为空 */
Status IsEmpty(const SqList L){
    if(0 == L.length){
        return TRUE;
    }
    else{
        return FALSE;
    }
}

/* 获取长度 */
int GetLength(const SqList L){
    return L.length;
}

/* 比较两个元素 */
Status compare(Elemtype e1, Elemtype e2){
    if(e1 == e2){
        return 0;
    }
    else if(e1 < e2){
        return -1;
    }
    else return 1;
}

/* 插入元素 */

Status InsertElem(SqList *L, int i, Elemtype e){
    Elemtype *new;
    if(i < 1 || i > L->length + 1){
        return ERROR;
    }
    //如果存储空间不足,增加空间,使用realloc(*ptr, new_size)函数重新分配空间
    //ptr是需要被重新分配的内存块,它是之前被malloc或calloc分配的,如果是空指针则会分配一个新内存并返回指针
    if(L->length >= L->size){
        new = (Elemtype*) realloc(L->elem, (L->size + INCREMENT_SIZE) * sizeof(Elemtype));
        if(!new){
            return ERROR;
        }
        L->elem = new;
        L->size +=INCREMENT_SIZE;
    }
    
    //插入元素前,利用两个指针将后面的元素后移;
    Elemtype *p = &L->elem[i-1];
    Elemtype *q = &L->elem[L->length-1];
    for(;q >= p; q--){
        *(q + 1) = *q;
    }
    *p = e;
    ++L->length;
    return OK;
}




/* 删除元素并返回其元素值: 使用指针向前移动元素 */
Status DeleteElem(SqList *L, int i, Elemtype *e){
    if(i < 1 || i > L->length ) {
        return ERROR;
    }
    Elemtype *p = &L->elem[i-1];
    *e = *p;
    for(; p < &L->elem[i-1]; p++){
        *(p) = *(p+1);
    }
    --L->length;
    return OK;
}


/* 查找元素根据位置获取元素 */
Status GetElem(const SqList L, int i, Elemtype *e){
    if(i < 1 || i > L.length-1){
        return ERROR;
    }
    *e = L.elem[i-1];
    return OK;
}

/* 查找元素 */
Status FindElem(const SqList L, Elemtype e, Status(*compare)(Elemtype, Elemtype)){
    int i;
    for(i = 0; i < L.length; i++){
        if(!(*compare)(L.elem[i], e)){
            return i + 1;
        }
    }
    if(i >= L.length){
        return ERROR;
    }
}

/* 查找前驱元素 */
Status PreElem(const SqList L,Elemtype cur_e,Elemtype *pre_e){
    int i;
    for(i = 0; i < L.length; i++){ //按位置迭代查找
        if(cur_e == L.elem[i]){
            if(i != 0){
                *pre_e = L.elem[i-1];
            }
            else return ERROR;
        }
    }
    if(i >= L.length) { //元素无此前驱元素
        return ERROR;
    }
    //return OK;//自己加的这行
}

/* 查找后继元素 */
Status NextElem(const SqList L, Elemtype cur_e, Elemtype *next_e){
    int i;
    for(i = 0; i < L.length; i++){
        if(cur_e == L.elem[i]){
            if(i < L.length - 1){ 
                *next_e = L.elem[i+1];
                return OK;
            }
            else return ERROR;
        }
    }
    if(i >= L.length - 1){
        return ERROR;
    }
}

/* 访问元素 */
void visit(Elemtype e){
    printf("%d",e);
}

/* 遍历线性表 使用 visit() */
Status TraverseList(const SqList L, void (*visit)(Elemtype)){
    int i;
    for(i = 0; i<L.length - 1; i++){
        visit(L.elem[i]);
    }
    return OK;
}

/* 主函数 */

int main(){
    SqList L;
    if(InitList(&L)){
        Elemtype e;
        printf("init_success\n");
        int i;
        for(i = 0; i < 10; i++){
            InsertElem(&L, i + 1, i);
        }
        printf("length is %d\n",GetLength(L));
        if(GetElem(L, 1, &e)){//获取第一个元素
            printf("The first element is %d\n", e);
        }
        else{
            printf("element is not exsit\n");
        }
        if(IsEmpty(L)){//判断是否为空
            printf("list is empty\n");
        }
        else {printf("list is not empty\n");}
        printf("The 5 at %d\n", FindElem(L, 5, *compare));
        PreElem(L, 6, &e); // 查找元素 6 的前驱元素
        printf("The 6's previous element is %d\n", e);
        NextElem(L, 6, &e); // 查找元素 6 的后继元素
        printf("The 6's next element is %d\n", e);
        DeleteElem(&L, 1, &e); // 删除 1 元素
        printf("delete first element is %d\n", e);
        printf("list:");
        TraverseList(L,visit);
        if (DestroyList(&L)){ // 销毁线性表
            printf("\ndestroy_success\n");
        }
    }
}

 运行结果:

shiyanlou:project/ $ gcc -o 2.1 2.1.c                                                      [18:29:32]
shiyanlou:project/ $ ./2.1                                                                 [18:45:14]
init_success
length is 10
The first element is 0
list is not empty
The 5 at 6
The 6's previous element is 5
The 6's next element is 7
delete first element is 0
list:1 2 3 4 5 6 7 8 9 
destroy_success
shiyanlou:project/ $      

练习题目(待补充。。。):

//练习题目||||||||||||
/* T01 :将所有奇数移动到偶数前面(要求时间最少,辅助空间最少)
思想:从左往右找到偶数L.data[i],从右往左找到奇数L.data[j]
将两者交换,这个过程直到i大于j为止
 */
void move(SqList &L){
    int i = 0, j = L.length-1, k;
    Elemtype temp;
    while(i <= j){
        while(L.elem[i]%2 == 1){
            i++;//i指向一个奇数
        }
        while(L.elem[j]%2 == 0){
            j--;//j指向一个偶数
        }
        if(i < j){
            temp = L.elem[i];//
            L.elem[i] =L.elem[j];
            L.elem[j] = temp;
        }
    }
}

/* T02 设计一个高效算法,将顺序表L中的所有元素逆置
思想:扫描顺序表的前半部分元素,对于元素L.data[i] 将其与对应元素L.data[L.length-i-1]交换 
*/
void reverse(SqList &L){
    int i;
    Elemtype x;
    for(i = 0;i<L.length/2;i++){
        x = L.elem[i];
        L.elem[i] = L.elem[L.lenght-i-1];
        L.elem[L.lenght-i-1] = x;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值