C语言数据结构二:线性表之单链表的实现

本次不给出头文件和main主函数了。可以参考之前的C语言数据结构一,线性表之单链表的实现。

下面给出具体的方法函数的实现:

#include "linklist.h"

void InitList(List *list){
    //分配空间
    list->first = list -> last = (Node*)malloc(sizeof(Node));
    assert(list->first!=NULL);
    //初始化几个数据域
    list->first->next = NULL;
    list->size = 0;
}

void push_back(List *list,ElemType x){
    //分配空间
    Node *s = (Node*)malloc(sizeof(Node));
    assert(s!=NULL);
    //对单个节点做初始化
    s->data = x;
    s->next = NULL;
    //尾指针的下一个给到新节点
    list->last->next = s;
    //再任命新的节点为尾指针
    list->last=s;
    //数量增加
    list->size++;
}

void push_front(List *list,ElemType x){
    //分配空间
    Node *s = (Node*)malloc(sizeof(Node));
    assert(s!=NULL);
    //初始化
    s->data = x;
    //两种情况:头插为第一个节点,则需要调整尾指针
    //头插非,则只需要单纯插入不需要调整尾指针
    //作插入操作
    //先链接,新节点的next为目前的第一个节点
    s->next = list->first->next;
    //后断开,将目前的第一个节点改为新节点
    list->first->next = s;
    //如果size为1,则插入的为第一个节点
    while(list->size == 0){
        list->last = s;
    }
    //数量增加
    list->size++;
}

void show_list(List *list){
    //作展示
    //将第一个节点给到p
    Node* p = list->first->next;
    //判断是否为空
    while(p != NULL){
        //不空则输出
        //遍历节点的数据
        printf("%d->",p->data);
        //将指针指向下一个节点
        p = p->next;
    }
    printf("\n");
}

void pop_back(List *list){
    //尾部清除

    //判断当前链表长度,为空不做处理
    if(list->size == 0 ){
        printf("当前链表为空");
        return;
    }
    //将头节点的指针赋值给指针
    Node *h = list->first;
    //判断该指针的下一个是否和尾指针指向的节点一样
    while(h->next != list->last){
        //不一样则将指针不断往下面移动
        h = h->next;
    }
    //一样了,则表示该指针的下一个为尾节点了

    //可以释放尾指针指向的尾节点了
    free(list->last);
    //将尾指针指向改为刚刚循环遍历搞出来的原来的尾节点的前驱节点
    list->last = h;
    //将现在的尾节点的next设置为NULL
    list->last->next =NULL;
    //数量减少一个
    list->size--;
}

void pop_front(List *list){
    //判断表是否为空表
    if(list->size == 0){
        printf("这个是空表\n")
        return;
    }
    //将头节点的指针传给h指针
    Node *h = list->first;
    //作头部弹出操作
    //头节点指针的next设置为当前首节点的下一个,这样可以将前面的下面一个断开
    list->first->next = h->next->next;
    //释放掉之前的首节点
    free(h->next);
    //当释放掉首节点后表空的时候,需要调整尾节点的位置,因为释放的就是尾节点
    while(list->size == 1){
        list->last = list->first;
    }
    list->size--;
}

void insert(List *list,ElemType x){
    //分配空间加上对节点的初始化
    Node *s = (Node*)malloc(sizeof(Node));
    assert(s!=NULL);
    s->data=x;
    s->next=NULL;
    //将头节点指针给到p指针
    Node *p = list->first;
    //将p指针在next域不为空的情况下和下一个节点的数据小于x的情况下,将p指针后移
    while(p->next!=NULL && p->next->data<x){
        p=p->next;
    }

    //p指针移动到了尾节点
    if(p->next == NULL){
        //需要修改尾指针为目前这个新的节点
        list->last = s;
    }
    //插入目前这个新的节点
    //新节点的next改成之前的尾节点的next域
    s->next = p->next;
    //之前的尾节点改为倒数第二个节点,让他的next给到新节点
    p->next = s;
    list->size++;
}

