线性表之单链表(C++/C)

线性表之单链表(C++/C)

1 基本操作

声明部分:


#include <cstdlib>
#include "stdio.h"

#define ElemType int

typedef struct LNode{
    ElemType data;
    struct LNode *next;

}LNode,*LinkList;
1.//初始化单链表
//不带头结点的单链表
bool InitList(LinkList &L)
//初始化单链表
//***带**头结点的单链表
bool InitListWithHead(LinkList &L)
//后插操作: 在p节点之后插入元素
bool InsertNextNode(LNode*p,ElemType e)
//前插操作 在p节点之前插入e
bool InsertPriorNode(LNode*p,ElemType e)
// 删除节点p的方法1  时间复杂度为O(n)
bool DeleteNode(LNode *p)
//删除节点p的方法2 时间复杂度为O(1) 原理 :你想删除我节点p,我把q节点的东西都拿来了(继承) 你去删q吧 其中 q为p的下一节点
bool DeleteNodePlus(LNode *p)
//按位查找
LNode *GetElem(LinkList L,int i)
//求表长
int ListLength(LinkList L)
//在第i个位置插入元素e  带头结点   尾插法
bool ListInsetWithHead(LinkList &L,int i,ElemType e)
//按位序插入 不带头结点
bool ListInset(LinkList &L,int i,ElemType e)
//按位序删除 带头节点
bool ListDeleteWithHead(LinkList &L,int i,ElemType &e)
//尾插法建立单链表  用户输入
LinkList List_TailInsert(LinkList &L)
//判断单链表是否为空
bool isEmpty(LinkList L)
//头插法 每次都插在头结点之后
//后插操作:在p接待之后 插入元素e
LinkList List_HeadInsert(LinkList &L)
void LinkListShow(LinkList L)

2.特别说明

//前插操作 在p节点之前插入e
bool InsertPriorNode(LNode*p,ElemType e)

在该函数中:特别说明如下:

 

3.主函数

int main(){
    LinkList L;
    ElemType e;
    InitList(L);
    List_HeadInsert(L);
    printf("The length of the LinkList is %d\n",ListLength(L));
    LinkListShow(L);
    if (ListDeleteWithHead(L,3,e))
        printf("The Node which was delete is %d\n",e);
    else
        printf("Fail to delete Node ");
    LinkListShow(L);
    if(ListInset(L,2,8))
        printf("Insert position 2 successfully \n");
    else
        printf("Fail to insert !\n");
    LinkListShow(L);

    return  0;
}

4.运行结果

5.源代码 


#include <cstdlib>
#include "stdio.h"

#define ElemType int

typedef struct LNode{
    ElemType data;
    struct LNode *next;

}LNode,*LinkList;

//初始化单链表
//不带头结点的单链表
bool InitList(LinkList &L){
    L=NULL;
    return true;
}

//初始化单链表
//***带**头结点的单链表
bool InitListWithHead(LinkList &L){
    L=(LNode*)malloc(sizeof(LNode)); //分配一个头结点
    if (L==NULL)
        return false;
    L->next=NULL;
    return true;  //头结点之后 暂时还没有节点
}

//后插操作: 在p节点之后插入元素
bool InsertNextNode(LNode*p,ElemType e){
    if (p==NULL)
        return false;
    LNode *s=(LNode*)malloc(sizeof(LNode));
    if (s==NULL)
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;  //将s节点连接到p之后
    return true;
}

//前插操作 在p节点之前插入e
bool InsertPriorNode(LNode*p,ElemType e){
    if (p==NULL)
        return false;
    LNode *s=(LNode*)malloc(sizeof(LNode));
    if (s==NULL)
        return false;
    s->next=p->next;     //此处应该这么理解: 1.首先 ‘=’ 既可以理解为赋值 ***也可以理解为 ‘指向’  原本是p-->下一个节点q 此时虽然称为前插法 但是 但是 我们依旧把s节点放在中间;
                         //原本你p的next是要指向q的  现在我毕竟插入了一个s 那我就用s的next 指向 p->next 即下一个节点 q;
    p->next=s;           //注意 我们确实声明 并且给了s节点内存空间 但是 它里面的值 依旧是不确定的 你可以理解为NULL; 既然上一步 你把p->next赋值给了别人 那么我就将s赋值给p->next 就是让p->next你下一次 指向s;
    s->data=p->data;     //原来即便s.data中有一个不确定的值 那那那 我就把p里面的值 给你s节点  这样 s就把 p节点的所有东西给继承过来了;
    p->data=e;           //反正 一开始我e就没赋值给过其他人 现在反正你p->data的值都给 s了 那 e就给p节点的data  有感情  --那味了!
                        //如此看来 是不是 有点像 s 和p 节点互换了位置 此称为前插法
    return true;
}

