//天勤p28,例2-3
//A,B是两条单链表(带表头节点),其中元素递增有序。设计一个算法,将两条链表合并成一条非递减有序的链表
#include "stdio.h"
#include<stdlib.h>
typedef struct Node{ //结构体
int data;
Node *next;
}Node;
void init(Node *&p){ //初始化
p->next = NULL;
}
void listCreate(Node *&p,int n){ //参数:头节点,数据
Node *q = (Node *)malloc(sizeof(Node));
//****头插法建立(插入)链表*********(后进先出)
q->data = n;
q->next = p->next;
p->next = q;
//****************
}
void Traversal(Node *&p){ //遍历
Node *q = p->next;
while (q != NULL)
{
printf("%d ",q->data);
q = q->next;
}
}
void merge(Node *&A,Node *&B,Node *&C){ //每次从两条链表里选一个最小的插入 //由于两条链表都是递增有序的,只要比头就好了
Node *p = A->next;
Node *q = B->next;
C->next = NULL;
Node *cTail = C; //指向c的尾部,只有头节点时头就是尾
// 首先要找到元素,再插入
while (p != NULL && q != NULL){
if (p->data > q->data){ //尾插法将AB链表上的节点插到C中,注意这里是整个节点插入,这样C就不用另外申请空间
cTail->next = q; //将q从接入C的尾部
cTail = q; //尾指针指向最新的尾部q
q = q->next; //q后移
}else{
cTail->next = p;
cTail = p;
p = p->next;
}
}//到最后,若A或B链表还有剩,则直接并入到c尾
if (p != NULL){
cTail->next = p;
}
if (q != NULL){
cTail->next = q;
}
}
// void merge(Node *A,Node *B,Node *&C){ //书上示例代码
// Node *p = A->next;
// Node *q = B->next;
// Node *r;
// C = A;
// C->next = NULL;
// free(B);
// r = C;
// while (p != NULL && q != NULL){
// if (p->data <= q->data){
// r->next = p;
// p = p->next;
// r = r->next;
// }else{
// r->next = q;
// q = q->next;
// r = r->next;
// }
// }
// r->next = NULL;
// if (p != NULL) r->next = p;
// if(q != NULL) r->next = q;
// }
int main(){
Node *list1 = (Node *)malloc(sizeof(Node));
Node *list2 = (Node *)malloc(sizeof(Node));
Node *list3 = (Node *)malloc(sizeof(Node));
init(list1);
init(list2);
init(list3);
for(int i=5;i>=0;i--){
listCreate(list1,i+1); //生成的链表:123456
listCreate(list2,2*i); //02468 10 //最后合并的链表:01223445668 10
}//先生成两条链表,方便检验
merge(list1,list2,list3);
Traversal(list3);
getchar();
return 0;
}
//使用malloc需要使用库stdlib.h
// 定义节点结构体要用如下格式:
// typedef struct Node{
// int data;
// Node *next;
// }Node;
//链表创建一个节点的方法:
//Node *p = (Node*)malloc(sizeof(Node));
// 尾插法插入节点:
// 首先定义一个尾节点tail,并让tail指向链表list的尾部
// 每插入一个节点p时,使用tail->next = p将新节点接入链表的尾部,这时tail指向的就不是链表的最后一个节点了,需要让tail指向最后一个节点
// 再用tail = p使尾节点tail重新指向链表的尾部
//假如p是一个结构体变量(定义方法:NODE p),就用‘ . ’
//假如p是一个结构体指针(定义方法 NODE *p),就用' -> '
//函数传参问题:
//假如p是一个结构体变量(定义方法:NODE p),传参时参数为 NODE &p
//假如p是一个结构体指针(定义方法 NODE *p),传参时参数为 NODE *&p
//链表类型问题:
// 有头节点:链表开头节点的数据域不存数据,从开头节点的下一个节点开始存数据,开头节点的下一个节点是第一个节点
// 没有头节点:链表开头节点数据域存放数据,开头节点即是链表的第一个节点