单链表的插入和删除

   常见的数据结构只有两种:

   1、数组

   2、链表 

   数组中的元素是连续存储的,而链表的元素则可以不连续,只需要有指针指向下一个元素即可。因此链表适合存储插入删除比较频繁的一组数据。另外链表的存储空间是动态的,不必预先分配指定的空间大小。。下面介绍链表的几种常见操作。

   首先先定义一个链表

   

  struct linklist {

    int data;

    struct linklist *next;

  };


  typedef linklist *linklistp;


 然后定义两个函数:

  

/**

 头结点插入

 */

linklistp insert_head(linklistp head,linklistp newnode){

   

    newnode->next = head;

    head = newnode;

    

    return head;

    

}

/**

 尾结点插入

 */

linklistp insert_tail(linklistp head,linklistp newnode){

    

    if(head == NULL){

        head = newnode;

        return head;

    }

    

    linklistp temp = head;

    while (1) {

        if(temp->next == NULL){

            

            temp->next = newnode;

            break;

            

        }

        temp = temp->next;

    }

    return head;

}

之后我们利用尾节点插入的函数来创建一个链表

    linklistp head = NULL;

    for(int i = 0;i < 10; i ++){

        linklistp newNode = (linklistp)malloc(sizeof(linklist));

        newNode->data = i;

        newNode->next = NULL;

        head = insert_tail(head,newNode);

    }


这样就创建了一个包含十个元素的链表。

然后再定义一个函数,求链表长度

/**

 获取链表长度

 */

int getLength(linklistp head){

    

    if(head == NULL){

        return 0;

    }

    

    int count = 1;

    linklistp temp = head;

    while (temp->next != NULL) {

        temp = temp->next;

        count ++;

    }

    return count;

    

}


然后实现指定位置插入元素的函数

/**

 指定位置插入

 */

linklistp insertAtIndex(linklistp head,int index,linklistp newNode){

   

    if(head == NULL){

        return head;

    }

    int length = getLength(head);

    //Tips:超出链表范围,直接返回

    if(index >= length+1 || index < 0) {

        return head;

    }

    //Tips:如果是在头结点前面插入

    if(index == 0){

        

        return insert_head(head, newNode);

    }

    //Tips:如果是在尾节点后面插入

    if(index == length){

        

        return insert_tail(head, newNode);

        

    }

    

    //Tips:先找到要插入位置的前一个元素,并且找到该元素的后继,然后将前一个元素的next指针指向待插入            的元素,待插入的元素的next指针指向刚才我们找到的后继,这样插入操作就完成了

    linklistp temp = head;

    for(int i = 0; i <= length; i ++){

        

        if(i == index-1){

            

            linklistp nextNode = temp->next;

            temp->next = newNode;

            

            newNode->next = nextNode;

            break;

            

        }

        temp = temp->next;

        

    }

    return head;

    

}


下面再来定义删除指定元素的操作

/**

 删除指定节点

 */

linklistp deleteAtIndex(linklistp head,int index){

   

    if(head == NULL){

        return head;

    }

    int length = getLength(head);

    if(index < 0 || index > length){

        return head;

    }

    //Tips:如果要删除的是头结点,那么把链表头结点变成原头结点后继,删除原头结点

    linklistp temp = head;

    if(index == 0){

        head = temp->next;

        free(temp);

        return head;

    }

    //Tips:删除的时候先找到要删除元素的前一个元素temp,让前一个元素temp的next指向要删除位置的元素            的后继,然后释放被删除的元素

    for(int i = 0; i < length; i ++){

        

        if(i == index-1){

            linklistp nextNode = temp->next->next;

            temp->next = nextNode;

            free(temp);

            

            break;

        }

        temp = temp->next;

    }


    return head;

}


最后再写一个函数输出链表的所有元素

/**

 输出链表元素

 */

void outPut(linklistp head){

    

    linklistp temp = head;

    while (temp) {

        

        printf("%d\n",temp->data);

        temp = temp->next;

    }

    

}

这样就可以进行操作删除的验证了

### 单链表插入删除节点的方法 #### 插入节点 在单链表插入新节点通常涉及找到合适的位置并更新相邻节点之间的链接。以下是具体过程: 对于头部插入的情况,在已有头指针的情况下,创建一个新的节点并将它的`next`设置为当前的头节点,之后更新头指针指向新的节点即可完成操作[^1]。 ```cpp void insertAtHead(Node*& head, int value){ Node* newNode = new Node(); newNode->data = value; newNode->next = head; head = newNode; } ``` 如果是在指定位置之前插入,则需先遍历到目标位置前的一个节点,并调整前后两个节点间的连接关系[^4]。 ```cpp bool insertAfter(Node* prevNode, int newValue) { if (prevNode == NULL) { cout << "the given previous node cannot be NULL"; return false; } Node* newNode = new Node(); // Allocate new node newNode->data = newValue; // Put in the data newNode->next = prevNode->next; // Make next of newNode as next of prev_node prevNode->next = newNode; // Move the next of prev_node as newNode return true; } ``` #### 删除节点 当需要移除某个特定值的第一个匹配项时,可以从头开始逐个比较直到发现相等的数据元素为止。一旦找到了待删去的目标对象,就要修改它前面那个元素所持有的引用使其不再指向即将被释放的对象而是跳过这个对象直接连向后者后面的那部分列表[^5]。 ```cpp void deleteNode(Node *&head_ref, int key) { // Store head node Node* temp = head_ref, *prev; // If head node itself holds the key to be deleted if (temp != NULL && temp->data == key) { head_ref = temp->next; // Changed head free(temp); // Free old head return; } // Search for the key to be deleted, keep track of the // previous node as we need to change 'prev->next' while (temp != NULL && temp->data != key) { prev = temp; temp = temp->next; } // If key was not present in linked list if (temp == NULL) return; // Unlink the node from linked list prev->next = temp->next; free(temp); // Free memory } ``` 上述代码展示了如何处理不同场景下的插入删除动作,无论是作为首元还是中间/末端的新成员加入或是退出队伍都能得到妥善解决[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值