常用的链表/堆栈 都是先 生成一个头指针head 再用头指针 申请一个 头节点空间,然后 头节点 的Data 一般是不储存数据的 ,
{ 当用 malloc函数分配内存后head就变为了名叫head的节点了。而不在是一个单独的指针了 }
{ 注意只要用malloc申请的空间 才能使 指针再 下次循环 指向不同的 内存空间 ,即每次申请的内存 地址都是一定不相同的,除非free了 这个内存空间,否则不可能再次被使用 }
当为链表/堆栈 为空时 则头节点 head->Next=NULL;否则则指向会储存 数据的普通节点;(这样实现的链表/堆栈 的空类型 判断 打印操作都比较方便)
【带头节点(不存放普通数据得)的引入是为了对链表删除、逆向、建立的时候操作更统一,不用专门对第一个元素单独处理。】
3、大部分程序用带头节点来存储链表的长度。
4、如何区分,很简单,看看程序的定义,和程序在建立链表的时候有没针对第一个节点做特殊处理。(做了特殊处理的,则说明头节点储存了数据/即没有头节点 ,只要头指针)
//说明的更加详细的博文-> https://blog.csdn.net/endeavor_g/article/details/80552680
#include#includetypedefintElementType;
typedefstruct Node *PtrToNode;structNode {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;//List是一个 struct Node 指针
List Merge( List L1, List L2 );
List Read();/*细节在此不表*/
void Print( List L ); /*细节在此不表;空链表将输出NULL*/
intmain(){
List L1,L2,L;
L1=Read();
L2=Read();//Print(L1);//Print(L2);
L=Merge( L1, L2 );
printf("\n------\n");
Print(L);
Print(L1);
Print(L2);
}
List Read() {
List r,L=(struct Node*)malloc(sizeof(structNode));
L->Next=NULL;//创建一个头节点;一般链表都是带头节点的;头节点的 Data是没有存放数据的 ;当然也可以创建没有头节点的链表;//因为带有头节点的 链表,可以让print操作更加简练;因此链表都是有一个 不存放数据的头节点的; 【链表】
r=L;intn;
scanf("%d",&n);while(n--) {///尾插法
Node *p=(struct Node*)malloc(sizeof(structNode));
scanf("%d",&p->Data);
p->Next=NULL;
r->Next=p;
r=p;
}returnL;
}voidPrint(List L) {if(L->Next) {
List r=L;while(r->Next) {
r=r->Next;
printf("%d",r->Data);
}
puts("");
}else{
printf("NULL\n");
}
}
List Merge(List L1,List L2){
List p1,p2,p3,head;
head=(struct Node*)malloc(sizeof(structNode));
p3=head;
p3->Next=NULL;
p1=L1->Next,p2=L2->Next;while(p1&&p2){if(p1->Data<=p2->Data){
p3->Next=p1;
p3=p3->Next;
p1=p1->Next;
}else{
p3->Next=p2;
p3=p3->Next;
p2=p2->Next;
}
}
p3->Next=p1?p1:p2;
L1->Next=NULL;
L2->Next=NULL;returnhead;
}
原文:https://www.cnblogs.com/home979/p/9226861.html