链表标志是头指针,只要知道头指针就可以对链表进行各类操作
头结点是为了方便操作而设置的非必要的结点结构体
头指针指向头结点的地址,所以它是一个二级指针
一般带头结点的链表程序中,对于头指针都没有很明显的表示出来
比如
构造结点结构体
typedef struct Node
{
int a;
struct Node *next;
}node,*pnode;
创建链表
pnode creat()
{
pnode head=(pnode)malloc(sizeof(node));
//创建头结点;
assert(head!=NULL);
head->next=NULL;
return head;
}
如上,仅仅是创建了一个头结点,之后是进行在头结点后面添加结点,之后就是遍历结点输出结点的数据域
当我们要输出结点数据域的时候会创建一个输出函数:
void pop(pnode List);
注意这里List仅仅是一个一级指针,它表示头结点的指针,而头指针是一个二级指针(指向头结点的地址,即指向指针的指针),当我们使用头结点的指针List的时候,函数体内会如下操作:
void pop(pnode List)
{
pnode p;
p=List->next;
while(p!=NULL)
{
printf(“”,p->data);//打印数据域
p->next=p;
}
}
pop函数的参数是头结点的指针,这时候就很不理解,按道理应该传递头指针而非头结点的指针
所以pop函数中显式地传递头指针的写法可以改成如下:
void pop(pnode *List)
{
pnode p;
p=(*List)->next;
while(p!=NULL)
{
printf(“”,p->data);
p=p->next;
}
}
这两种写法效果是一样的,但是第二种显式地表示了头指针这个概念。
头指针是一个二级指针 node **p;
头结点指针是一个一级指针:node *h;
node * 效果同 pnode。
对头结点指针取地址运算:&h,得到的就是头指针p
带头结点的链表可以这样方便的隐藏头指针这个概念。
如有错误欢迎指正。