对应视频:23考研408数据结构代码题参考模板(链表)
标红色的为必须掌握
有多个模板的只要掌握一种即可。
单链表
单链表结点结构体
struct node{
int data;//数据
node *next;//指向下一个结点的指针
};
其中数据域data的类型可以根据需要修改成其他的。
单链表中间插入结点
模板1
以下两段代码本质是一样的,只不过一个在函数中new结点,一个结点在外面new好然后通过参数传进来
void insert(node *p,int value){
//在p指向结点的后面插入一个值为value的结点
//申请新节点的空间,上面是C写法,下面是C++写法
//node *q=(node*)malloc(sizeof(node));
node *q=new node;
q->data=value; //先把数据放进去
//将q结点连进去
q->next=p->next;
p->next=q;
}
void insert(node *p,node *q){
//在p指向结点的后面插入一个结点q
q->next=p->next;
p->next=q;
}
模板2
以下两段代码本质是一样的,只不过一个在函数中new结点,一个结点在外面new好然后通过参数传进来
void insert(node *p,int value){
//在p指向结点的后面插入一个值为value的结点
//申请新节点的空间,上面是C写法,下面是C++写法
//node *q=(node*)malloc(sizeof(node));
node *q=new node;
q->data=value; //先把数据放进去
//将q结点连进去
node *r=p->next; //r可能指向NULL,但不影响
p->next=q;
q->next=r;
}
void insert(node *p,int value){
//在p指向结点的后面插入一个结点q
node *r=p->next; //r可能指向NULL,但不影响
p->next=q;
q->next=r;
}
单链表中删除结点
以下两段代码本质是一样的,只不过一个是将删除的结点空间free掉,一个是返回(可能有其他用途,就是将这个结点从链表中摘下来)
void del(node *p){
//删除p的后一个结点
//这里不考虑q为NULL的情况
node *q=p->next;//q为要删除的结点
p->next=p->next->next;
//释放结点空间,上面是C写法,下面是C++写法
//free(q);
delete q;
}
node* del(node *p){
//删除p的后一个结点,并将该结点返回
//这里不考虑q为NULL的情况
node *q=p->next;//q为要删除的结点
p->next=p->next->next;
return q; //将从链表中删除的结点返回
}
遍历链表(以求链表长度和查找元素为例)
模板1
int length(node *head){
//返回单链表的长度
int cnt=0; //计数器,初始为0
//遍历单链表中的所有结点
for(node *p=head->next;p!=NULL;p=p->next){
cnt++; //计数器+1
}
return cnt;
}
node* find(node *head,int value){
//查找单链表中是否有元素value
//有则返回该结点,无则返回NULL
for(node *p=head->next;p!=NULL;p=p->next){
if(p->data == value){
//找到了,返回该结点
return p;
}
}
return NULL;//没找到,返回NULL
}
模板2
int length(node *head){
//返回单链表的长度
int cnt=0; //计数器,初始为0
//遍历单链表中的所有结点
node *p=head->next; //p指向链表中第一个元素所在的结点
while(p!=NULL){
cnt++; //计数器+1
p=p->next;//p指向下一个结点
}
return cnt;
}
node* find(node *head,int value){
//查找单链表中是否有元素value
//有则返回该结点,无则返回NULL
node *p=head->next;//p指向链表中第一个元素所在的结点
while(p!=NULL){
if(p->data == value){
//找到了,返回该结点
return p;
}
p=p->next;//p指向下一个结点
}
return NULL;//没找到,返回NULL
}
头插法建立单链表
这里用到了前面在链表中插入结点的insert()函数,在考试时需要将insert()函数写上
node* head_insert(int A[],int n){
//将数组A中的元素以头插法的形式插入链表中
//返回链表的头结点
node *head=new node;//头结点
head->next=NULL; //一开始链表中没有元素
for(int i=0;i<n;i++){
//由于是头插法,所以在头结点后面插入一个结点
insert(head,A[i]);
}
return head; //返回链表的头结点
}
尾插法建立单链表
这里用到了前面在链表中插入结点的insert()函数,在考试时需要将insert()函数写上
node* tail_insert(int A[],int n){
//将数组A中的元素以尾插法的形式插入链表中
//返回链表的头结点
node *head=new node;//头结点
head->next=NULL; //一开始链表中没有元素
node *tail=head; //尾指针
for(int i=0;i<n;i++){
insert(tail,A[i]);//由于是尾插法,所以在尾结点后面插入一个结点
tail=tail->next;//更新尾指针的值
}
return head; //返回头结点
}
链表元素逆置
采用头插法的方法,将链表中原来的结点一个个摘下来放入新的链表中
模板1
void reverse(node *head){
//将链表中的元素逆置
node *head2=(node*)malloc(sizeof(node));//新链表的头结点
//node *head2=new node;
head2->next=NULL;
//每次摘下原链表的第一个结点
while(head->next!=NULL){ //原链表中还有结点
node *p=head->next;//将第一个结点摘下
head->next=head->next->next;//原链表接上后面的结点
//以头插法将p结点插入新链表中
p->next=head2->next;
head2->next=p;
}
head->next=head2->next; //将原先的头结点指向新的链表
free(head2);//因为已经将原先的头结点指向新的链表,所以head2就没用了
//delete head2;
}
模板2
用到前面的insert()和del()函数,考试时需要写上
void insert(node *p,node *q){
//在p指向结点的后面插入一个结点q
q->next=p->next;
p->next=q;
}
node* del(node *p){
//删除p的后一个结点,并将该结点返回
//这里不考虑q为NULL的情况
node *q=p->next;//q为要删除的结点
p->next=p->next->next;
return q; //将从链表中删除的结点返回
}
void reverse(node *head){
//将链表中的元素逆置
node *head2=(node*)malloc(sizeof(node));//新链表的头结点
//node *head2=new node;
head2->next=NULL;
//每次摘下原链表的第一个结点
while(head->next!=NULL){ //原链表中还有结点
node *p=del(head);//将第一个结点摘下
insert(head2,p);//以头插法将p结点插入新链表中
}
head->next=head2->next; //将原先的头结点指向新的链表
free(head2);//因为已经将原先的头结点指向新的链表,所以head2就没用了
//delete head2;
}
获取链表中间结点(双指针法,快慢指针)
node* get_mid(node *head){
//获取链表的中间结点,双指针法
node *p=head;//快指针
node *q=head;//慢指针
while(p!=NULL && p->next!=NULL){
//p不为空结点且p不是最后一个结点
//快指针p走两步
p=p->next;
p=p->next;
//慢指针走一步
q=q->next;
}
//p走到末尾时,q刚好在中间位置
return q;
}
双链表
双链表结点结构体
struct node{
int data; //数据域
node *pre; //指向前一个结点的指针
node *next; //指向后一个结点的指针
};
双链表中插入结点
模板1
void insert(node *p,node *q){
//在p结点后插入结点q
//以下顺序不唯一,只要不断链就行
q->next=p->next;
q->pre=p;
if(q->next!=NULL){
q->next->pre=q;
}
p->next=q;
}
模板2
void insert(node *p,node *q){
node *r=p->next;//r可能指向NULL
//以下顺序任意
p->next=q;
q->pre=p;
q->next=r;
if(r!=NULL){
r->pre=q;
}
}
双链表中删除结点
模板1
node* del(node *p){
//将p结点后面的结点从链表中删除,并将删除的结点返回
//这里不考虑p后面结点为NULL的情况
node *q=p->next; //q为要删除的结点
p->next=p->next->next;
if(q->next!=NULL){
q->next->pre=p;
}
return q;//将链表中删除的结点返回
}
模板2
node* del(node *p){
//将p结点后面的结点从链表中删除,并将删除的结点返回
//这里不考虑p后面结点为NULL的情况
node *q=p->next;
node *r=q->next;//r可能指向NULL
p->next=r;
if(r!=NULL){
r->pre=p;
}
return q;
}
双链表的遍历
参考单链表的遍历