设计链表的实现

本文探讨了在C语言中设计链表时的选择,强调了带头指针与不带头指针的区别,特别是在链表的插入和删除操作中的影响。文章提醒读者避免使用`ListNode`作为结构体名称,因为LeetCode已有此定义,建议使用`LNode`代替。内容还解释了头结点的作用,指出头结点能简化添加和删除操作的特殊情况判断,提高代码的简洁性和统一性。
摘要由CSDN通过智能技术生成

解题思路
我们知道链表有带头指针和不带头指针两种,这个题目的坑在于你最开始选择哪种方式决定了你是走向正确还是失败。在设计之前最好看清各函数的输入、输出,由于插入和删除操作都返回为空,而我们都知道C语言中的函数传惨是按值传递,也就是说,如果你选择不带头指针方式,是没法在在头部进行插入和删除操作的,你尽可以改变函数内的头指针位置,但是主调函数中的头指针位置是无法改变的。
还有要注意的是结构体不能声明为ListNode,因为Leetcode中内部已经定义了该变量,因此这里定义结构体为LNode。

1.先区分一下概念:

头结点:

在单链表第一个元素结点之前设置的一个结点,数据域可以不存任何信息,指针域指向单链表第一个元素的结点。对于单链表来说,头结点可有可无,但为了操作方便,一般情况下单链表都具有头结点,后面的分析将会区别一下有头结点和没有头结点的区别。

优点:

减少了单链表添加删除时特殊情况的判断,减少了程序的复杂性,主要是添加和删除在第一个有元素的结点(首元结点)上有区别,如果链表没有头结点,则删除或添加时都得需要判断一次首元结点,有了头结点以后,首元结点实际为链表的第二个结点,使得所有的元素结点的添加删除更具有统一性,举例如下:

代码

typedef struct LNode{
  int val;
  struct LNode *next;
} MyLinkedList;

/** Initialize your data structure here. */
MyLinkedList* myLinkedListCreate() {
  MyLinkedList *temp = (MyLinkedList*)malloc(sizeof(MyLinkedList));
  temp->next = NULL;
  return temp;
}

/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
int myLinkedListGet(MyLinkedList* obj, int index) {
  if(!obj) return -1;
  MyLinkedList *ptr = obj->next;
  for(int i = 0; ptr && i < index; i++) {
      ptr = ptr->next;
  }
  return ptr ? ptr->val : -1;
}

/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
  if(!obj) return -1;
  MyLinkedList *temp = (MyLinkedList*)malloc(sizeof(MyLinkedList));
  temp->val = val;
  temp->next = obj->next;
  obj->next = temp;
}

/** Append a node of value val to the last element of the linked list. */
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
  if(!obj) return -1;
  MyLinkedList *temp = (MyLinkedList*)malloc(sizeof(MyLinkedList));
  temp->val = val;
  temp->next = NULL;
  
  // 最后一个不为NULL的节点
  MyLinkedList *ptr = obj;
  while(ptr->next) {
    ptr = ptr->next;
  }
  ptr->next = temp;
}

/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
  if(!obj || index < 0) return -1;

  MyLinkedList *temp = (MyLinkedList*)malloc(sizeof(MyLinkedList));
  temp->val = val;
  temp->next = NULL;

  // 找到要插入的前一个节点
  MyLinkedList *ptr = obj;
  for(int i = 0; ptr && i < index; i++) {
    ptr = ptr->next;
  }
  if(ptr) {
    temp->next = ptr->next;
    ptr->next = temp;
  }
}

/** Delete the index-th node in the linked list, if the index is valid. */
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
  if(!obj || index < 0) return -1;

  // 找到要删除的前一个节点
  MyLinkedList *ptr = obj;
  for(int i = 0; ptr && i < index; i++) {
    ptr = ptr->next;
  }
  if(ptr && ptr->next) {
    ptr->next = ptr->next->next;
  }
}

void myLinkedListFree(MyLinkedList* obj) {
  if(!obj) return -1;
  obj->next = NULL;
}

/**
 * Your MyLinkedList struct will be instantiated and called as such:
 * MyLinkedList* obj = myLinkedListCreate();
 * int param_1 = myLinkedListGet(obj, index);
 
 * myLinkedListAddAtHead(obj, val);
 
 * myLinkedListAddAtTail(obj, val);
 
 * myLinkedListAddAtIndex(obj, index, val);
 
 * myLinkedListDeleteAtIndex(obj, index);
 
 * myLinkedListFree(obj);
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值