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->datakey来判断查找,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;
}