结论,如果不是一定强制不要家头结点,链表最好加上头结点,不然会出现头结点丢失的情况。非常的麻烦。看下面代码:完成一个没有头结点的链表 初始化结构体
struct ListNode {
int val;
struct ListNode *next;
};
这个看似简单,但是包含了两层意思,一个是链表,一个是链表的节点。及其容易混淆理解
void pushFromTail(struct ListNode* obj, int val)
{
struct ListNode* ptrNode = obj;
while (ptrNode->next != NULL)
{
ptrNode = ptrNode->next;
}
ptrNode->next = (struct ListNode*)malloc(sizeof(struct ListNode));
ptrNode->next->val = val;
ptrNode->next->next = NULL;
}
链表的初始化与创建:
struct ListNode* myInitList = (struct ListNode*)malloc(sizeof(struct ListNode));
myInitList->val = 1;
myInitList->next = NULL;
pushFromTail(myInitList, 2);
这里面有两个陷阱: 1:必须要初始化。 2:尾部加入,一定要用ptr.next增加最后一个节点,不然会出现头结点丢失的情况。 对比有头节点的 结构体定义:
typedef struct LinkNode
{
int val;
struct LinkNode* next;
}LinkNode;
typedef struct {
int size;
LinkNode* head;
} MyLinkedList;
一个结构体表示节点,一个结构体变式链表,很容易理解。 链表初始化:不需要初始化头结点,因为头结点是一个虚的节点
MyLinkedList* mylist = myLinkedListCreate();
尾部加入也容易理解:
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
if (obj == NULL) return ;
LinkNode* ptrNode = NULL;
ptrNode = obj->head;
while (ptrNode->next != NULL )
{
ptrNode = ptrNode->next;
}
ptrNode->next = (LinkNode*)malloc(sizeof(LinkNode));
ptrNode->next->val = val;
ptrNode->next->next= NULL;
obj->size++;
}
所以在穿件链表的时候,除非是题目特殊要求,建议加上头结点。用连个结构体来表示,容易理解。
|