2021-12-09

这篇博客详细介绍了C++中链表的数据结构,包括单向链表和双向链表。内容涵盖链表结点的结构、链表的创建、遍历、在不同位置插入和删除结点的操作。特别强调了动态内存分配和指针操作在链表操作中的关键作用,以及单向链表和双向链表的特点和区别。示例代码展示了如何实现这些操作,包括双向链表的定义、创建、插入和删除结点的过程。
摘要由CSDN通过智能技术生成

C++学习笔记(23)

1.动态链表的每个结点存放元素的自身信息和与之关联的元素的地址
单向链表只需存放直接后继节点的地址,双向链表既有直接前驱也有直接后继节点的地址。
结构成员可以是指向自身结构类型的指针,但不能是自身结构类型的变量。
在这里插入图片描述
在这里插入图片描述

2.建立链表:

struct Node
{int data;
Node * next;
};     //①定义链表结构体;

Node * head=NULL;   //②定义头指针;

void CreateList(Node * & head)   //指针型引用,参数是头指针;
{Node *s,*p=NULL;  //实操中不对p赋空值会报错;
s=new Node;   //动态分配空间,创建新结点;
cin>> s->data;   //输入信息到新结点;
while(s->data != 0)    //若是有效结点;
  {if(head==NULL)   head=s;    //第一个结点;head指向整一个结构体;
   else    p->next=s;   //上一个结点的指针域指向这个结点一整个结构;
   p=s;         //指针p前移到现在的这个结点;
   s=new Node;   //分配下一个结点的空间;
   cin>> s->data;   //再次输入,开始下一轮循环;
   }

p->next = NULL;  //最后一个结点的指针域赋空值;不但表示链表结束,还防止误操作;

delete s;   //释放值为0的结点和辅助指针的空间;
s=NULL;
return;

3.遍历链表:从头指针开始使用跟踪指针逐个输出结点值,直到指针为空。

void ShowList(Node* head)
{
    cout << "now the items of node are:\n";
    while (head)
    {
        cout << head->data << '\t';
        head = head->next;
    }
    cout << endl;
}

链表便于实现插入和删除结点的动态操作,关键是正确修改结点的指针。首先是查找确认操作位置,然后按位置的不同分别处理。

4.在表头插入结点和在*p之后插入结点:
①生成新结点;
②把新结点连接到链表上;
③修改头指针。
`在这里插入图片描述
在这里插入图片描述

5.在p之前插入结点:
方法①:查找p的前驱结点的地址,借助辅助指针。
在这里插入图片描述
方法②:避免重新搜索前驱结点,可以先把新结点插入到
p之后再交换数据域。
在这里插入图片描述

删除节点也要根据结点的位置进行不同的处理,还要注意释放被删除的结点。都需要辅助指针。

6.删除头节点:
在这里插入图片描述

7.删除*p:需要查找其前去结点指针。
方法①:双指针跟踪;
方法②:仅用一个指针跟踪
for循环终止条件是p->nextNULL;
循环体内用p->next->data
key来判断查找,p是目标结点的前驱结点。
在这里插入图片描述

单向链表特点:
  1.我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的.
  2.只能从头遍历到尾或者从尾遍历到头(一般从头到尾)

双向链表特点
  1.每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 实现起来要困难一些
  2.相对于单向链表, 必然占用内存空间更大一些.
  3.既可以从头遍历到尾, 又可以从尾遍历到头

8.双向链表的定义:
  双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。下图为双向链表的结构图。
  在这里插入图片描述
在这里插入图片描述
声明定义代码:

typedef struct Node{
    struct Node *pre;
    int data;
    struct Node *next;
};

9.双向链表的创建:
同单链表相比,双链表仅是各节点多了一个用于指向直接前驱的指针域。因此,我们可以在单链表的基础轻松实现对双链表的创建。
  需要注意的是,与单链表不同,双链表创建过程中,每创建一个新节点,都要与其前驱节点建立两次联系,分别是:
  将新节点的 prior 指针指向直接前驱节点;
  将直接前驱节点的 next 指针指向新节点;

10.双向链表的插入:
①插入到表头:(表尾同理)
  将新数据元素添加到表头,只需要将该元素与表头元素建立双层逻辑关系即可。
  换句话说,假设新元素节点为 temp,表头节点为 head,则需要做以下 2 步操作即可:
  temp->next=head; head->prior=temp;

②添加至表的中间位置:
  同单链表添加数据类似,双向链表中间位置添加数据需要经过以下 2 个步骤,如下图所示:
  新节点与其直接后继节点建立双层逻辑关系;
  新节点的直接前驱节点与之建立双层逻辑关系;

11.双向链表结点的删除:

Node * DeleteList(Node * head,int data)
{
    Node * temp=head;
    /*遍历链表*/
    while (temp)
    {
        /*判断当前结点中数据域和data是否相等,若相等,摘除该结点*/
        if (temp->data==data) 
        {
            /*判断是否是头结点*/
            if(temp->pre == NULL)
            {
                head=temp->next;
                temp->next = NULL;
                free(temp);
                return head;
            }
            /*判断是否是尾节点*/
            else if(temp->next == NULL)
            {
                temp->pre->next=NULL;
                free(temp);
                return head;
            }
            else
            {
                temp->pre->next=temp->next;
                temp->next->pre=temp->pre;
                free(temp);
                return head;   
            }
            

        }
        temp=temp->next;
    }
    printf("Can not find %d!\r\n",data);
    return head;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值