--链表
-链表的概念
线性表的链式存储结构,我们叫做链表,将线性表L=(a0,a1,...an-1)中各元素分布在储存器中的不同存储区域,线性表中的各元素称为结点,通过地址或指针建立节点之间的联系所得到的存储结构叫做链表结构
-数据域和指针域
数据域:节点的data域存放数据元素a0
指针域:指针域是一个指针,指向a0的直接后继节点
-头节点、尾节点和虚拟头节点
头节点:链表中的第一个节点叫做头节点
尾节点:链表中的最后一个节点叫尾节点(尾节点的指针域为NULL)
虚拟头节点:为了方便对链表进行操作,一般会在链表的头节点前面,再创建一个节点,称为虚拟头节点(dummyhead),让该节点的指针域指向真正的头节点,(虚拟头节点的数据域默认不使用,只是用指针域)
封装节点的代码实现:
-单向链表的代码实现
linked_list.c
#include "linkedlist.h"
void linkedlist_init(node_t** p_head){
node_t* p_node = (node_t*)malloc(sizeof(node_t));
if(p_node==NULL){
printf("malloc failure:%s\n",strerror(errno));
return;
}
memset(p_node,0,sizeof(node_t));
p_node->next = NULL;
*p_head = p_node;
}
// 添加的方法
bool linkedlist_insert_head(node_t* p_head,datatype_t val){
//将data添加到链表的头部
// 1、封装成节点
node_t* p_node = (node_t*)malloc(sizeof(node_t));
if(p_node==NULL){
printf("malloc failure:%s\n",strerror(errno));
return false;
}
memset(p_node,0,sizeof(node_t));
p_node->data = val;
p_node->next = NULL;
// 2、改变指针的指向
p_node->next = p_head->next;
p_head->next = p_node;
return true;
}
// 打印链表中所有的结点数据
void linkedlist_display(node_t* head){
node_t* cur = head->next;
while(cur!=NULL){
printf("%d--->",cur->data);
cur= cur->next;
}
printf("NULL\n");
}
bool linkedlist_insert_tail(node_t* p_head,datatype_t val){
// 1、封装成节点
node_t* p_node = (node_t*)malloc(sizeof(node_t));
if(p_node==NULL){
printf("malloc failure:%s\n",strerror(errno));
return false;
}
memset(p_node,0,sizeof(node_t));
p_node->data = val;
p_node->next = NULL;
// 找尾巴
node_t* tail=p_head;
while(tail->next!=NULL){
tail = tail->next;
}
tail->next = p_node;
return true;
}
bool linkedlist_insert_order(node_t* p_head,datatype_t val){
// 1、封装成节点
node_t* p_node = (node_t*)malloc(sizeof(node_t));
if(p_node==NULL){
printf("malloc failure:%s\n",strerror(errno));
return false;
}
memset(p_node,0,sizeof(node_t));
p_node->data = val;
p_node->next = NULL;
// 找添加结点的前驱结点
node_t* pre=p_head;
while(pre->next!=NULL && pre->next->data < val){
pre=pre->next;
}
p_node->next = pre->next;
pre->next = p_node;
return true;
}
// 删除节点根据值
bool linkedlist_remove_data(node_t* head,datatype_t data){
node_t* pre = head;
while(pre->next!=NULL && pre->next->data !=data){
pre=pre->next;
}
if(pre->next ==NULL){
printf("没有找到要删除的节点\n");
return false;
}else{
// 保存删除节点
node_t* delnode = pre->next;
pre->next = pre->next->next;
free(delnode);
delnode=NULL;
return true;
}
}
void linkdelist_clean(node_t** head){
if(*head == NULL){
return;
}
node_t* pre = *head;
while(pre->next!=NULL){
node_t* delnode = pre->next;
pre->next = pre->next->next;
free(delnode);
delnode=NULL;
}
free(*head);
*head= NULL;
}
linked_list.h
#ifndef __HEAD_LINKED_LIST_H__
#define __HEAD_LINKED_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
typedef int datatype_t;
// 定义结构体类型
typedef struct Node{
// 数据域
datatype_t data;
// 指针域
struct Node* next;
}node_t;
extern bool linkedlist_insert_head(node_t* p_head,datatype_t val);
extern void linkedlist_display(node_t* head);
extern bool linkedlist_insert_tail(node_t* p_head,datatype_t val);
extern bool linkedlist_insert_order(node_t* p_head,datatype_t val);
extern void linkedlist_init(node_t** p_head);
extern bool linkedlist_remove_data(node_t* head,datatype_t data);
extern void linkdelist_clean(node_t** head);
#endif
main.c
#include "linkedlist.h"
void menu();
void insert_head_data(node_t* p_head);
void insert_tail_data(node_t* p_head);
void insert_order_data(node_t* p_head);
void remove_data(node_t* head);
int main(){
node_t* head = NULL;
int select;
do{
menu();
printf("请选择:");
scanf("%d",&select);
// 针对不同的选择进行不同的操作
switch(select){
case 1:
linkedlist_init(&head);
break;
case 2:
if(head==NULL){
linkedlist_init(&head);
}
insert_head_data(head);
break;
case 3:
if(head==NULL){
linkedlist_init(&head);
}
insert_tail_data(head);
break;
case 4:
if(head==NULL){
linkedlist_init(&head);
}
insert_order_data(head);
break;
case 5:
if(head==NULL){
linkedlist_init(&head);
}
remove_data(head);
break;
case 8:
linkedlist_display(head);
break;
case 0:
printf("welcome to next come\n");
linkdelist_clean(&head);
exit(EXIT_SUCCESS);
break;
default:
printf("选择错误\n");
}
}while(1);
}
void menu(){
printf("-----------链表的操作-----------\n");
printf("1、初始化链表\n");
printf("2、在表头添加节点\n");
printf("3、在尾部添加节点\n");
printf("4、按顺序添加节点\n");
printf("5、删除节点\n");
printf("8、显示链表节点数据\n");
printf("0、退出\n");
printf("--------------end---------------\n");
}
void insert_head_data(node_t* p_head){
printf("请输入要添加的内容:");
datatype_t num;
scanf("%d",&num);
// 调用链表的头插法,将num插入到链表中
bool result = linkedlist_insert_head(p_head,num);
if(result){
printf("插入成功\n");
}else {
printf("插入失败\n");
}
}
void insert_tail_data(node_t* p_head){
printf("请输入要添加的内容:");
datatype_t num;
scanf("%d",&num);
// 调用链表的头插法,将num插入到链表中
bool result = linkedlist_insert_tail(p_head,num);
if(result){
printf("插入成功\n");
}else {
printf("插入失败\n");
}
}
void insert_order_data(node_t* p_head){
printf("请输入要添加的内容:");
datatype_t num;
scanf("%d",&num);
bool result = linkedlist_insert_order(p_head,num);
if(result){
printf("插入成功\n");
}else {
printf("插入失败\n");
}
}
void remove_data(node_t* head){
printf("请输入要删除的内容:");
datatype_t num;
scanf("%d",&num);
bool result = linkedlist_remove_data(head,num);
if(result){
printf("删除成功\n");
}else {
printf("删除失败\n");
}
linkedlist_display(head);
}