首页 > 编程语言 >【C++】链表相关的项目(2.0)

【C++】链表相关的项目(2.0)

时间:2024-07-16 15:59:25浏览次数:18  
标签:cur pos C++ next 链表 lp 2.0 节点

链表相关的项目1.0需要请点击            

---------------------------------------------------

准备工作

首先弄几个可能会需要的头文件:

#include<stdio.h>
#include<stdlib.h> 
#include<string.h>
typedef int ADT; //定义自定义数据类型 


​

​

因为写的是关于链表的项目需要定义一个结构体:

//定义结构体 
typedef struct N
{
	ADT data;
	struct N *next;	
}Node;



​

定义有关链表的结构体:

​
//定义链表结构体 
typedef struct
{
	Node *head, *tail;//定义头尾指针 
	unsigned size;//定义变量 
}List;

​

初始化操作:

//初始化链表函数 
List *init_list(List *lp) 
{
	lp -> head = lp -> tail = (void*)0; //头尾指针为空
    lp -> size = 0;//链表个数为0
    return lp; 
}



​

制作节点(这部分仅仅跟后面的几个操作有关):

​//制作节点 
Node *make_node(ADT d)
{
	Node *np = malloc(sizeof(Node));//申请空间 
	if(!np)//申请成功 
	    return (void*)0;
	np -> data = d;
	np -> next = (void*)0;
	return np;
}

​

​

---------------------------------------------------------------------------------------------------------------------------------

这篇重要的部分来咯~

  • 1.清空链表操作
  • 2.链表头插操作
  • 3.链表尾插操作
  • 4.链表头删操作
  • 5.链表尾删操作
  • 6.查找位置操作
  • 7.插入某元素到指定位置的函数 (插入某元素之后,否则头插)
  • 8.插入某元素到指定位置的函数 (插入某元素之前,否则尾插)方法1 
  • 9.插入某元素到指定位置的函数 (插入某元素之前,否则尾插)方法2 
  • 10.删除某元素之后的第一个元素的函数 
  • 11.删除元素本身,不存在则不删的函数 方法1 
  • 12.删除元素本身,不存在则不删的函数 方法2
  • 13.按序打印链表函数

---------------------------------------------------------------------------------------------------------------------------------

1.0中咱们写到5

2.0从6开始 

~~~~~~~~~~~~~~~~~

NO6 查找位置操作

//6 
//查找操作函数(找位置)
// 定义了一个函数find_element,它接收一个指向List结构体的指针lp和一个ADT类型的值d作为参数。  
// 函数返回一个整型值,表示元素d在链表中的位置(如果找到的话),或者返回0表示未找到。  
int find_element(List *lp, ADT d)    
{    
    // 初始化一个整型变量position为1。这个变量用于跟踪当前正在检查的节点在链表中的位置。  
    // 假设链表至少有一个元素,所以初始位置设为1。  
    int position = 1;   
      
    // 通过lp指针获取链表的头节点,并将其地址赋给Node类型的指针cur。  
    // cur将用于遍历链表。  
    Node *cur = lp->head;   
    
    // 使用while循环遍历链表。循环的条件是cur不为NULL,即当前节点不是链表的末尾。  
    while (cur)   
    {    
        // 如果当前节点的数据域data的值等于要查找的值d,  
        if (cur->data == d)   
        {    
            // 则函数直接返回当前的位置position。  
            // 这里的position是从1开始计数的,符合通常对链表元素位置的理解。  
            return position;   
        }    
    
        // 如果当前节点的数据不等于d,则将cur指针移动到下一个节点。  
        cur = cur->next;   
          
        // 同时,递增position的值,以便在下一次循环中检查下一个节点的位置。  
        position++;   
    }    
    
    // 如果循环结束(即遍历完整个链表),仍然没有找到等于d的节点,  
    // 则函数返回0,表示未找到元素。  
    return 0;   
}

---------------------------------------------------------------------------------------------------------------------------------

