Bootstrap

代码随想录 第三天||203.移除链表元素

链表与数组不同,链表是映像存储,不像数组那样连续存址,所以对于链表删除节点应该按照下面的图示进行:

代码如下:

#include<iostream>
//#include<stdio.h>
#include<cmath>
#include<string>

using namespace  std;
//    // Definition for singly-linked list.
    //struct 定义的是一个简单的单向链表节点,ListNode是一个链表节点,ListNode* 代表一个链表
          //struct ListNode{
          //int type;
          //union {
          //    int i;
          //    string str;
          //} val; // 联合体,用于保存不同类型的值
          //ListNode *next;
          //ListNode() : val{.i=0}, next(nullptr) {}        //这是一个不带参数的构造函数,用冒号语法对val和next成员变量进行初始化。它将val初始化为0,next指针初始化为nullptr(空指针)。
          //ListNode(string s) : val(), next(nullptr) {}        //这是一个不带参数的构造函数,用冒号语法对val和next成员变量进行初始化。它将val初始化为0,next指针初始化为nullptr(空指针)。
          //ListNode(int x) : val(x), next(nullptr) {}  //在C++中,冒号可以用于成员初始化列表。构造函数是用于创建对象并对其进行初始化的特殊函数,使用冒号语法可以在构造函数内部设置成员变量的初始值。这种方式在效率和可读性上都比在构造函数体内赋值更好。
          //ListNode(int x, ListNode* next) : val(x), next(next) {}
          //ListNode(string s, ListNode *next) : str(s), next(next) {}
          //};

         // 在这个数据结构中,联合体中包含了两个不同类型的成员变量i和str。在构造函数ListNode(string s)中,使用了默认构造函数对联合体val进行初始化,但是此时联合体中没有指定具体的成员变量类型,编译器也无法知道应该使用哪个成员变量进行初始化。因此,在这里需要显式指定要初始化的成员变量。将构造函数ListNode(string s)中的val()修改为 { .str = s },即可指定要初始化联合体中的字符串变量str。这样修改后的代码如下:


          struct ListNode {
              int val;
              //string str;
              //union type{
              //    int i;
              //    string str;
              //}; // 联合体,用于保存不同类型的值   
                  ListNode* next;
                  ListNode() : val{ 0 }, next(nullptr) {}    // 这是一个不带参数的构造函数,用冒号语法对val和next成员变量进行初始化。它将val初始化为0,next指针初始化为nullptr(空指针)。
                 // ListNode(string s) : type{ .str = s }, next(nullptr) {}  // 这是一个不带参数的构造函数,用冒号语法对val和next成员变量进行初始化。它将val初始化为0,next指针初始化为nullptr(空指针)。
                  ListNode(int x): val{ x }, next(nullptr) {}    // 在C++中,冒号可以用于成员初始化列表。构造函数是用于创建对象并对其进行初始化的特殊函数,使用冒号语法可以在构造函数内部设置成员变量的初始值。这种方式在效率和可读性上都比在构造函数体内赋值更好。
                  ListNode(int x, ListNode* next) : val{ x }, next(next) {}
                 // ListNode(string s, ListNode* next) : type{ .str = s }, next(next) {}
          };

//删除对应值的节点
class Solution1 {
public:
    //使用数组初始化量表
    ListNode* createList(std::initializer_list<int> vals) {
        ListNode dummy(0);   //定义一个结构体变量dummy
        ListNode* tail = &dummy;   //将dummy的内存地址解引用
        for (auto val : vals) {
            tail->next = new ListNode(val);   //将tail的指针所访问的内存,赋予值val,同时建立一个新的链表节点
            tail = tail->next;      //递归
        }
        return dummy.next;
    }
    ListNode* removeElements(ListNode* head, int targetval) {
        //如果删除头结点
        while(head->val == targetval && head != NULL) {  //为啥不是if呢,如果删除头结点后发现,原来的第二个节点里的值也是targetval,如果用if就直接删除头结点后执行完了
            ListNode* tempt = head;
            head = head->next;
            delete tempt;
        }

        //如果删除的是链表内部的节点
        //ListNode* cur=ListNode*head;
        ListNode* cur = head;
        while (cur!= NULL && cur->next != NULL) {
            if (cur->next->val != targetval) {
                //ListNode* tempt = cur;
                cur = cur->next;
              // delete tempt;
            }
            else {
                ListNode* tempt = cur->next;
                cur->next = cur->next->next;
                delete tempt;
            }

        }
        return 0;
    }
};
//定义输出链表单元操作
//void printList(ListNode* head) {
//    ListNode* cur = head;
//    while (cur != nullptr) {
//        std::cout << cur->val << "  ";
//        cur = cur->next;
//    }
//}


