训练营第三天

本文介绍了链表操作的基本技巧,包括如何使用虚拟头结点简化删除操作,以及typedef的作用。同时展示了链表节点删除、添加、查找和翻转的实现,并强调了内存管理的重要性,提醒开发者养成良好的内存释放习惯。此外,还讨论了代码中可能存在的边界问题和优化点。
  • 删除链表中的节点
    • 大喜! 虽然很简单这道题,但是对于用c写的我,需要自己造东西,不看资料写出了虚拟头结点,开心 但是maybe只是凑巧加油!
    • e 现在是24日的0:46  睡觉 明天补 这几天在干综测 又是班委 害`
    • struct ListNode* removeElements(struct ListNode* head, int val){
          typedef struct ListNode ListNode;
          ListNode *shead;
          shead = (ListNode*)malloc(sizeof(ListNode));
          shead->next = head;
          ListNode *cur = shead;
          while (cur->next) {
              if (cur->next->val == val) {
                  ListNode* temp = cur->next;
                  cur->next = cur->next->next;
                  free(temp);
              }
              else {
                  cur = cur->next;
              }
          }
          head = shead->next;
          free(shead);
          return head;
      }
      •   可以见得 上面我们使用了虚拟头结点 为什么要使用这个东西呢
        • 如果直接对head操作, 那么我们就需要对head->val == val 时 特殊操作一个while  可是如果够早了虚拟头结点  那么我们就可以直接以一套方法处理整个链表
      • 其次 我们使用了一个typedef的东西,这是一个给别人起小名的方法,比如你叫张李王防守打法水电费防守打法,但是我给你起个小名叫小张。typedef struct ListNode ListNode; 橙色的是原名 绿色的是小名
      • 此外 我们也使用了free(temp);这个东西,将不符合的节点删除掉,虽然在我们简单地额程序中删不删无所谓,但是对于大型程序,不删很有可能造成内存泄露。所以我们培养好习惯删掉。 删除步骤,新构造一个 listNode* temp = cur->next; free(temp);
  • l链表的基本操作:
    • MyLinkedList *cur = obj->next;  直接赋值有没有错呢

    • 无意外的 简答题叠加在一块就会出现各种各样的错, 太令人不开心啦错  错误代码:

      • 
        typedef struct {
            int val;
            struct MyLinkedList* next;
        } MyLinkedList;
        
        
        MyLinkedList* myLinkedListCreate() {
            MyLinkedList* head;
            head = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            head->next = NULL;
            return head;
        }
        
        int myLinkedListGet(MyLinkedList* obj, int index) {
            MyLinkedList* cur;
            cur = obj->next;
            int i = 0;
            while (i != index && cur != NULL) {
                cur = cur->next;
                i++;
            }
            if (cur != NULL)
                return cur->val;
            else 
                return -1;
        }
        
        void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
            MyLinkedList* cur = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            cur->val = val;
            cur->next = obj->next;
            obj->next = cur;
        }
        
        void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
            MyLinkedList* cur = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            cur = obj->next;
            cur->next = NULL;
            MyLinkedList* temp = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            temp->val = val;
            while (cur->next) {
                cur = cur->next;
            }
            cur->next = temp;
        }
        
        void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
            if (index == 0) {
                myLinkedListAddAtHead(obj, val);
                return ;
            }
        
            MyLinkedList* cur = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            cur = obj->next;
            MyLinkedList* temp = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            temp->val = val;
            for (int i = 0; i < index - 1; i++) {
                cur = cur->next;
            }
            temp->next = cur->next;
            cur->next = temp;
        }
        
        void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
            MyLinkedList* cur = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            obj->next = cur;
            for (int i = 1; i < index && cur != NULL; i++) {
                cur = cur->next;
            }
            if (cur == NULL) 
                return;
            else 
                cur->next = cur->next->next;
        }
        
        void myLinkedListFree(MyLinkedList* obj) {
            while (obj != NULL) {
                MyLinkedList* temp = obj;
                obj = obj->next;
                free(temp);
            }
        }
        

        正确代码:

        typedef struct {
            int val;
            struct MyLinkedList* next;
        } MyLinkedList;
        
        
        MyLinkedList* myLinkedListCreate() {
            MyLinkedList *head = (MyLinkedList *)malloc(sizeof (MyLinkedList));
            head->next = NULL;
            return head;
        }
        
        int myLinkedListGet(MyLinkedList* obj, int index) {
            MyLinkedList *cur = obj->next;
            for (int i = 0; cur != NULL; i++) {
                if (i == index) {
                    return cur->val;
                }
                else {
                    cur = cur->next;
                }
            }
            return -1;
        }
        
        void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
            MyLinkedList *nhead = (MyLinkedList*) malloc(sizeof(MyLinkedList));
            nhead->val = val;
            nhead -> next = obj -> next;
            obj->next = nhead;
            
        }
        
        void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
            MyLinkedList *tail = (MyLinkedList*) malloc(sizeof(MyLinkedList));
            tail->val = val;
            tail->next = NULL;
            MyLinkedList *cur = obj;
            while (cur->next != NULL) {
                cur = cur->next;
            }
            cur->next = tail;
        }
        
        void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
            MyLinkedList *middle = (MyLinkedList*)malloc(sizeof(MyLinkedList));
            middle->val  = val;
            if (index == 0) {
               myLinkedListAddAtHead(obj,val);
                return ;
            }
            
            MyLinkedList *cur = obj->next;
            for (int i = 1; cur != NULL; i++) {
                if (i == index) {
                   middle->next = cur->next;
                   cur->next = middle;
                   return ;
                }
                else {
                    cur = cur->next;
                }
            }
        }
        
        void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
            if (index == 0) {
                MyLinkedList *tmp = obj->next;
                if(tmp != NULL) {
                    obj->next = tmp->next;
                    free(tmp);
                }
            }
            MyLinkedList *cur = obj->next;
            for (int i = 1; cur != NULL && cur->next != NULL; i++) {
                if (i == index) {
                    MyLinkedList *tmp;
                    tmp = cur->next;
                    cur->next = tmp->next;
                    free(tmp);
                    return ;
                }
                else {
                    cur = cur->next;
                }
            }
        }
        
        void myLinkedListFree(MyLinkedList* obj) {
            while (obj != NULL) {
                MyLinkedList *tmp = obj;
                obj = obj->next;
                free(tmp);
            }
        }
        
        •  计数怎么计? obj->next 也就是真正的头结点是我们的第一个(0)结点
        • 结构内指针域的定义方式: struct  MyListNode* next;
    • 翻转链表:
      • 链表是一刷是重点内容 所以翻转其实还不错 
      • 唯一的缺点就是  ; 对于边界问题考虑不足,比如head 是空的时候,我们直接返回就可以 ,而不是继续一堆操作
      • 另外 还有个问题就是 我什么时候需要对创建的结构体指针进行动态分配 什么时候不需要呢  answer :
        • 1如果需要多添加一个节点来存储这个数据,然后放到链表中的时候,需要申请内存。
        • 2如果只需要一个指针 来找链表中的某个位置,就不需要申请,只需要定义一个变量,指向某个空间的位置。
          • struct ListNode* reverseList (struct ListNode* head) {
                if (head == NULL) return NULL;
                struct ListNode* cur ;
                cur = head->next;
                struct ListNode* temp;
                struct ListNode* pre;
                pre = head;
                pre->next = NULL;
                while (cur) {
                    temp = cur->next;
                    cur->next = pre;
                    pre = cur;
                    cur = temp;
                }
                return pre;
            }

不断成长!加油 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值