// 删除节点p的方法1  时间复杂度为O(n)
bool DeleteNode(LNode *p){
    if (p==NULL)
        return false;
//    if (p->next==NULL)
//        return false;
    LNode *q=p->next; //令q指向被删除的节点
    p->next=q->next; //将*q节点从链中断开
    free(q);
    return true;
}
//删除节点p的方法2 时间复杂度为O(1) 原理 :你想删除我节点p,我把q节点的东西都拿来了(继承) 你去删q吧 其中 q为p的下一节点
bool DeleteNodePlus(LNode *p){
    if (p==NULL)
        return false;
    LNode *q=p->next; //令q指向被删除的节点
    p->data=p->next->data; //和后继节点交换数据域
    p->next=q->next; //将*q节点从链中断开
    free(q);
    return true;

}
//按位查找
LNode *GetElem(LinkList L,int i){
    LNode *p;  //指针p指向当前扫描到的节点
    int j=0;  //当前p指向的是第几个节点
    p=L;      //L指向头节点 头结点是第0个节点 不存数据
    while (p!=NULL&&j<i-1){  //循环找不到第i-1个节点
        p=p->next;
        j++;

    }
    return p;
}

//求表长
int ListLength(LinkList L){
    int length=0;
    LNode *p=L;
    while (p->next !=NULL){
        p=p->next;
        length++;
    }
    return length;
}

//在第i个位置插入元素e  带头结点   尾插法
bool ListInsetWithHead(LinkList &L,int i,ElemType e){
    if (i<1){
        return false;
    }
    LNode *p;  //指针p指向当前扫描到的节点
    int j=0;  //当前p指向的是第几个节点
    p=L;      //L指向头节点 头结点是第0个节点 不存数据
    while (p!=NULL&&j<i-1){  //循环找不到第i-1个节点
        p=p->next;
        j++;

    }
    return InsertNextNode(p,e);
}
//按位序插入 不带头结点
bool ListInset(LinkList &L,int i,ElemType e){
    if (i<1){
        return false;
    }
    if (i==1){  //插入第一个节点会与其他节点的操作不同
        LNode *s=(LNode*)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;  //头指针指向 新插入的节点
        return true;
    }
    LNode *p;  //指针p指向当前扫描到的节点
    int j=0;  //当前p指向的是第几个节点
    p=L;      //L指向头节点 头结点是第0个节点 不存数据
    while (p!=NULL&&j<i-1){  //循环找不到第i-1个节点
        p=p->next;
        j++;

    }
    return InsertNextNode(p,e);
}
//按位序删除 带头节点
bool ListDeleteWithHead(LinkList &L,int i,ElemType &e){
    if (i<1)
        return false;
    LNode *p;
    int j=0;
    p=L;  //L指向头结点  头结点是第0个节点 不存数据
    while (p!=NULL&j<i-1){
        p=p->next;
        j++;
    }
    if (p==NULL)
        return false;
    if (p->next==NULL)
        return false;
    LNode *q=p->next; //令q指向被删除的节点
    e=q->data;
    p->next=q->next; //将*q节点从链中断开
    free(q);
    return true;
}

//尾插法建立单链表  用户输入
LinkList List_TailInsert(LinkList &L){
    ElemType x;
    L=(LinkList)malloc(sizeof(LNode));  //建立头结点
    LNode*s,*r=L;                       //r为表位指针
    scanf("%d",&x);
    while (x!='#'){
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;
        r->next=s;
        r=s;                             //r指向新的表尾节点  r让其永远指向最后一个节点
        scanf("%d",&x);
    }
    r->next=NULL;                       //尾节点r指针置空
    return L;
}


//判断单链表是否为空
bool isEmpty(LinkList L){
    if (L==NULL)
        return true;
    else
        return false;
}
//头插法 每次都插在头结点之后
//后插操作:在p接待之后 插入元素e
LinkList List_HeadInsert(LinkList &L){
    ElemType x;
    L=(LinkList)malloc(sizeof(LNode));  //建立头结点
    LNode*s;
    L->next=NULL;

    scanf("%d",&x);
    while (x!=9999){
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;
        s->next=L->next;
        L->next=s;     //将新节点插入表中 L为头指针
        scanf("%d",&x);
    }

    return L;


}
void LinkListShow(LinkList L){
    if (!L)
        printf("The LinkList is Null !");
    else
    {
        printf("The data of the LinkList are\n");
        LNode *p=L->next;
        while (p) {
            printf("%d  ", p->data);
            p = p->next;
        }
        printf("\n");
    }
}








int main(){
    LinkList L;
    ElemType e;
    InitList(L);
    List_HeadInsert(L);
    printf("The length of the LinkList is %d\n",ListLength(L));
    LinkListShow(L);
    if (ListDeleteWithHead(L,3,e))
        printf("The Node which was delete is %d\n",e);
    else
        printf("Fail to delete Node ");
    LinkListShow(L);
    if(ListInset(L,2,8))
        printf("Insert position 2 successfully \n");
    else
        printf("Fail to insert !\n");
    LinkListShow(L);

    return  0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linszjava@gmail.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值