class UsingDummynode {
public:
    ListNode* deletenode(ListNode* head, int val) {
       // ListNode* freenode = (0);//会导致delete freenode越界,原因就是这是个静态指针,使用后会自动释放
        ListNode* freenode=new ListNode(0);  //delete freenode越界is  OK
        freenode->val = 0;
        freenode->next = head;
        //以上三段代码施加了一个虚拟节点
        ListNode* cur = freenode;
        while (cur!=NULL&&cur->next!=NULL){
            if (cur->next->val == val) {
                ListNode* tempt = cur;
                cur->next = cur->next->next;
                delete tempt;
            }
            else {
                cur = cur->next;
            }
        }
//        delete freenode;
        return head;
    }
   

};


//class designListNode {
//public:
//    //获取第Index个链表的节点
//    
//    int  Get_index_node(ListNode* head, int index) {
//        ListNode* cur =head;
//        int i = 0;
//      //  while (cur->val != NULL && i = index) {
//            while (cur->val != NULL) {
//                if (i+1 == index) {
//                    return cur->val;    //如果当前节点编号==index,返回本节点的值
//                    break;
//                }
//                else if(i+1!=index){   
//                    i=i+1;
//                    cur = cur->next;     //如果当前节点的编号!=index,遍历i++
//                }
//                else {
//                    return -1;
//                }
//        }
//           // while(cur->val != NULL&&i==index)
//    }
//    //在第Index个链表节点前插入新的节点
//
//    ListNode* insert_before_index_node(ListNode* head, int index) {
//        ListNode* cur = head;
//        ListNode* waitting_insert_node=new ListNode();
//        //waitting_insert_node->val = 6;
//        int i = 0;
//        //  while (cur->val != NULL && i = index) {
//        while (cur->val != NULL) {
//            if (i == index) {//下一个节点就是待前插入节点
//                ListNode* tempt = cur;
//                waitting_insert_node->next = cur->next;
//                cur->next = waitting_insert_node;
//                delete tempt;
//                break;
//            }
//            else if (i != index) {
//                i = i + 1;
//                cur = cur->next;     //如果当前节点的编号!=index,遍历i++
//            }
//            else {
//                return head;
//            }
//        }
//        // while(cur->val != NULL&&i==index)
//        delete waitting_insert_node;
//    }
//};

int main()
{
    Solution1 s1;
    //UsingDummynode U1;
    //designListNode designListNode1;
    ListNode* testList = s1.createList({ 8, 2, 3, 4, 5, 6, 7 }); // 用{1,1,3,4,5,6,7}初始化链表
   // ListNode* head = s1.createList({ 1, 2, 3, 4, 6, 6, 7 }); // 用{1,1,3,4,5,6,7}初始化链表
    //ListNode* head =new ListNode (1, 2, 6, 3, 4, 5, 6);   //C1001 内部编译器错误编译器无法为构造生成正确的代码,通常是由于特定表达式和优化选项的组合或分析中出现的问题。
    ListNode* result = s1.removeElements(testList, 6);
    //ListNode* result = U1.deletenode(testList, 1);
    int index = 4;
   // ListNode* result = designListNode1.insert_before_index_node(testList, index);
    ListNode* check = result;   //输出1 2 3 4 5 7
    //ListNode* cur = &result;  //"ListNode**类型的值不能用于初始化ListNode*类型的实体"其实原因就是,&result代表一个储存result指针的地址,而cur本身就是一个结构指针(指向ListNode类型的指针)
    //ListNode* cur = result;
    /*while (result != NULL) {
        cout << result->val << "  ";
        result = result->next;
    }*/
    cout << "[";
    while (check != NULL) {
       cout << check->val;  //check位置原来是cur,因为cur我用的动态存储,C++是不会自动清理内存的,所以如果我在main还使用cur,就会导致越界溢出
      
        if (check->next != NULL)
        {
            cout << ",";
        }
        check = check->next;
    } cout << "]";
    //printList(result);
   // cout << result;
    return 0;
}

 

 

;