数据结构—单链表(C++)
- 单链表(singly linked list)是有限个数据结构类型相同的元素所组成的有序集合.
- 通常,将单链表中的数据元素作为结点(node)
- 结点包含两个基本部分:数据域和指针域;
- 数据域用来存储结点的数据信息.
- 指针域:用来存储下一个结点的地址.
- 结点的逻辑结构:
data |
---|
*next |
特殊的结点:
- 单链表的第一个结点称为头结点,用head表示.
- 最后一个结点称为尾结点.用rear表示.
- 尾结点的指针域指向NULL.
- NULL是内存中的一个特殊的存储单元,其地址为0,也叫空地址.
单链表的建立
-单链表的逻辑结构是线性的,而存储结构去不一定是线性的.
-通过new为结点分配内存,采取了动态内存分配方式.
void Create(int n){ //创建含n个结点的单链表
Node *NewNode,*rear; //NewNode为新结点,rear为尾结点
for(int i=1;i<=n;i++){
NewNode=new Node; //新结点申请内存
NewNode->data=i; //结点的数据域赋值
NewNode->next=NULL; //结点的指针域赋值
if(head == NULL){
head=NewNode;
rear=NewNode;
}else{
rear->next=NewNode;
rear=NewNode;
}
}
}
单链表的结点删除
在单链表中,删除一个结点(设为DelNode) 根据结点位置和结点个数,有三种情况:
- 结点个数=1,删除头结点.
head=NULL;
delete DelNode;
- 结点个数>1,删除头结点
head=head->next;
delete DelNode;
- 结点个数>1,删除非头结点
p=head;
while(p->next!=DelNode) //查找删除结点的前一个结点p
p=p->next;
p->next=DelNode->next;
delete DelNode;
单链表的结点插入
将插入结点InsNode插入到PosNode结点的后面.
- 若PosNode==NULL,则将结点InsNode插入到头结点之前
InsNode->next=head;
head=InsNode;
- 若PosNode != NULL,则将结点InsNode插入到PosNode之后
InsNode->next=PosNode->next;
PosNode->next=InsNode;
单链表的结点查找
根据结点数据域的数据信息,进行数据对比,找到第一个返回结点地址或没有返回NULL.
Node* Search(int n){ //查找值为n的结点地址
int flag=0;
Node *p=head;
while(p!=NULL){
if(p->data==n){
flag=1;
break;
}
p=p->next;
}
if(flag==0) return NULL;
else return p;
}
#include<iostream>
using namespace std;
/*单链表
*/
struct Node { //结点定义
int data; //数据域
Node *next; //指针域
};
Node *head; //定义单链表的头结点为全局变量
void Create(int n){ //创建含n个结点的单链表
Node *NewNode,*rear; //NewNode为新结点,rear为尾结点
for(int i=1;i<=n;i++){
NewNode=new Node; //新结点申请内存
NewNode->data=i; //结点的数据域赋值
NewNode->next=NULL; //结点的指针域赋值
if(head == NULL){
head=NewNode;
rear=NewNode;
}else{
rear->next=NewNode;
rear=NewNode;
}
}
}
void Display(){ //输出单链表
Node *p=head; //探测指针p
if(p==NULL){
cout<<"链空,无节点输出"<<endl;
return ;
}
while(p!=NULL){
cout<<p->data<<"["<<p<<"]"<<"=>";//输出结点的值和内存地址
p=p->next;
}
cout<<"NULL"<<endl;
}
Node* Search(int n){ //查找值为n的结点地址
int flag=0;
Node *p=head;
while(p!=NULL){
if(p->data == n){
flag=1;
break;
}
p=p->next;
}
if(flag == 0) return NULL;
else return p;
}
void Delete(Node *DelNode){ //删除结点
Node *p;
if(head == NULL){
cout<<"链表为空"<<endl;
return;
}
if(DelNode == NULL){
cout<<"链表中无此结点"<<endl;
return;
}
if(DelNode==head){ //若删除头结点head
if(head->next!=NULL){ //若链表结点数>1
head=head->next;
}else{ //若链表只有一个结点
head=NULL;
}
delete DelNode;
}else{ //若删除不是头结点head
p=head;
while(p->next!=DelNode) //查找删除结点的前一个结点
p=p->next;
p->next=DelNode->next;
delete DelNode;
}
}
void deleteAll(){
Node* DelNode;
while(1){
DelNode=head;
head=head->next;
if(head==NULL) break;
delete DelNode;
}
Display();
}
void Insert(Node * PosNode,Node* InsNode){ //将InsNode插入到PosNode结点之后
if(PosNode==NULL){ //将InsNode插入头结点之前
InsNode->next=head;
head=InsNode;
}else{
InsNode->next=PosNode->next;
PosNode->next=InsNode;
}
}
int main(){
head=new Node;
head=NULL;
Create(5);
cout<<"结点所占字节数为"<<sizeof(Node)<<endl;
Display();
Node* DelNode;
DelNode=Search(1);
Delete(DelNode);
Display();
DelNode=Search(3);
Delete(DelNode);
Display();
DelNode=Search(5);
Delete(DelNode);
Display();
deleteAll();
system("pause");
return 0;
}
写于 2020-10-14