【数据结构】单链表

单链表

一、单链表的设计

1.单链表的结构定义:

typedef struct Node{
int data;//数据域
struct Node* next;//后继指针
}Node,*List;

2.单链表的结构示意图:

单链表结构示意图

3.单链表的最后一个节点的next域为NULL;

4.为什么要有一个头节点?

  • 简单方便,不用传二级指针

二、单链表的实现

  • list.cpp
    • 头插,尾插与按值删除
//头插
bool  Insert_head(List  plist, int val){
   assert(plist != NULL);
   Node*p = (Node*)malloc(sizeof(Node));
   assert(p != NULL);
   p->data = val;
   p->next = plist->next;
   plist->next = p;
   return true;
}
//尾插
bool  Insert_tail(List plist, int val){
   assert(plist != NULL);
   Node*p = (Node*)malloc(sizeof(Node));
   assert(p != NULL);
   p->next = val;
   Node*q = plist;
   for(; q->next != NULL; q = q->next){
   		;
   }
   p->next = q->next;
   q->next = p;
   return true;
}
//判空
bool   IsEmpyt(List plist){
   assert(plist != NULL);
   return plist->next == NULL;
}
//删除第一个val的值
bool  DelVal(List plist, int val){
   assert(plist != NULL);
   if(IsEmpyt(plist) == NULL){
   	return false;
   }
   Node*p = GetPrio(plist, val);
   Node*q = p->next;
   p->next = q->next;
   free(q);
   
}

//返回key的前驱地址,如果不存在返回NULL
Node* GetPrio(List  plist, int key){
   assert(plist != NULL);
   Node*p = plist;
   for(; p->next != NULL; p = p->next){
   if(p->next->data == val){
   	return p;
   }
   return NULL;
}
   
    • 整合:
#include "list.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
// 初始化链表,确保链表头指针不为空
void InitList(List plist) {
   assert(plist != NULL);
   plist->next = NULL; // 将头节点的指针置为空
}
// 头插法插入节点
bool Insert_head(List plist, int val) {
   Node* p = (Node*)malloc(sizeof(Node));
   assert(p != NULL);
   if (plist == NULL)
       return false;
   p->data = val;
   p->next = plist->next; // 先连接后面的
   plist->next = p; // 头节点指向新节点
   return true;
}
// 尾插法插入节点
bool Insert_tail(List plist, int val) {
   Node* p = (Node*)malloc(sizeof(Node));
   assert(p != NULL);
   if (plist == NULL)
       return false;
   p->data = val;
   p->next = NULL;
   Node* tail = plist;
   while (tail->next != NULL) {
       tail = tail->next; // 移动到链表末尾
   }
   tail->next = p; // 将新节点连接到末尾
   return true;
}
// 在链表的指定位置(pos)(0,1...)插入节点(val)
bool Insert(List plist, int pos, int val) {
   // 检查链表是否为空
   if (plist == NULL)
       return false;
   if (pos < 0 || pos > GetLength(plist)) {
       return false;
   }
   Node* p = (Node*)malloc(sizeof(Node));
   assert(p != NULL);
   p->data = val;
   Node* current = plist;
   int count = 0;
   // 找到要插入位置的前一个节点
   while (current != NULL && count < pos) {
       current = current->next;
       count++;
   }
   if (current == NULL) {
       free(p); // 未找到位置,释放新节点
       return false;
   }
   // 插入新节点
   p->next = current->next;
   current->next = p;
   return true;
}
// 判断链表是否为空
bool IsEmpty(List plist) {
   return plist->next == NULL; // 如果头节点的下一个节点为空,链表为空
}
// 获取链表节点的个数
int GetLength(List plist) {
   int count = 0;
   Node* current = plist->next;
   while (current != NULL) {
       count++;
       current = current->next;
   }
   return count;
}
// 在链表中查找第一个包含指定值的节点
Node* Search(List plist, int key) {
   Node* current = plist->next;
   while (current != NULL) {
       if (current->data == key)
           return current; // 找到节点后返回节点指针
       current = current->next;
   }
   return NULL; // 未找到时返回NULL
}

// 删除链表指定位置(pos)(1,2,3...)的节点
bool DelPos(List plist, int pos) {
   if (IsEmpty(plist))
       return false;
   Node* current = plist;
   int count = 0;
   // 找到要删除位置的前一个节点
   while (current->next != NULL && count < pos - 1) {
       current = current->next;
       count++;
   }
   if (current->next == NULL) {
       return false; // 未找到位置
   }
   Node* temp = current->next;
   current->next = temp->next;
   free(temp);
   return true;
}
// 删除第一个包含指定值(val)的节点
bool DelVal(List plist, int val) {
   if (IsEmpty(plist))
       return false;
   Node* current = plist;
   while (current->next != NULL) {
       if (current->next->data == val) {
           Node* temp = current->next;
           current->next = temp->next;
           free(temp);
           return true;
       }
       current = current->next;
   }
   return false;
}
// 返回指定值的前驱节点地址
Node* GetPrio(List plist, int key) {
   Node* current = plist;
   while (current->next != NULL && current->next->data != key) {
       current = current->next;
   }
   if (current->next == NULL || current == plist) {
       return NULL; // 未找到前驱节点
   }
   return current;
}
// 返回指定值的后继节点地址
Node* GetNext(List plist, int key) {
   Node* current = Search(plist, key);
   if (current != NULL && current->next != NULL) {
       return current->next;
   }
   return NULL; // 未找到后继节点
}
//返回key的后继地址,如果不存在返回NULL;
Node* GetNext(List plist, int key)
{
   assert(plist != NULL);
   if (plist == NULL)
       return NULL;
   Node* p = Search(plist, key);
   if (p == NULL)
       return NULL;
   return p->next;
}
// 输出链表的所有节点数据
void Show(List plist) {
   Node* current = plist->next;
   while (current != NULL) {
       printf("%d ", current->data);
       current = current->next;
   }
   printf("\n");
}
// 销毁整个链表
void Destroy(List plist) {
   Node* current = plist;
   while (current->next != NULL) { // 遍历 ?????????????
       Node* temp = current;
       current = current->next;
       free(temp);
   }
   // 不需要将plist设置为NULL
}

三、总结

1.特点

头插,头删 时间复杂度是O(1)
尾插,尾删 时间复杂度是O(n)

2.考点

头插,尾插,按值删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值