单链表的存储结构及其基本操作的实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单链表是一种常见的数据结构,用于存储线性表的数据。
它由一系列节点组成,每个节点包含数据部分和一个指向下一个节点的指针。
单链表的存储结构和基本操作是数据结构与算法中重要的基础知识,下面将对单链表的存储结构及其基本操作进行详细介绍。
一、单链表的存储结构
1. 节点的定义
单链表的节点可以使用结构体来表示,结构体中包含数据域和指针域两部分,数据域用来存储具体的数据,指针域用来指向下一个节点。
节点的定义如下:
```c
typedef struct Node {
int data;
struct Node *next;
} Node;
```
上面的代码定义了一个节点的结构体,其中data表示节点的数据,next表示指向下一个节点的指针。
2. 单链表的定义
单链表本身可以使用一个指向头节点的指针来表示,头节点不包含数据,只包含一个指向第一个真正包含数据的节点的指针。
单链表的定
义如下:
```c
typedef struct LinkedList {
Node *head;
} LinkedList;
```
上面的代码定义了一个单链表的结构体,其中head指向第一个节点。
二、单链表的基本操作
1. 初始化
单链表的初始化操作用来创建一个空链表,即一个只包含头节点的链表。
初始化操作的实现如下:
```c
LinkedList *initLinkedList() {
LinkedList *list = (LinkedList*)malloc(sizeof(LinkedList));
list->head = NULL;
return list;
}
```
上面的代码中,我们先分配了一个LinkedList结构体的空间,然后将其head指针置为NULL,最后返回这个初始化好的链表。
2. 插入节点
向单链表中插入节点可以分为头部插入、尾部插入和指定位置插入三种情况。
下面分别介绍这三种情况的实现方法。
(1)头部插入
头部插入即在链表的头部插入一个新的节点,实现方法如下:
```c
void insertAtHead(LinkedList *list, int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = list->head;
list->head = newNode;
}
```
上面的代码中,我们首先分配了一个新的节点,并将其数据域赋值为传入的数据,然后将新节点的next指针指向原来的头节点,最后将链表的head指针指向新节点。
(2)尾部插入
尾部插入即在链表的尾部插入一个新的节点,实现方法如下:
```c
void insertAtT本人l(LinkedList *list, int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
if(list->head == NULL) {
list->head = newNode;
} else {
Node *temp = list->head;
while(temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
```
上面的代码中,我们首先分配了一个新的节点,并将其数据域赋值为
传入的数据,然后将新节点的next指针置为NULL。
如果链表为空,直接将head指向新节点;如果链表不为空,找到链表最后一个节点,将其next指针指向新节点。
(3)指定位置插入
指定位置插入即在链表的指定位置插入一个新的节点,实现方法如下:
```c
void insertAtIndex(LinkedList *list, int data, int index) {
if(index < 0) {
printf("Invalid index\n");
return;
}
if(index == 0) {
insertAtHead(list, data);
return;
}
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
Node *temp = list->head;
for(int i = 0; i < index - 1; i++) {
if(temp->next != NULL) {
temp = temp->next;
} else {
printf("Invalid index\n");
return;
}
}
newNode->next = temp->next;
temp->next = newNode;
}
```
上面的代码中,我们首先判断插入位置是否合法,如果不合法则直接返回;如果插入位置为0,则调用insertAtHead函数;否则遍历链表找到需要插入的位置,然后进行插入操作。
3. 删除节点
从单链表中删除节点可以分为头部删除、尾部删除和指定位置删除三
种情况。
下面分别介绍这三种情况的实现方法。
(1)头部删除
头部删除即删除链表的第一个节点,实现方法如下:
```c
void deleteAtHead(LinkedList *list) {
if(list->head != NULL) {
Node *temp = list->head;
list->head = list->head->next;
free(temp);
}
}
```
上面的代码中,我们先判断链表是否为空,如果不为空则删除头节点,并释放其内存。
(2)尾部删除
尾部删除即删除链表的最后一个节点,实现方法如下:
```c
void deleteAtT本人l(LinkedList *list) {
if(list->head == NULL) {
return;
}
if(list->head->next == NULL) {
free(list->head);
list->head = NULL;
return;
}
Node *temp = list->head;
while(temp->next->next != NULL) {
temp = temp->next;
}
free(temp->next);
temp->next = NULL;
}
```
上面的代码中,我们先判断链表是否为空,如果为空则直接返回;如果链表只有一个节点,则直接删除该节点;否则遍历链表找到倒数第
二个节点,然后删除最后一个节点。
(3)指定位置删除
指定位置删除即删除链表的指定位置上的节点,实现方法如下:
```c
void deleteAtIndex(LinkedList *list, int index) {
if(index < 0 || list->head == NULL) {
return;
}
if(index == 0) {
deleteAtHead(list);
return;
}
Node *temp = list->head;
for(int i = 0; i < index - 1; i++) {
if(temp->next != NULL) {
temp = temp->next;
} else {
return;
}
}
if(temp->next == NULL) {
return;
}
Node *toBeDeleted = temp->next;
temp->next = temp->next->next;
free(toBeDeleted);
}
```
上面的代码中,我们首先判断删除位置是否合法,如果不合法则直接返回;如果删除位置为0,则调用deleteAtHead函数;否则遍历链表找到需要删除的位置,然后进行删除操作。
4. 打印链表
打印链表即按顺序打印出链表中各个节点的数据,实现方法如下:
```c
void printLinkedList(LinkedList *list) {
Node *temp = list->head;
while(temp != NULL) {
printf("d ", temp->data);
temp = temp->next;
}
printf("\n");
}
```
上面的代码中,我们使用一个临时指针遍历整个链表,依次打印各个节点的数据。
5. 搜索节点
搜索节点即在链表中查找是否包含指定数据的节点,实现方法如下:
```c
int search(LinkedList *list, int data) {
int index = 0;
Node *temp = list->head;
while(temp != NULL) {
if(temp->data == data) {
return index;
}
temp = temp->next;
index++;
}
return -1;
}
```
上面的代码中,我们使用一个临时指针遍历整个链表,依次查找是否包含指定数据的节点,如果找到则返回其位置,否则返回-1。
单链表的存储结构及其基本操作包括初始化、插入节点、删除节点、打印链表和搜索节点等操作,这些操作是单链表的基本操作,深入理解单链表的存储结构及其基本操作对于数据结构与算法的学习具有重要意义。
希望本文所述内容能够帮助读者更好地理解单链表的存储结构及其基本操作,并进一步深入学习数据结构与算法的相关知识。