【数据结构】02 单链表

 IDE:VSCode

语言:C语言

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

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2

typedef int Elemtype;
typedef int Status;

/* 存储结构 */
typedef struct LNode{
    Elemtype data;//数据域
    struct LNode *next;//指针域
}LNode, *LinkList; //*LinkList 为LNode类型的指针,当我们定义LNode *p时,可以用 LinkList p 进行替换

/* 初始化链表 
1.生成新结点做头结点,用头指针L指向头结点
2.头结点的指针域置空
 */
Status InitList(LinkList *L){
    *L = (LinkList) malloc(sizeof(LNode));
    if(!L){
        exit(OVERFLOW);
    }
    (*L)->next = NULL;// (*L)
}

/* 销毁链表
1.创建一个新的空表
2.释放原链表的空间
3.将空表赋值给原来的链表
 */
 void DestroyList(LinkList *L){
     LinkList temp;
     while(*L){
         temp = (*L)->next;
         free(*L);
         *L = temp;
     }
 }


/* 清空链表 DestroyList() L->next */
void ClearList(LinkList L){
    LinkList p = L->next;
    L->next = NULL;
    DestroyList(&p);
}

/* 判断是否为空 L->next */
Status isEmpty(LinkList L){
    if(L->next){
        return FALSE;
    }
    else{
        return TRUE;
    }
}

/* 获取长度 p=L->next*/
int GetLength(LinkList L){
    int i = 0;
    LinkList p = L->next;
    while(p){
        i++;
        p = p->next;
    }
    return i;
}

/* 单链表在第i个位置插入 
1.申请结点s,p; p从头结点遍历至第i-1个位置
2.新结点s存放元素e
3.s->next 指向p->next;
  p->next 指向s;
*/                
Status InsertElem(LinkList L, int i,Elemtype e){ 
    int j = 0;
    LinkList s, p = L;
    while(p && j < i - 1){
        j++;
        p = p->next;
    }
    if(!p || j > i-1){// j>i-1说明位置不对
        return ERROR;
    }
    s = (LinkList) malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}      

/* 删除第i个元素
1.使用结点p,q, p指向头结点L
2.p遍历至第i-1个元素,q指向第i个元素(q=p->next)
3.p->next 指向 q->next; *e=q->data; free(q);
 */

Status DeleteElem(LinkList L, int i, Elemtype *e){
    int j = 0;
    LinkList q, p = L;
    while(p && j < i-1){
        j++;
        p = p->next;
    }
    if(!p || j > i-1){
        return ERROR;
    }
    q = p->next;
    p->next = q->next;
    *e = q->data;
    free(q);
    return OK;
 }
 
 /* 根据位置获取元素 
 1.p指针指向头结点的下一个元素
 */
Status GetElem(LinkList L, int i,Elemtype *e){
    int j =1;
    LinkList p=L->next;
    while(p && j < i){//直到j==i
        j++;
        p = p->next;
    }
    if(!p || j > i){
        return ERROR;
    }
    *e = p->data;
    return OK;
}

/* 比较两个元素是否相等 相等为0 大于为1 小于为-1*/
Status  compare(Elemtype e1,Elemtype e2){
    if(e1 == e2){return 0;}
    else if(e1 > e2) {return 1;}
    else {return -1;}
}


/* 查找元素的指定位置 */
int FindElem(LinkList L,Elemtype e, Status (*cpmpare)(Elemtype,Elemtype)){
    int i = 0;
    LinkList p = L->next;
    while(p){
        i++;
        if(!compare(p->data,e)){//相等时返回0,a>b返回1,小于返回-1
            return i;
        }
        p = p->next;
    }
    return 0;
}

/* 获取前驱元素 
1.指针p用于遍历,指针q指向p->next;
2.如果q->data == cur_e
    前驱元素就是 p->data
*/
Status PreElem(LinkList L,Elemtype cur_e,Elemtype *pre_e){
    LinkList q, p = L->next;
    while(p->next){
        q = p->next;
        if(q->data == cur_e){
            *pre_e = p->data;
            return OK;
        }
        p = q;
    }
    return ERROR;
}

/* 获取后继元素 */
Status NextElem(LinkList L, Elemtype cur_e,Elemtype *next_e){
    LinkList p = L->next;
    while(p->next){
        if(p->data == cur_e){
            *next_e = p->next->data;
            return OK;
        }
        p = p->next;
    }
    return ERROR;
}



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

 /* 遍历链表 */
 Status TraverseList(LinkList L, void (*visit)(Elemtype)){
     LinkList p = L->next;
     while(p){
         visit(p->data);
         p = p->next;
     }
 }

int main(){
    LinkList L;
    InitList(&L);
    Elemtype e;
    int i;
    if (L){
        printf("init success\n");
    }

    if (isEmpty(L)){ // 判断链表是否为空
        printf("list is empty\n");
    }

    for (i = 0; i < 10; i++){ // 插入元素
        InsertElem(L, i + 1, i);
    }

    if (GetElem(L, 1, &e)) { // 获取元素的值
        printf("The first element is %d\n", e);
    }

    printf("length is %d\n", GetLength(L)); // 获取表长

    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); // 删除元素
    printf("delete first element is %d\n", e);

    printf("list:");
    TraverseList(L,visit); // 遍历链表

    DestroyList(&L); // 销毁线性表
    if (!L) {
        printf("\ndestroy success\n");
    }
}

运行结果:

shiyanlou:project/ $ gcc -o 3.1 3.1.c                                                      [18:29:19]
shiyanlou:project/ $ ./3.1                                                                 [18:29:22]
init success
list is empty
The first element is 0
length is 10
The 5 at 6
The 6's previous element is 5
The 6's next element is 7
delete first element is 0
list:123456789
destroy success

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值