Node *find(List *list,ElemType x){
    //P指针赋值为首节点
    Node *p = list->first->next;
    //P指针从首节点开始,在P指针不为空的情况下和在P指针的数据域不为查找的数据的情况下,将p后移
    while(p!=NULL && p->data!=x){
        p=p->next;
    }
    //查到到了或者p到了最后一个节点的next,结束遍历
    //如果p是最后一个的next,则返回的是NULL,否则返回的是有值的p
    retun p;
}

int length(List *list){
    return list->size();
}

void delete_val(List *list,ElemType key){
    if(list->size == 0 ){
        //当前为空表,无可删除
        return;
    }
    //将list指针和查找的元素传进去,去获取要删除的节点
    Node *p = find(list,key);


    if(p==NULL){
        printf("查找失败\n");
        return;
    }
    //判断是否是尾节点,因为尾巴要改尾指针
    if(list->last == p){
        pop_back(list);
    }else{
        //使用覆法删除
        p->data=p->next->data;
        p->next=p->next->next;
        free(p->next);
        list->size--;
    }
}

//排序
//利用插入进行排序
void sort(List *list){
    //判断表是否为空表或者只有一个元素,如果如此,则不需要排序
    if(list->size == 0||list->size == 1){
        return;
    }

    //切割链表的首节点和之后的节点为两个链表
    //将首节点指针给s,将首节点指针的下一个指针给q
    Node *s = list->first->next;
    //q这里开始可以独立成一个新的链表
    Node *q = s->next;
    //将首节点指针给到尾节点,
    list->last=s;
    //尾节点的下一个设置为空
    list->last->next = NULL;
    //判断链表二是否为空链表
    while(q!=NULL){
        //不空则开始将链表二的数据拿出来比较并且插入链表一
        //q指针给到s
        s=q;
        //q指向下一个节点
        q=q->next;
        //将链表一的头节点给到p
        Node *p = list->first;
        //判断p的下一个是否为空,并且判断p的下一个的数据是否小于s的数据
        while(p->next!=NULL&&p->next->data<s->data){
            //如果成立,则p往后面移动,和后面的比较
            p=p->next;
        }
        //比到了最后一个节点
        if(p->next == NULL){
            //该表链表一的尾指针为新节点s
            list->last=s;
        }
        //作插入操作
        //先链接,新节点的下一个设置为当前尾指针的下一个
        s->next = p->next;
        //老的尾节点的下一个设置为新的节点
        p->next = s;
    }
}

//倒置,使用头插法作倒置
void resver(List *list)
{
    //数据表元素不够没有倒置的意义
    if(list->size==0||list->size==1){
        return;
    }
    //首节点给到p指针
    Node* p =list->first->next;
    //首届点的呃下一个节点给到q指针,用来标识一个新的链表二
    Node *q = p->next;

    //尾指针给到首节点处
    list->last = p;
    //开始和链表二断开,首节点的next设置为null
    list->last->next = NULL;
    //判断q指针是否为空,本质是判断链表二的首指针和之后不断遍历的新的指针是否为空
    while(q!=NULL){
        //不为空,开始作头部插入
        //将当前节点给到p指针
        p=q;
        //再将q指针赋值为当前节点的下一个,用以下次的遍历判空
        q=p->next;
        //链表二的节点的next给到链表一的头节点的next
        p->next = list ->first->next;
        //链表一的头节点的下一个给到p
        list->first->next=p;
    }
}

//清除
void clear(List *list){
    if(list->size ==0){
        return;
    }
    //将首节点给到p
    Node *p = list->first->next;
    //判断p是否不为空,非空进行删除处理和往后遍历
    while(p!=NULL){
        //首节点给到当前p的下一个节点
        list->first->next=p->next;
        //释放p
        free(p);
        //p依旧代表首节点,不过首节点已经变了
        p=list->first->next;
    }
    //尾指针回归
    list->last=list->first;
    //清除长度
    list->size =0;
}

void destroy(List *list){
    clear(list);
    free(list->first);
    list->first=list->last=NULL;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值