数据结构【2】链表——①单链表

 本贴继续记录数据结构-线性表的学习代码


PS:根据网络课程自学,使用c/c++语言混合编写,但大量代码还是以c为主。部分代码区分带头节点与不带头结点。

链表


目录

目录

目录

链表

目录

1.包含头文件

2.定义节点

3.判空

4.求表长

5.按序号插入

6.后插操作

7.后插操作

8.按序号、按值查找

 9.按位删除

11. 尾插法、头插法建立单链表


1.包含头文件

#include <iostream>
#include <stdbool.h>

using namespace std;

2.定义节点

//定义单链表节点类型
typedef struct LNode 
{
    int data;           //数据域
    struct LNode *next; //指针域
}LNode,*LinkList; //LNode强调结点,LinkList强调链表

3.判空

//判空
bool Empty(LinkList L)
{
   //[不带头] return (L==NULL);
    if(L->next == NULL) //[带头]
        return true;
    else
        return false;
}

4.求表长

//求表长
int Length(LinkList L)
{
    int len=0;  //计数变量
    LNode *p=L; 
    while (p->next != NULL) //判断下一个结点是否为空
    {
        p=p->next;
        len++;  //每访问一个结点,自增1
    }
    return len; //返回结点数量
}

5.按序号插入

PS:部分代码涉及封装操作,即将原本复杂、重复的代码写成一个函数,并调用。

//按序号插入 在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList& L, int i, int e)
{
    if(i<1) //判断结点是否合法(位序从1开始
        return false;
    //(可封装)LNode *p = GetElem(L,i-1);
    LNode *p; //指针p指向当前能扫描到的结点
    int j=0;  //当前p指向的是第几个结点
    p=L;      //L指向头结点,头结点是第0个结点
    while (p != NULL && j < i - 1)  //在第i个结点前插入所以循环到i-1个结点
    {
        p=p->next;
        j++;
    }
   
 //以下代码可用 (封装)后插函数代替
    //return InsetNextNode(p,e);
    if(p==NULL) //i值不合法,大于当前链表长度
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));//动态分配一个地址
    s->data=e;  //元素e插入到数据区
    s->next=p->next;   //指针指向原结点的下一结点
    p->next=s;  //原结点指针指向插入结点s
    return true;    //插入成功
}


//按序号插入 在第i个位置插入元素e(不带头结点)
bool ListInsert2(LinkList& LL, int i, int e)
{
    if(i<1) //判断位序的合法性
        return false;
    //(可封装)LNode *p = GetElem(L,i-1);
    if (i == 1) //插入在第一个结点时
    {
        LNode *s=(LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next = LL;   //新结点指向原链表
        LL=s;   //头指针指向新结点
    }
    //其余操作相同
    LNode* p; //指针p指向当前能扫描到的结点
    int j = 0;  //当前p指向的是第几个结点
    p = LL;      //L指向头结点,头结点是第0个结点
    while (p != NULL && j < i - 1)  //在第i个结点前插入所以循环到i-1个结点
    {
        p = p->next;
        j++;
    }
   
 //以下代码可用 (封装)后插函数代替
    //return InsetNextNode(p,e);
    if (p == NULL) //i值不合法,大于当前链表长度
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));//动态分配一个地址
    s->data = e;  //元素e插入到数据区
    s->next = p->next;   //指针指向原结点的下一结点
    p->next = s;  //原结点指针指向插入结点s
    return true;    //插入成功
}

6.后插操作

//后插操作:在p结点后插入元素e
bool InsertNextNode(LNode* p, int e)
{
    if(p==NULL) //判断插入结点是否合法
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    if(s==NULL) //内存分配失败
        return false;
    s->data=e;  //用结点s保存数据元素e
    s->next=p->next;
    p->next=s;  //将结点s连到p之后
    return true;
}

7.后插操作

//前插操作:在p结点之前插入元素e
bool InserPriorNode(LNode* p, int e)
{
    if(p == NULL)   //判断结点是否合法
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    if(s==NULL) //判断内存分配
        return false;
    s->next=p->next;    //将新结点指向下一结点
    p->next=s;          //将原结点指向新结点 
    s->data=p->data;    //将原结点数据复制到新结点
    p->data=e;          //将插入数据赋值给原结点
    return true;
}

8.按序号、按值查找

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


//按值查找(带头),找到数据域==e的结点
LNode * LocateElem(LinkList L, int e)
{
    LNode *p = L->next;     //从第1个结点开始查找数据域为e的结点
    while(p == NULL && p->data != e)
        p->next;
    return p;   //找到后返回该结点指针,否则返回NULL
}

 9.按位删除

//按位删除节点(带头
bool ListDelete(LinkList& L, int i, int &e)//用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++;
    }
    if(p==NULL) //i值不合法
        return false;
    if(p->next == NULL) //第i-1个结点后没有其他结点
        return false;
    LNode *q=p->next;   //令q指向被删除结点
    e = p->data;        //用e返回元素的值
    p->next=q->next;    //将*q结点从链中“断开”
    free(q);            //释放结点存储空间
    return true;        //删除成功
}

10.删除指定结节点

//删除指定结点
bool DeleteNode(LNode* p)
{
    if(p == NULL)   //判断结点是否为空
        return false;   
    LNode *q = p->next; //令p指向*p的后继结点
    p->data = p->next->data;    //和后继结点交换数据域
    p->next=q->next;    //将*q结点从链中断开
    free(q);        //释放后继结点的存储空间
    return true;
}

11. 尾插法、头插法建立单链表

//尾插法建立单链表
LinkList List_Tailnsert(LinkList &L)    //正向建立链表
{
    int x;  //假设输入的数据为整型参数
    L=(LNode *)malloc(sizeof(LNode));   //建立头结点
    LNode *s,*r=L;      //r为表尾结点
    cout << "向链表输入值,输入000结束";
    cin >> x;    //输入结点的值
    while (x != 000)    //循环插入数据,到000结束
    {
        s=(LNode *)malloc(sizeof(LNode));   //建立结点,并让s指向这个结点
        s->data = x;        //插入数据x
        r->next = s;        //让r指向s,建立链接
        r = s;              //让r指向新的表尾结点
        cin >> x;           //输入数据
    }
    r->next = NULL;         //尾结点指针置空
    return L;
}


//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
    LNode *s;
    int x;
    L=(LinkList)malloc(sizeof(LNode));  //创建头结点
    L->next = NULL;
    cout << "向链表输入值,输入000结束";    //初始为空链表
    cin >> x;       //插入结点的值
    while (x != 000)    //输入000结束
    {
    s=(LNode *)malloc(sizeof(LNode));   //创建新结点,
    s->data=x;          //x的值插入新结点
    s->next=L->next;    //新结点直指向L的下一结点
    L->next=s;          //将新结点插入表中,L为头指针
    cin >> x;           //再插入数据
    }
    return L;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值