NO7 —— NO12(由于这六个模块都需要通过找到某个指针才能实现本身想要的功能,所以我全部归为一类)

//查找指针函数(找某个指针) 
Node *find_in_list(List *lp, ADT d) {
    Node *cur = lp->head; // 将cur指针初始化为链表的头节点,从头开始遍历
    while (cur && cur->data != d) { // 当cur不为空且cur指向的节点数据不等于d时,继续循环
        cur = cur->next; // 将cur指针移动到下一个节点
    }
    return cur; // 如果找到数据等于d的节点,返回该节点的指针;如果没有找到,cur将为NULL,返回NULL
}
//7
//插入某元素之后,否则头插
List *insert_some_element(List *lp, int d, Node *pos) {
    if (pos == (void*)0) // 如果pos是NULL,说明没有找到指定位置或者链表为空
        return push_front_list(lp, d); // 调用另一个函数在链表头部插入新元素d
    Node *new_node = make_node(d); // 根据元素d创建一个新的节点
    new_node->next = pos->next; // 将新节点的next指向pos节点的下一个节点,为插入做准备
    pos->next = new_node; // 将pos节点的next指向新节点,完成插入
    if (pos == lp->tail) // 如果pos是链表的尾部节点
        lp->tail = new_node; // 更新链表的尾部为新节点
    lp->size++; // 链表长度增加1
    return lp; // 返回链表的指针
}
//8
//插入某元素之前,否则尾插 方法1 
List *insert_element_front(List *lp, ADT d, Node *pos) {
    if (pos == (void*)0) // 如果pos是NULL,说明链表为空或者没有找到指定节点
        return push_back_list(lp, d); // 调用另一个函数在链表尾部插入新元素d
    if (pos == lp->head) // 如果pos是头节点
        return push_front_list(lp, d); // 调用另一个函数在头部插入新元素d
    Node *cur = lp->head; // 从链表的头节点开始遍历
    while (cur->next != pos) // 当cur的下一个节点不是pos时,继续遍历
        cur = cur->next; // 移动到下一个节点
    Node *new_node = make_node(d); // 创建一个新节点,数据为d
    new_node->next = pos; // 将新节点的next指向pos节点,为插入做准备
    cur->next = new_node; // 将cur节点的next指向新节点,完成插入
    lp->size++; // 链表长度增加1
    return lp; // 返回链表的指针
}
//9
//插入某元素之前,否则尾插 方法2
List *insert_element_front2(List *lp, ADT d, Node *pos) {
    if (pos == (void*)0) // 如果链表为空
        return push_back_list(lp, d); // 在尾部插入新元素d
    Node *new_node = make_node(pos->data); // 创建一个新节点,复制pos节点的数据
    new_node->next = pos->next; // 新节点的next指向pos节点的下一个节点
    pos->next = new_node; // 将pos节点的next指向新节点,完成插入
    pos->data = d; // 更新pos节点的数据为新元素d
    if (pos == lp->tail) // 如果pos是链表的尾部节点
        lp->tail = new_node; // 更新链表的尾部为新节点
    lp->size++; // 链表长度增加1
    return lp; // 返回链表的指针
}
//10
//删除某元素之后的第一个元素的函数 
Node *del_element_next(List *lp, Node *pos) {
    if (pos == (void*)0 || pos == lp->tail) // 如果pos是NULL或pos是链表的尾部节点,不能删除
        return (void*)0;
    Node *del = pos->next; // del指向pos节点的下一个节点,即要删除的节点
    pos->next = del->next; // 将pos节点的next指向del的下一个节点,从而跳过del节点
    if (del == lp->tail) // 如果del是链表的尾部节点
        lp->tail = pos; // 更新链表的尾部为pos节点
    free(del); // 释放del节点的内存
    lp->size--; // 链表长度减少1
    return lp; // 返回链表的指针
}
//11
//删除元素本身,不存在则不删的函数 方法1 
List *del_element_self(List *lp, Node *pos) {
    if (pos == (void*)0) // 如果pos是NULL,不执行删除
        return (void*)0;
    if (pos == lp->head) // 如果pos是头节点,使用特殊方法删除
        return pop_front_first(lp);
    Node *cur = lp->head; // 从链表的头节点开始遍历
    while (cur->next != pos) // 找到pos节点的前一个节点
        cur = cur->next;
    cur->next = pos->next; // 将cur节点的next指向pos的下一个节点,从而删除pos节点
    if (pos == lp->tail) // 如果pos是尾部节点
        lp->tail = cur; // 更新链表的尾部为cur节点
    free(pos); // 释放pos节点的内存
    lp->size--; // 链表长度减少1
    return lp; // 返回链表的指针
}
//12
//删除元素本身,不存在则不删的函数 方法2 
List *del_element_self2(List *lp, Node *pos) {
    if (pos == (void*)0) // 如果pos是NULL,不执行删除
        return (void*)0;
    if (pos == lp->tail) // 如果pos是尾部节点,使用特殊方法删除
        return pop_back_last(lp);
    Node *del = pos->next; // del指向pos节点的下一个节点
    pos->data = del->data; // 将del节点的数据复制到pos节点
    pos->next = del->next; // 将pos节点的next指向del的下一个节点,从而跳过del节点
    if (del == lp->tail) // 如果del是尾部节点
        lp->tail = pos; // 更新链表的尾部为pos节点
    free(del); // 释放del节点的内存
    lp->size--; // 链表长度减少1
    return lp; // 返回链表的指针
}

---------------------------------------------------------------------------------------------------------------------------------

NO13 按序打印链表函数

//13
//按序打印链表函数
// 定义print_list函数,它接受一个指向List类型的指针lp作为参数  
// List类型在代码段之外定义,我们假设它包含至少两个成员:head(指向链表首节点的指针)和size(链表中节点的数量)  
void print_list(const List *lp)   
{  
    // 打印一条分隔线,用于在输出中区分不同的链表内容  
    printf("------------------------------------------<<<<<----------------------------------------------------------\n");  
  
    // 定义一个Node类型的指针current,并将其初始化为lp->head,即链表的头节点  
    // 假设Node是链表节点的类型,包含至少两个成员:data(存储的数据,这里假设是歌曲的ID)和next(指向下一个节点的指针)  
    Node *current = lp -> head;  
  
    // 检查链表是否为空(即头节点是否为NULL)  
    if(current)  
    {  
        // 如果链表不为空,首先打印出链表中歌曲的第一个数据 
        // 注意,这里假设lp->size是正确的,即它确实反映了链表中节点的数量  
        printf("链表储存了%d个数据:%d", lp->size, current->data);  
  
        // 将current指针移动到下一个节点,以便开始打印后续的链表数据
        current = current -> next;  
  
        // 使用while循环遍历链表中的剩余节点  
        while(current)  
        {  
            // 打印当前节点的数据,并在前面加上箭头以表示顺序  
            printf("->%d", current->data);  
  
            // 将current指针移动到下一个节点,继续循环直到链表末尾  
            current = current -> next;  
        }  
  
        // 打印换行符,结束当前链表的打印  
        printf("\n");  
    }   
    else  
    {  
        // 如果链表为空,则打印一条消息说明链表列表为空  
        printf(" 链表序列为空!\n");  
    }  
  
    // 打印另一条分隔线,用于在输出中区分不同的链表内容  
    printf("------------------------------------------<<<<<----------------------------------------------------------\n");   
}

-------------------------------------------------------------------------------------------------------------------------------- 

这一篇解释代码的方法与上一篇略有不同,但我觉得这样放在源代码里面解释估计更方便理解。

个人认为想要更好的理解链表一定一定要通过画图,因为画图会更加直观,这里就不给大家展示。sorry~

这篇重点到这基本就结束了,下一篇我大概会附上我的完整代码让大家看看完整的运行结果是什么样的。

感谢各位观看!!         

