一,什么是单链表
单链表是由结构体变量与结构体变量连接在一起的数据结构。
链表中的结构体是由数据域和指针域组成的, 而前一个结构体的指针域是指向下一个结构体的,从而将多个结构体连接起来,组成单链表。
struct Node
{
int data;//结构域(存放数据)
struct Node*next;//指针域(指向下一个结构体)
};
二,动态创建一个链表
动态创建一个链表是由动态内存申请和模块化设计(链表的功能,包含的数据)完成。
总的来说,创建一个链表是由一下五个步骤组成
1.创建链表(创建一个表头表示整个链表)
2.创建结点
3.插入结点
4.删除结点
5.打印遍历链表(测试)
1.创建链表
首先,我们应该创建一个表头来表示整个链表,代码如下
struct Node* createList()
{
struct Node* headNode = (struct Node*)malloc(sizeof(Node));//使用malloc函数动态分配空间
//headNode->data = 1;由于我们创建的是表头,二表头不存储数据,所以这里不需要数据域
//headNode成为了一个结构体变量
headNode->next = NULL;
return headNode;
}
2.创建结点
这里创建结点和创建链表相似,只不过这里需要一个数据域,代码如下
struct Node* createNode(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
3.插入结点
插入节点总共有三种,分别为头插法,尾插法和指定位置插入。这里我们只讲头插法。
头插法,就是将一个新的结点插入表头的后面,使表头的指针域指向新的结点,而新的结点的指针域指向原本头结点指向的结点,代码如下
void insertNodeByHead(struct Node* headNode, int data)
{
//首先,创建插入结点
struct Node* newNode = createNode(data);
newNode->next = headNode->next;//新的结点指向原来表头指向的结点
headNode->next = newNode;//表头指向新结点
}
4.删除结点
删除结点,就是将指定的结点从链表中删除,而删除结点中用处最广泛的就是指定位置删除,而指定位置删除,本质上是从表头开始向后找,当遇到满足删除条件的结点,就将其从链表中删除,然后停止,所以,这种方法只能将离表头最近的满足条件的结点删除。所以说,如果链表有多个相同的结点,则要进行多次指定位置删除才可将所有满足条件的结点删除,也就是说每次删除最多只能删掉一个结点,代码如下
void deleteNodeByhead(struct Node* headNode, int posData)
{
struct Node* posNode = headNode->next;//找出指定位置的结点
struct Node* posNodeFront = headNode;//找出指定位置的前一个结点
if (posNode == NULL)
{
printf("链表为空\n");
}
else
{
while (posNode->data != posData)//如果不符合要求,则向后寻找
{
posNodeFront = posNode;
posNode = posNodeFront->next;
if (posNode == NULL)
{
printf("没有找到相关信息,无法删除\n");
break;
}
}
posNodeFront->next = posNode->next;
free(posNode);//删除该节点
}
}
5.打印遍历链表(测试)
打印链表是从第二个结点开始打印,不包括表头,代码如下
void printList(struct Node* headNode)//打印以headNode为表头的链表
{
struct Node* pMove = headNode->next;//定义一个移动的指针pMove,从第二个结点开始打印
while (pMove)
{
printf("%d\n", pMove->data);//打印pMove中的数据
pMove = pMove->next;//pMove向后走
}
printf("\n");
}
6.以下,我在主函数中尝试了插入和删除的相关操作,代码如下
int main()
{
struct Node* list = createList();
insertNodeByHead(list, 1);
insertNodeByHead(list, 2);
insertNodeByHead(list, 3);
insertNodeByHead(list, 4);
insertNodeByHead(list, 1);
printList(list);
deleteNodeByhead(list, 1);
printList(list);
system("pause");
return 0;
}
下面是结果
下面就是全部代码
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;//结构域
struct Node*next;//指针域
};
struct Node* createList()
{
struct Node* headNode = (struct Node*)malloc(sizeof(Node));//使用malloc函数动态分配空间
//headNode->data = 1;由于我们创建的是表头,二表头不存储数据,所以这里不需要数据域
//headNode成为了一个结构体变量
headNode->next = NULL;
return headNode;
}
struct Node* createNode(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void printList(struct Node* headNode)//打印以headNode为表头的链表
{
struct Node* pMove = headNode->next;//定义一个移动的指针pMove,从第二个结点开始打印
while (pMove)
{
printf("%d\n", pMove->data);//打印pMove中的数据
pMove = pMove->next;//pMove向后走
}
printf("\n");
}
void insertNodeByHead(struct Node* headNode, int data)
{
//首先,创建插入结点
struct Node* newNode = createNode(data);
newNode->next = headNode->next;//新的结点指向原来表头指向的结点
headNode->next = newNode;//表头指向新结点
}
void deleteNodeByhead(struct Node* headNode, int posData)
{
struct Node* posNode = headNode->next;//找出指定位置的结点
struct Node* posNodeFront = headNode;//找出指定位置的前一个结点
if (posNode == NULL)
{
printf("链表为空\n");
}
else
{
while (posNode->data != posData)//如果不符合要求,则向后寻找
{
posNodeFront = posNode;
posNode = posNodeFront->next;
if (posNode == NULL)
{
printf("没有找到相关信息,无法删除\n");
break;
}
}
posNodeFront->next = posNode->next;
free(posNode);//删除该节点
}
}
int main()
{
struct Node* list = createList();
insertNodeByHead(list, 1);
insertNodeByHead(list, 2);
insertNodeByHead(list, 3);
insertNodeByHead(list, 4);
insertNodeByHead(list, 1);
printList(list);
deleteNodeByhead(list, 1);
printList(list);
system("pause");
return 0;
}