1.用c和cpp构造链表
typedef struct ListNode* initLink(){
int i;
struct ListNode* p = NULL;
struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
temp->val = 0;
temp->next = NULL;
p = temp;
for (i = 1; i < 5; i++){
struct ListNode* a = (struct ListNode*)malloc(sizeof(struct ListNode));
a->val = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
int main() {
struct ListNode* p = NULL;
printf("初始化链表为:\n");
p = initLink();
return 0;
}
这里有一些关键点需要注意:
typedef struct ListNode*
这个语法是错误的。typedef用于创建类型别名,但这里看起来像是试图定义一个结构体并返回一个指向该结构体的指针。正确的做法应该先定义结构体,然后在函数中返回指向该结构体的指针。- 在
initLink
函数中,你创建了一个链表,然后返回了链表的第一个节点的指针。这个函数没有错误,但是需要确保在使用返回的指针时,不会出现内存泄漏。 - 在
main
函数中,调用了initLink
函数并把返回的指针赋值给了p
。然后就可以通过这个指针来遍历和打印链表了。
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
ListNode* initLink() {
int i;
ListNode *p = NULL;
ListNode *temp = (ListNode*)malloc(sizeof(ListNode));
temp->val = 0;
temp->next = NULL;
p = temp;
for (i = 1; i < 5; i++){
ListNode *a = (ListNode*)malloc(sizeof(ListNode));
a->val = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
void printLink(ListNode *p) {
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
}
int getLength(ListNode *p){
ListNode* temp = p; //创建一个新的指针temp并将其初始化为p所指向的地址。
//这样,temp现在也指向链表的第一个节点。
int length=0;
while (temp) {
length++;
temp = temp->next;
}
return length;
}
int main() {
ListNode *p = NULL; //初始化NULL,防止随机分配内存
printf("初始化链表为:\n");
p = initLink();
printLink(p);
// 注意这里需要释放链表占用的内存,否则会出现内存泄漏。你可以在主函数结束前加上释放内存的代码。比如:
// while (p != NULL) {
// ListNode *temp = p;
// p = p->next;
// free(temp);
// }
int length=getLength(p);
printf("lidt length: %d\n",length);
return 0;
}
运行结果:
让我们逐行分析这段代码:
ListNode *temp = (ListNode*)malloc(sizeof(ListNode));
这行代码做了以下几件事:
ListNode *temp
: 这里声明了一个名为temp
的指针,该指针指向ListNode
类型的结构体。(ListNode*)
: 这是一个类型转换。由于malloc
返回的内存块是未类型的,所以我们需要将其强制转换为ListNode
类型。malloc(sizeof(ListNode))
: 这调用了malloc
函数,请求分配一个大小为sizeof(ListNode)
的内存块。sizeof
运算符返回其操作数所占用的内存大小(以字节为单位)。在这里,操作数是ListNode
类型,因此它会返回ListNode
结构体的大小。- 总的来说,这行代码的作用是分配足够的内存来容纳一个
ListNode
结构体实例,并将分配的内存地址赋给temp
指针。
请注意,使用malloc
分配的内存需要使用free
来释放,以避免内存泄漏。在不再需要使用这个ListNode
时,你应该调用free(temp);
来释放这块内存。
2.链表的增删改查
1.链表的插入
这个函数接受三个参数:一个指向链表头节点的指针,要插入的数据,以及要插入的位置。如果插入位置为1或链表为空,则新节点将被插入到链表的头部。否则,函数将找到要插入位置的前一个节点,并将新节点插入到该节点之后。要注意的是要判断插入的位置是否有效。
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
ListNode* initLink() {
int i;
ListNode *p = NULL;
ListNode *temp = (ListNode*)malloc(sizeof(ListNode));
temp->val = 0;
temp->next = NULL;
p = temp;
for (i = 1; i < 5; i++){
ListNode *a = (ListNode*)malloc(sizeof(ListNode));
a->val = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
void printLink(ListNode *p) {
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
}
int getLength(ListNode *p){
ListNode* temp = p; //创建一个新的指针temp并将其初始化为p所指向的地址。
//这样,temp现在也指向链表的第一个节点。
int length=0;
while (temp) {
length++;
temp = temp->next;
}
return length;
}
void insert(ListNode **head_ref, int data, int position) {
ListNode *new_node = (ListNode*)malloc(sizeof(ListNode));
new_node->val = data;
new_node->next = NULL;
ListNode *current = *head_ref;
ListNode *prev = NULL;
int count = 0;
if (position == 1) {
new_node->next = current;
*head_ref = new_node;
return;
}
while (count < position - 1 && current != NULL) {
prev = current;
current = current->next;
count++;
}
if (current == NULL) {
printf("Cannot insert node at position %d - reaching the end of the linked list.\n", position);
free(new_node);
return;
}
prev->next = new_node;
new_node->next = current;
}
int main() {
ListNode *p = NULL; //初始化NULL,防止随机分配内存
printf("初始化链表为:\n");
p = initLink();
printLink(p);
// 注意这里需要释放链表占用的内存,否则会出现内存泄漏。你可以在主函数结束前加上释放内存的代码。比如:
// while (p != NULL) {
// ListNode *temp = p;
// p = p->next;
// free(temp);
// }
int length=getLength(p);
printf("lidt length: %d\n",length);
// 插入节点到链表头部(位置1)
insert(&p, 6, 1);
printf("After inserting node at position 1: ");
printLink(p);
// 插入节点到链表尾部(位置5)
insert(&p, 7, 5);
printf("After inserting node at position 5: ");
printLink(p);
return 0;
}
运行结果为:
2.链表的删除
- 首先,检查链表是否为空。如果为空,则打印错误消息并返回。
- 如果要删除的节点是头节点(即位置为1),那么释放头节点的内存,并将头指针指向下一个节点。
- 如果要删除的节点不是头节点,那么就需要遍历链表以找到要删除的节点。我们使用一个循环来遍历链表,直到我们到达所需的位置或到达链表的末尾。在这个过程中,我们跟踪当前节点(
current
)和前一个节点(prev
)。 - 如果在遍历过程中到达了所需的位置,但我们未能找到相应的节点,则打印错误消息并返回。
- 如果找到了要删除的节点,那么我们需要更新前一个节点的
next
指针,使其指向当前节点的下一个节点。然后释放当前节点的内存。
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
ListNode* initLink() {
int i;
ListNode *p = NULL;
ListNode *temp = (ListNode*)malloc(sizeof(ListNode));
temp->val = 0;
temp->next = NULL;
p = temp;
for (i = 1; i < 5; i++){
ListNode *a = (ListNode*)malloc(sizeof(ListNode));
a->val = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
void printLink(ListNode *p) {
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
}
int getLength(ListNode *p){
ListNode* temp = p; //创建一个新的指针temp并将其初始化为p所指向的地址。
//这样,temp现在也指向链表的第一个节点。
int length=0;
while (temp) {
length++;
temp = temp->next;
}
return length;
}
void insert(ListNode **head_ref, int data, int position) {
ListNode *new_node = (ListNode*)malloc(sizeof(ListNode));
new_node->val = data;
new_node->next = NULL;
ListNode *current = *head_ref;
ListNode *prev = NULL;
int count = 0;
if (position == 1) {
new_node->next = current;
*head_ref = new_node;
return;
}
while (count < position - 1 && current != NULL) {
prev = current;
current = current->next;
count++;
}
if (current == NULL) {
printf("Cannot insert node at position %d - reaching the end of the linked list.\n", position);
free(new_node);
return;
}
prev->next = new_node;
new_node->next = current;
}
void deleteNode(ListNode **head_ref, int position) {
ListNode *current = *head_ref;
ListNode *prev = NULL;
int count = 0;
if (current == NULL) {
printf("The linked list is empty, cannot delete node.\n");
return;
}
if (position == 1) {
ListNode *temp = current;
*head_ref = current->next;
free(temp);
return;
}
while (count < position - 1 && current != NULL) {
prev = current;
current = current->next;
count++;
}
if (current == NULL) {
printf("Cannot delete node at position %d - reaching the end of the linked list.\n", position);
return;
}
prev->next = current->next;
free(current);
}
int main() {
ListNode *p = NULL; //初始化NULL,防止随机分配内存
printf("初始化链表为:\n");
p = initLink();
printLink(p);
// 注意这里需要释放链表占用的内存,否则会出现内存泄漏。你可以在主函数结束前加上释放内存的代码。比如:
// while (p != NULL) {
// ListNode *temp = p;
// p = p->next;
// free(temp);
// }
int length=getLength(p);
printf("lidt length: %d\n",length);
// 插入节点到链表头部(位置1)
insert(&p, 6, 1);
printf("After inserting node at position 1: ");
printLink(p);
// 插入节点到链表尾部(位置5)
insert(&p, 7, 5);
printf("After inserting node at position 5: ");
printLink(p);
// 删除第3个节点
deleteNode(&p, 3);
printf("After deleting node at position 3: ");
printLink(p);
return 0;
}
运行结果为: