链表的基本操作
一:链表的概念
链表是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表上的指针链接次序实现的。链表由一系列结点(链表中的每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
二:链表的种类
实际中链表多种多样,以下情况组合起来就有八种:
1:单链表,双向链表
2:带头,不带头
3:循环,不循环
三:不带头单链表的基本操作
test.h
typedef int DataType;
typedef struct ListNode {
DataType data;
struct ListNode* next;
}Node;
void ListInit(Node* head);//初始化
void ListDestroy(Node* head);//销毁
Node* ListPushFront(Node* head, DataType val);//头插
Node* ListPushBack(Node* head, DataType val);//尾插
Node* Listinsert(Node* head, int index,DataType val);//下标插
Node* ListPopFront(Node* head);//头删
Node* ListPopBack(Node* head);//尾删
Node* ListErase(Node* head,int index);//下标删
Node* ListRemove(Node* head, DataType val);//按值删
void ListClear(Node* head);//清空
void ListIsEmpty(Node* head);//判空
void Listprint(Node* head);//打印
test.c
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"test.h"
void ListInit(Node* head) {
head = NULL;
}
void ListDestroy(Node* head) {
if (head == NULL) {
return;
}
while (head) {
Node*next = head->next;
free(head);
head = next;
}
}
Node* ListPushFront(Node* head, DataType val) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = val;
node->next = head;
head = node;
return node;
}
Node* ListPushBack(Node* head, DataType val) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = val;
Node* cur = head;
while (cur->next) {
cur = cur->next;
}
cur->next = node;
node->next = NULL;
return head;
}
Node* Listinsert(Node* head,int index, DataType val) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = val;
Node* cur = head;
for (int i = 0;i < index-1;i++) {
cur = cur->next;
}
node->next = cur->next;
cur->next = node;
return head;
}
Node* ListPopFront(Node* head) {
assert(head != NULL);
Node* next = head->next;
free(head);
head = next;
return head;
}
Node* ListPopBack(Node* head) {
Node* cur = head;
while (cur->next->next) {
cur = cur->next;
}
cur->next = NULL;
return head;
}
Node* ListErase(Node* head,int index) {
if (index == 0) {
return ListPopFront(head);
}
Node* cur = head;
for (int i = 0;i < index - 1;i++) {
cur = cur->next;
}
Node* next = cur->next;
cur->next = next->next;
free(next);
return head;
}
Node* ListRemove(Node* head, DataType val) {
if (head == NULL) {
return NULL;
}
Node* node = (Node*)malloc(sizeof(Node));
Node* rhead = NULL;
Node* cur = head;
while (cur) {
if (cur->data == val) {
if (rhead == NULL) {
head = cur->next;
free(cur);
cur = head;
}
else {
rhead->next = cur->next;
free(cur);
cur = rhead->next;
}
}
else {
rhead = cur;
cur = cur->next;
}
}
return head;
}
void ListClear(Node* head) {
if (head == NULL) {
return;
}
while (head) {
Node* next = head->next;
free(head);
head = next;
}
head = NULL;
}
void ListIsEmpty(Node* head) {
if (head == NULL) {
printf("链表为空");
}
else {
printf("链表不为空");
}
}
void Listprint(Node* head) {
for (Node* cur = head;cur != NULL;cur = cur->next) {
printf("%d-->", cur->data);
}
printf("NULL\n");
}
四:不带头双向链表的基本操作
test.h
typedef int DataType;
typedef struct DListNode {
DataType val;
struct DListNode* next;
struct DListNode* pre;
}DNode;
void DListNodeInit(DNode** head);//初始化
void DListNodePushBack(DNode* head, DataType val);//尾插
void DListNodePushFront(DNode* head, DataType val);//头插
void DListNodePopFront(DNode* head);//头删
void DListNodePopBack(DNode* head);//尾删
void DListNodeinsert(DNode* head, int pos, DataType val);//任意位置插入
void DListNodeErase(DNode* head, int pos);//任意位置删除
void DListNodeClear(DNode* head);//清除
void DListNodeDestroy(DNode* head);//销毁
void DListNodeprint(DNode* head);//遍历
test.c
void DListNodeInit(DNode** head) {
assert(head);
DNode* node = (DNode*)malloc(sizeof(DNode));
node->next = node;
node->pre = node;
*head = node;
}
void DListNodePushBack(DNode* head, DataType val) {
DNode* node = (DNode*)malloc(sizeof(DNode));
node->val = val;
node->pre = head->pre;
node->next = head;
head->pre->next = node;
head->pre = node;
}
void DListNodePushFront(DNode* head, DataType val) {
DNode* node = (DNode*)malloc(sizeof(DNode));
node->val = val;
node->next = head->next;
node->pre = head;
head->next->pre = node;
head->next = node;
}
void DListNodePopFront(DNode* head) {
DNode* temp = head->next;
head->next = temp->next;
temp->next->pre = head;
free(temp);
}
void DListNodePopBack(DNode* head) {
DNode* temp = head->pre;
temp->pre->next = head;
head->pre = temp->pre;
free(temp);
}
void DListNodeinsert(DNode* head, int pos, DataType val) {
DNode* node = (DNode*)malloc(sizeof(DNode));
node->val = val;
DNode* cur = head->next;
for (int i = 0;i < pos-1;i++) {
cur = cur->next;
}
node->next = cur->next;
node->pre = cur;
cur->next = node;
}
void DListNodeErase(DNode* head, int pos) {
DNode* cur = head->next;
for (int i = 0;i < pos-1;i++) {
cur = cur->next;
}
DNode* temp = cur;
temp->pre->next = temp->next;
temp->next->pre = temp->pre;
free(temp);
}
void DListNodeClear(DNode* head) {
DNode* cur = head->next;
while (cur != head) {
free(cur);
cur = cur->next;
}
}
void DListNodeDestroy(DNode* head) {
DListNodeClear(head);
free(head);
}
void DListNodeprint(DNode* head) {
DNode* cur = head->next;
for (cur;cur != head;cur = cur->next) {
printf("%d--> ", cur->val);
}
}