IE盒子

搜索
查看: 180|回复: 0

c 语言数据结构之单链表的定义、插入和删除

[复制链接]

1

主题

4

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2023-3-7 06:14:12 | 显示全部楼层 |阅读模式
1,定义一个单链表

基础定义先了解一下:
struct LNode{   //定义单链表结点类型
    ElemType data;  //每个节点存放一个数据元素
    struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
/*
struct LNode *p=(struct LNode*)malloc(sizeof(struct LNode));    //增加一个新的结点,在内存中申请一个结点所需的空间,并用指针p 指向这个结点
*/
LNode *GetElem(LinkList L,int i){
    int j=1;
    LNode *p=L->next;
    if(i==0)
        return L;
    if(i<1)
        return NULL;
    while(p!=NULL&&j<i){
        p=p->next;
        j++;
    }
        return p;
}上述代码LNode *GetElem(LinkList L,int i) 中需要注意的是:若强调这是一个单链表,使用 LinkList;若强调这是一个结点,则使用LNode * 。
1,不带头结点的单链表

struct LNode{   //定义单链表结点类型
    ElemType data;  //每个节点存放一个数据元素
    struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;

bool InitList(LinkList &L){ //初始化一个单链表
    L=NULL; //空表,防止脏数据
    return true;
}

void test(){
    LinkList L; //声明一个指向单链表的指针
    //初始化一个空表
    InitList(L);
    //.....
}2,带头结点的单链表

struct LNode{   //定义单链表结点类型
    ElemType data;  //每个节点存放一个数据元素
    struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;

//初始化一个单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));   //分配一个头结点
    if(L==NULL) //内存不足,分配失败
        return false;
    L->next=NULL;   //头结点之后暂时还没有结点
    return true;
}

//判断单链表是否为空(带头结点)
bool Empty(LinkList L){
    if(L-next==NULL)
        return true;
    else
        return false;
}

void test(){
    LinkList L; //声明一个指向单链表的指针
    //初始化一个空表
    InitList(L);
    //.....2,单链表的基本操作

1,插入

1,按位序插入(ListInsert(&L,i,e))

在第i 个位置插入元素e (带头结点)
bool ListInsert(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++;
    }
    if(p==NULL) //i 值不合法
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;  //将结点s 连到p 之后
    return true;    //插入成功
}
不带头结点的:(不存在 “第0个“ 结点)实现代码如下:
bool ListInsert(LinkList &L,int i,ElemType e){
    if(i<1)
        return false;
    if(i==1){   //插入第1个结点的操作与其他结点操作不同
        LNode *s=(LNode *)malloc(sizeof(LNode));
        s->data=e;
        s->next=L;
        L=s;    //头指针指向新结点
        return true;
    }
    LNode *p;   //指针p指向当前扫描到的节点
    int j=1;    //当前p 指向的是第几个结点
    p=L;    //p指向第1个结点(注意:不是头结点)
   
     while(p!=NULL&&j<i-1){ //循环找到第i-1个结点
        p=p->next;
        j++;
    }
    if(p==NULL) //i 值不合法
        return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;  //将结点s 连到p 之后
    return true;    //插入成功
}2,指定结点的后插操作(InsertNextNode(LNode *p,ElemType e)

在p 结点之后插入元素e :
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保存数据元素e
    s->next=p->next;
    p->next=s;
}3,指定结点的前插操作

在p 结点之前插入元素e
bool InsertPrioNode(LNode *p,ElemType 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 连接到p 之后
    s->data=p->data;    //将p 中元素复制到s 中
    p->data=e;  //p 中元素覆盖为e
    return true;
}结合下图在体会一下:



下面再看一下在p 结点之前插入结点s
bool InsertPrioNode(LNode *p,ElemType e){
    if(p==NULL||s==NULL)
        return false;
    s->next=p->next;
    p->next=s;  //s 连接到p 之后
    ElemType temp=p->data;  //交换数据域部分
    p->data=s->data;
    s->data=temp;
    return true;
}这招偷天换日结合下图好好体会一下:



2,删除

1,按位序删除(带头结点)

删除表L 中第i 个位置的元素,并用e 返回删除元素的值。那具体怎么做呢?我们要找到第 i-1 个结点,将其指针指向第 i+1 个结点,并释放第 i 个结点。示例代码如下:
bool ListDelete(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++;
    }
    if(p==NULL)        //i 值不合法
        return false;
    if(p->next==NULL)        //说明第i-1个结点之后无其他结点
        return false;
    LNode *q=p->next;        //令q 指向被删除结点
    e=q->data;                //用e 返回元素的值
    p->next=q->next;        //将 *q 结点从链中“断开”
    free(q);                //释放结点的存储空间
    return true;        //删除成功
}

2,指定结点的删除

以下是删除指定结点p 的操作:
bool DeleteNode(LNode *p){
    if(p==NULL)
        return false;
    LNode *q=p->next;        //令q 指向 *p 的后继结点
    p->data=p->next->data;        //和后继结点交换数据域
    p->next=q->next;        //将 *q 结点从链中“断开”
    free(q);                        //释放后继结点的存储空间
    return true;
}
上面几行代码如果没有不是很理解的话,可以结合下面的动态进一步理解:



好了,以上就是关于单链表的定义,插入和删除的一些基本操作。我们不要怕慢,打牢基础在慢慢加速哦~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表