单链表的创建、插入、删除操作(C语言实现)
#include <stdio.h>
#include <stdlib.h>
/*定义单链表节点类型*/
typedef struct ListNode{
int val;
struct ListNode *next;//C语言这里需要加struct
}ListNode;
/*尾插法创建单链表——形成与输入相同的序列*/
ListNode* initLinkList(){
//创建虚拟头节点
ListNode* dummyHead=(ListNode*)malloc(siezof(ListNode));
dummyHead->val=0;
dummyHead->next=NULL;
//创建操作指针
p=dummyHead;
//创建变量n,并接收将要输入的数据个数
int n;
scanf("%d",n);
//循环接收数据并封装成单链表节点,并挂载在单链表上
for(int i=0;i<n;i++){
int num;
scanf("%d",num);
ListNode* node=(ListNode*)malloc(siezof(ListNode));
node->val=num;
node->next=NULL;
p->next=node;
p=p->next;
}
return dummyHead->next;
}
/*单链表中间插入元素和头部插入元素*/
ListNode* insertElem(ListNode* head,int elem int location){
ListNode* dummyHead=(ListNode*)malloc(siezof(ListNode));
dummyHead->next=head;
ListNode* p=head;//为了方便在头节点之前插入
for(int i=0;i<location-1;i++){
p=p->next;
//如果时插入尾部
if(p->next==NULL){
ListNode* last=(ListNode*)malloc(siezof(ListNode));
last->val=elem;
last->next=NULL;
p->next=last;
return head;
}
}
//如果是插入中间或者头部
ListNode* insert=(ListNode*)malloc(siezof(ListNode));
insert->val=elem;
insert->next=NULL;
ListNode *temp=p->next;
p->next=insert;
insert->next=temp;
return head;
}
/*单链表删除元素*/
ListNode *delElem(ListNode *head,int target){
ListNode* dummyHead=(ListNode*)malloc(siezof(ListNode));
dummyHead->next=head;
ListNode* p=dummyhead;//为了方便删除头节点
while(p->next!=NULL){//最后一个元素能遍历到吗?能,当p指向倒数第二个时
if(p->next->val==target){
ListNode* temp=p->next;
p->next=p->next->next;
free(temp);
}
p=p->next;
}
return head;
}
/*单链表查找元素*/
ListNode* findElem(ListNode* head,int target){
ListNode* p=head;
while(p!=NULL){
if(p->val==target){
return p;
}
p=p->next;
}
return NULL;//???没找到是否返回NULL?
}
注意:
- 单链表尾部插入元素分为一类,加了虚拟头节点后头部和中间插入元素分为一类。
- 单链表中间插入元素只要把握好指针操作顺序,不需要创建临时指针将三个节点全指起来。
insert->next=p->next;
p->next=insert;
C++实现,对单链表的删除指定元素操作
/*单链表节点类型定义*/
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
//注意删除单链表节点时要访问其上一个节点
//对头节点的删除操作与其它节点不一样
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
//******************************************************
//添加虚拟头节点
ListNode* dummyNode=new ListNode(-1);
dummyNode->next=head;//易漏掉这句
//新建操作指针,初始化指向虚拟头节点
ListNode* p=dummyNode;
//*****************************************************
while(p!=NULL&&p->next!=NULL){//为啥一定要加p!=NULL?
if(p->next->val==val){
p->next=p->next->next;
}
p=p->next;//不能丢
}
return dummyNode->next;
}
};
注意:
- 使用C++中的sturct定义节点类型,需要添加构造函数。因为后面新建虚拟头节点调用节点的构造函数实现
- 链表操作函数返回的还是链表,以链表头节点形式返回,返回值是ListNode* 类型
- 新建操作指针,初始化指向虚拟头节点
- 注意命中要删除的目标节点是通过其前驱节点实现的