什么是单链表?
单链表(Linked List):由各个内存结构通过一个next指针链接在一起组成,每一个内存结构都存在后继内存结构(链尾除外),内存结构由数据域和next指针域组成。 Data 数据 + Next 指针,组成一个单链表的内存结构;第一个内存结构称为 链头,最后一个内存结构称为 链尾;链尾的 Next 指针设置为 NULL (指向空);单链表的方向单一(只能从链头一直遍历到链尾)
单链表的基本操作
单链表的结构体定义
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct ListNode* next;
}ListNode;
创建节点
ListNode* BuyListNode(DataType x) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
assert(node);
node->data = x;
node->next = NULL;
return node;
}
打印链表
void ListPrint(ListNode* head) {
ListNode* cur = head;
while (cur) {
printf("%d--->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
为什么要使用二级指针?
单链表尾插 ATTENTION:此处函数的参数传了一个二级指针 如图,如果我们不修改head指针的指向时,使用一级指针,可如果我们想修改head的指向时就要使用二级指针,与普通变量类似,若要修改普通变量的值,则需要传入变量的地址,若只是使用变量则传值即可。同理,若要修改head的指向,则需要传入二级指针,若使用一级指针,则只能修改所对应的内存块中的值,却无法修改指针本身的值即指针指向的是哪个内存块。 函数中传递指针,在函数中改变指针的值,就是在改变实参中的数据信息。但是这里改变指针的值实际是指改变指针指向地址的值,因为传递指针就是把指针指向变量的地址传递过来,而不是像值传递一样只是传进来一个实参的拷贝。所以当我们改变指针的值时,实参也改变了。
void ListPushBack(ListNode** head, DataType x) {
assert(head);
if (*head == NULL) {
*head = BuyListNode(x);
}
else {
ListNode* cur = *head;
while (cur->next) {
cur = cur->next;
}
cur->next= BuyListNode(x);
}
}
单链表尾删
void ListPopBack(ListNode** head) {
assert(head);
if (*head == NULL) {
return;
}
else {
if ((*head)->next==NULL ) {
*head= NULL;
free(*head);
}
else {
ListNode* cur = *head;
ListNode* prev = NULL;
while (cur->next) {
prev = cur;
cur = cur->next;
}
prev->next = NULL;
free(cur);
}
}
}
** 单链表头插**
void ListPushFront(ListNode** head, DataType x) {
assert(head);
if (NULL == *head) {
*head = BuyListNode(x);
}
else {
ListNode* cur = BuyListNode(x);
cur->next = *head;
*head = cur;
}
}
单链表头删
void ListPopFront(ListNode** head) {
assert(head);
if (*head == NULL) {
return;
}
else {
ListNode* cur = *head;
*head = (*head)->next;
free(cur);
}
}
单链表查找
ListNode* ListFind(ListNode* head, DataType x) {
assert(head);
if (head == NULL) {
return NULL;
}
else {
ListNode* cur = head;
while (cur) {
if (cur->data == x) {
return cur;
}
cur = cur->next;
}
return NULL;
}
}
单链表在pos之后插入值
void ListInsertAfter(ListNode** pos, DataType x) {
assert(pos);
if (pos == NULL) {
return;
}
ListNode* node = BuyListNode(x);
node->next = (*pos)->next;
(*pos)->next = node;
}
单链表删除pos之后的值
void ListEraseAfter(ListNode** pos) {
assert(pos);
if (*pos == NULL) {
return;
}
else {
if ((*pos)->next == NULL) {
return;
}
ListNode* node = (*pos)->next;
(*pos)->next = node->next;
free(node);
}
}
单链表销毁 如果不销毁的话会造成内存泄露
void ListDestory(ListNode** head) {
assert(head);
ListNode* cur = *head;
while (cur) {
*head = cur->next;
free(cur);
cur = *head;
}
*head = NULL;
}
完整代码
#include<stdio.h>
#include<malloc.h>
#include "List.h"
#include<assert.h>
ListNode* BuyListNode(DataType x) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
assert(node);
node->data = x;
node->next = NULL;
return node;
}
void ListDestory(ListNode** head) {
assert(head);
ListNode* cur = *head;
while (cur) {
*head = cur->next;
free(cur);
cur = *head;
}
*head = NULL;
}
void ListPrint(ListNode* head) {
ListNode* cur = head;
while (cur) {
printf("%d--->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
void ListPushBack(ListNode** head, DataType x) {
assert(head);
if (*head == NULL) {
*head = BuyListNode(x);
}
else {
ListNode* cur = *head;
while (cur->next) {
cur = cur->next;
}
cur->next= BuyListNode(x);
}
}
void ListPopBack(ListNode** head) {
assert(head);
if (*head == NULL) {
return;
}
else {
if ((*head)->next==NULL ) {
(*head)->next = NULL;
free(*head);
}
else {
ListNode* cur = *head;
ListNode* prev = NULL;
while (cur->next) {
prev = cur;
cur = cur->next;
}
prev->next = NULL;
free(cur);
}
}
}
void ListPushFront(ListNode** head, DataType x) {
assert(head);
if (NULL == *head) {
*head = BuyListNode(x);
}
else {
ListNode* cur = BuyListNode(x);
cur->next = *head;
*head = cur;
}
}
void ListPopFront(ListNode** head) {
assert(head);
if (*head == NULL) {
return;
}
else {
ListNode* cur = *head;
*head = (*head)->next;
free(cur);
}
}
ListNode* ListFind(ListNode* head, DataType x) {
assert(head);
if (head == NULL) {
return NULL;
}
else {
ListNode* cur = head;
while (cur) {
if (cur->data == x) {
return cur;
}
cur = cur->next;
}
return NULL;
}
}
void ListInsertAfter(ListNode** pos, DataType x) {
assert(pos);
if (pos == NULL) {
return;
}
ListNode* node = BuyListNode(x);
node->next = (*pos)->next;
(*pos)->next = node;
}
void ListEraseAfter(ListNode** pos) {
assert(pos);
if (*pos == NULL) {
return;
}
else {
if ((*pos)->next == NULL) {
return;
}
ListNode* node = (*pos)->next;
(*pos)->next = node->next;
free(node);
}
}
void test() {
ListNode* head = NULL;
ListPushBack(&head, 1);
ListPushBack(&head, 2);
ListPushBack(&head, 3);
ListPushBack(&head, 4);
ListPushBack(&head, 5);
ListPushBack(&head, 6);
ListPrint(head);
ListPopBack(&head);
ListPrint(head);
ListPushFront(&head, 0);
ListPrint(head);
ListPopFront(&head);
ListPrint(head);
ListPrint(ListFind(head, 5));
ListNode* pos = ListFind(head, 5);
ListInsertAfter(&pos, 6);
ListPrint(head);
ListEraseAfter(&pos);
ListPrint(head);
ListDestory(&head);
ListPrint(head);
}
#include "List.h"
int main() {
test();
return 0;
}
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct ListNode* next;
}ListNode;
ListNode* BuyListNode();
void ListDestory(ListNode** pHead);
void ListPrint(ListNode* pHead);
void ListPushBack(ListNode** pHead, DataType x);
void ListPopBack(ListNode** pHead);
void ListPushFront(ListNode** pHead, DataType x);
void ListPopFront(ListNode** pHead);
ListNode* ListFind(ListNode* pHead, DataType x);
void ListInsertAfter(ListNode** pos, DataType x);
void ListEraseAfter(ListNode** pos);
void test();
测试结果
void test() {
ListNode* head = NULL;
ListPushBack(&head, 1);
ListPushBack(&head, 2);
ListPushBack(&head, 3);
ListPushBack(&head, 4);
ListPushBack(&head, 5);
ListPushBack(&head, 6);
ListPrint(head);
ListPopBack(&head);
ListPrint(head);
ListPushFront(&head, 0);
ListPrint(head);
ListPopFront(&head);
ListPrint(head);
ListPrint(ListFind(head, 5));
ListNode* pos = ListFind(head, 5);
ListInsertAfter(&pos, 6);
ListPrint(head);
ListEraseAfter(&pos);
ListPrint(head);
ListDestory(&head);
ListPrint(head);
}
|