单链表的基本实现和操作

#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef int ElemType;
typedef int Status;

//单链表

//链表节点
typedef struct Lnode{
    ElemType data;//数据域,可以是struct,也可以是int等。
    struct Lnode *next;//指针域
}Lnode,*LinkList;

//创建空链表
Status creatList(LinkList &L){
    L = (LinkList)malloc(sizeof(Lnode));//申请一个节点空间,为头结点
    L->next = NULL;//给头结点next域给空值;
    return 1;
}

//头插法创建单链表,倒叙排列,后入的元素放在头位置上
void creatHeadList(LinkList &L,int n){//n为节点个数
    L = (LinkList)malloc(sizeof(Lnode));
    L->next = NULL;//先创建一个带头结点的单链表
    for(int i = n;i>0;i--){
        Lnode *p =  (LinkList)malloc(sizeof(Lnode));
        scanf("%d",&p->data);
        p->next = L->next;//插入到表头
        L->next = p;//更改头节点位置,指向最新元素
    }
}
//尾插法创建单链表,从后面一个个接入
void creatTailList(LinkList &L,int n){//n为节点个数
    L = (LinkList)malloc(sizeof(Lnode));
    L->next = NULL;//先创建一个带头结点的单链表
    Lnode *last = L;//尾结点last
    for(int i = 1;i<=n;i++){
        Lnode *p =  (LinkList)malloc(sizeof(Lnode));//建立新节点接收数据
        scanf("%d",&p->data);
        p->next = NULL;//一定要给节点next值赋值为NULL
        last->next = p;//新节点p插入到表尾
        last = p;//尾结点last更新位置,指向新的尾结点
    }
}

//判断链表是否为空
int isEmpty(LinkList L){//若L为空,返回1,不空返回0
    if(L->next)//非空
     return 0;
    else
     return 1;
}

//销毁单链表L
int destroyList(LinkList &L){
    Lnode *p;
    while(L){
        p = L;
        L = L->next;//头结点指向下一个,一个一个销毁
        free(p);
    }
    return 1;
}

//清空单链表,头尾结点还在,只是清空内容
int clearList(LinkList &L){
    Lnode *p,*q;//p指向第一个元素,q连续指向后面元素,用来逐个清空
    p = L->next;
    while(p){
        q = p->next;
        free(p);
        p = q;
    }
    L->next = NULL;//头结点指针域为空
    return 1;
}

//求单链表L的表长
int listLength(LinkList L){
    Lnode *p;
    p = L->next;//p指向第一个结点
    int count = 0;//计数器
    while(p){//遍历单链表,统计结点数
        count++;
        p = p->next;
    }
    return count;
}

//获取第i个元素值,用e返回,e传过来的是地址
int getElem(LinkList L,int i,ElemType &e){
   Lnode *p = L->next;
   int j = 1;//初始化
   while(p && j<i){//向后扫描,直到p指向第i个元素或者p为空
     p = p->next;
     j++;
   }
   if(!p || j>i){//第i个元素不存在
    return 0;
   }
   e = p->data;//取第一个元素
   return 1;
}//getElem

//查找链表中指定元素值的位置,若有则返回该地址,没有返回NULL
Lnode *locateElem(LinkList L,ElemType e){
    Lnode *p = L->next;
    while(p && p->data !=e){
        p = p->next;
    }
    return p;//找到了则直接返回p的地址,找不到也会直接返回NULL,所以直接return p 就可以。
}

//查找链表中指定元素值的位置,若有则返回位置序号,没有返回0
int locateElem(LinkList &L,ElemType e){
    Lnode *p = L->next;
    int j = 1;//用来标记下标位置
    while(p && p->data !=e){
        p = p->next;
        j++;
    }
    if(p)//p不为空,说明跳出循环的条件是找到了相同元素值
        return j;
    else//查找失败
        return 0;
}

//在单链表中第i个元素之前插入数据元素e
int insertList(LinkList &L,int i,ElemType e){
    Lnode *p = L;
    int j = 0;
    while(p && j<i-1){
        p = p->next;
        j++;
    }
    //此时p指向的是第i-1个节点的地址
    if(!p || j>i-1)//i大于表长+1  或者小于1,插入位置非法
        return 0;
    Lnode *q = (LinkList)malloc(sizeof(Lnode));//生成新节点
    q->data = e;
    q->next = p->next;//将节点q插入到L中
    p->next = q;
    return 1;
}
//在指定节点p前插入元素(先在p后面插入节点,然后换元,妙啊)
int insertPriorNode(Lnode *p,ElemType e){
    if(p == NULL){//p为空
        return 0;
    }
    Lnode *s = (Lnode *)malloc(sizeof(Lnode));
    if(s == NULL)//分配失败
        return 0;
    s->next = p->next;
    p->next = s;//s接到p后面
    s->data = p->data;//p中元素赋给s
    p->data = e;//p中元素用e覆盖,实现完整插入工作
    return 1;
}
//删除第i个节点,被删数据值用e暂存
int deleteList(LinkList &L,int i,ElemType &e){
    if(i < 1)//i值不合法
        return 0;
    Lnode *p = L;
    int j = 0;
    while(p && j<i-1){
        p = p->next;
        j++;
    }
    if(!(p->next))//如果i处节点为NULL或者i超出链表长度,返回错误
        return 0;
    Lnode *q = p->next;//q节点指向i处
    p->next = q->next;//将i前节点指向i后节点,跳过i处
    e = q->data;//e暂存被删元素值
    free(q);//释放i处节点
    return 1;
}
//删除指定节点p(偷天换日)
int deleteNode(Lnode *p){//此代码限制条件,p也不能为最后尾结点,必须为尾结点前面的节点。】】】】
    if(p == NULL)//p为空
        return 0;
    Lnode *q = p->next; //令q指向*p的后继节点
    p->data = q->data;//p和后继节点交换数据域
    p->next = q->next;//将*q节点从链中断开
    free(q);
    return 1;
}

//遍历输出链表
void printList(LinkList L){
    Lnode *p = L->next;
    if(!p)
        return;
    printf("%d",p->data);
    p = p->next;
    while(p){
        printf(" %d",p->data);
        p = p->next;
    }
}

int main()
{
    LinkList L;
    creatTailList(L,5);
    printList(L);
    printf("\n");
    Lnode *p = L->next->next->next;
    deleteNode(p);
    printList(L);
//    int x;
//    deleteList(L,3,x);
//    printList(L);




    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值