ps:  想要观看第一篇的朋友  请点击                   

▬▬▬▬.◙.▬▬▬▬
       ▂▄▓▄▂
 ◢◤█████▄▄▄◢◤ 
 █小迟专用直升机█▀▀╬ 
  ◥██████◤
  ══╩══╩═══

 ~~~未完待续~~~~

标签:cur,pos,C++,next,链表,lp,2.0,节点
From: https://blog.csdn.net/2302_80244781/article/details/140441151

相关文章

  • C++11平凡可复制类型检测is_trivially_copyable
    1.C++基础回顾     在C++11中,平凡类型(TrivialType)、平凡可复制类型(TrivialCopyable)、标准布局类型(Standard-layoutType)是描述类在内存中布局特性的术语,它们与类的构造、拷贝、赋值和销毁行为有关,也影响着类的内存布局和对齐方式。下面用通俗的语言解释这些概念:1.1.平......
  • C++获取当前毫秒数
    转自https://www.cnblogs.com/c9080/p/17509268.html,在C++11中,可以使用<chrono>头文件中的std::chrono::system_clock类来获取当前时间戳。它提供了多种精度和分辨率的时钟类型,其中最常用的是系统时钟。以下是一个示例程序,演示如何使用std::chrono::system_clock类获取......
  • C++ 用智能指针这样包装 this 指针是否可行
    #include<iostream>#include<memory>usingnamespacestd;classA;classB{public:B(shared_ptr<A>a){pa=a;cout<<"B构造..."<<endl;}~B(){cout<<&quo......
  • C++游戏篇1“很好的游戏,使我手指旋转”(原创)
    话不多说,上代码!#include<bits/stdc++.h>#include<windows.h>usingnamespacestd;intGe,Fen,timp,F,a[22][6];doubleShi,B;voidS(intForgC,intBackC){WORDwColor=((BackC&0x0F)<<4)+(ForgC&0x0F);SetConsoleTextAttribute(GetS......
  • C++转换进制
    前言本蒟蒻:让C++转进制?我都不会转,更何况让C++转。正文转进制,我们要知道36进制的0-35都用什么表示。0-9就是0-9,而10-35分别是ABCDEFG........RSTUVWXYZ。我们可以设一个字符串表示0-35:strings="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";重要的一步来了,参考以下方法,用while......
  • 底软驱动 | 大厂面试爱考的C++内存相关
    文章目录C++内存相关C++内存分区C++对象的成员函数存放在内存哪里堆和栈的区别堆和栈的访问效率“野指针”有了malloc/free为什么还要new/deletealloca内存崩溃C++内存泄漏的几种情况内存对齐柔性数组参考推荐阅读C++内存相关本篇介绍了C++内存相关的知识。C++......
  • 代码练习4-合并 k 个升序的链表。
    数据范围:节点总数 0≤......
  • 逆序打印c++
    逆序打印c++第一次写文章请大佬多多指教说明输入n个数,要求程序按输入时的逆序把这n个数打印出来,已知整数不超过100个。也就是说,按输入相反顺序打印这n个数。输入格式两行,第一行,一个整数N;第2-N+1行,N个整数。输出格式一行,按相反顺序输出这N个数,中间用空格隔开。样例......
  • C/C++ 逗号表达式的注意事项
    在C和C++中,逗号表达式是一种使用逗号运算符,分隔的表达式序列。逗号运算符用于顺序执行其操作数,并返回最后一个操作数的结果。尽管逗号表达式在某些情况下很有用,但它们也需要注意一些重要的细节和潜在的问题。1.逗号表达式的定义和用法逗号表达式由一系列表达式组成,这些表......
  • C++程序设计(谭浩强) 课后习题第五章第6~9题
    6.#include<iostream>usingnamespacestd;classA{public: voidf1(){cin>>i;A::f2();}protected: voidf2(){cout<<"i="<<i<<endl;}private: inti;};classB:publicA{public: voidf3(){cin>>k;cout<......