前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >链表相关知识

链表相关知识

作者头像
且陶陶
发布2023-04-12 14:54:46
2340
发布2023-04-12 14:54:46
举报
文章被收录于专栏:Triciaの小世界

前置知识:

内存区域:

在这里插入图片描述
在这里插入图片描述

一.内存四区:

  1. 代码区:函数代码 存放在代码区 函数名就是函数地址。
  2. 全局区:全局的变量 字符串常量 初始化 int a = 0;
  3. 栈 区:告诉计算机 int double char 定义一个变量c,系统开辟 释放。
  4. 堆 区:自己确定有多大,装什么数据?用完之后是否继续用?自己决定开辟,释放。

例如:其中的b,c,d就是定义在栈区。

代码语言:javascript
复制
int main(){
	int b;
	float c;
	double d;
	}

4个字节可以用以下存放: 1.char c[4]; 2.int 3.float 4.short c[2];

代码语言:javascript
复制
#include<stdlib.h>  
int *p;
p =  (int *)malloc(size);  //在堆区开辟size个字节的内存,指针p指向这段内存
//(用malloc开辟的内存,不会自己释放,需要主动释放)
free(p);   //释放

任何数据都可以用malloc()。

二、数据结构:

用一套具体的方法,管理这些内存。高效有序

  • 链表:内存之间互相连接的一种数据结构。(两种:空头链表,无空头链表)
  • 结点:每一块内存。
  • 数据:每一个结点里面,存放数据。

链表的操作:

(一)链表的头尾添加:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
g_pEnd->pNext = pTemp;      
g_pEnd = pTemp;
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
pTemp->pNext = g_pHead;    
g_pHead = pTemp;
代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>
struct Node
{
    int a;//数据成员
    struct Node* pNext;//指向下一个结点的指针
};
//链表头尾指针
struct Node* g_pHead = NULL;
struct Node* g_pEnd = NULL;
//创建链表,在链表中增加一个数据。(尾添加)
void AddListTill(int a)
{
    //创建一个节点
    struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
    //对节点数据进行赋值
    pTemp->a = a;
    pTemp->pNext = NULL;
    //将节点链接到链表上
    if(NULL == g_pHead||NULL == g_pEnd)  //链表里没有东西,新来的节点既是头也是尾
    {
        g_pHead = pTemp;
        g_pEnd = pTemp;
    }
    else    //正常情况,往尾巴上添加
    {
        g_pEnd->pNext = pTemp;
            // 尾巴一直指向最后一个节点
        g_pEnd = pTemp;
    //逻辑顺序:先把新的节点接到尾上,再挪动尾结点,使他一直指向最后一个节点。
    }
}

//创建链表,在链表中增加一个数据。(头添加)
void AddListHead(int a)
{
    //创建一个节点
    struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node);
    //节点数据赋值
    pTemp->a = a;
    pTemp->pNext = NULL;
    //接在链表上
    if(NULL == g_pHead)
    {
        g_pHead = pTemp;
        g_pEnd = pTemp;
    }
    else
    {
        pTemp->pNext = g_pHead;
        g_pHead = pTemp;
    //逻辑顺序:先把新的结点接到头上,再挪动头结点,使他一直指向第一个节点。
    }
}



int main()
{
    int a[8] = {1,2,3,4,5,6,7,8};
    int i;
    g_pHead;
    for(i = 0;i<8;i++){
    AddListTill(a[i]);
    AddListHead(a[i]);
    }
    return 0;
}

(二):链表的遍历:

在这里插入图片描述
在这里插入图片描述

1. 链表的全部遍历:

注:操作链表时,头指针不能变,可以定一个中间指针(pTemp)

代码语言:javascript
复制
int main()
{
    int a[8] = {1,2,3,4,5,6,7,8};
    int i;
    g_pHead;
    for(i = 0;i<8;i++){
    AddListTill(a[i]);
    //AddListHead(a[i]);
    }
    ScanList();
    return 0;
}

void ScanList()
{
    struct Node *pTemp = g_pHead;
    while(pTemp != NULL)
    {
        pTemp = pTemp->pNext;
        //逻辑:pTemp指向pTemp的后一个,直到遍历结束
        printf("%d\n",pTemp->a);
    }
}

2. 查询指定结点:

代码语言:javascript
复制
int main()
{
    int a[8] = {1,2,3,4,5,6,7,8};
    int i;
    g_pHead;
    for(i = 0;i<8;i++){
    AddListTill(a[i]);
    //AddListHead(a[i]);
    }

   struct Node *pFind = SelectNode(5);
     if(pFind != NULL)
     {
        printf("%d\n",pFind->a);
     }
    else
    {
        printf("没找到!");
    }
    return 0;
}



struct Node* SelectNode(int a)
{
    struct Node *pTemp = g_pHead;
    while(pTemp != NULL)
    {
       if(a == pTemp->a)
       {
           return pTemp;
       }
        pTemp = pTemp->pNext;
    }
    //没找到
    return NULL;
}

(三)链表清空:

一个节点一个节点的遍历,释放。

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
void FreeList()
{
    //记录头,防止头被修改,丢内存
    struct Node *pTemp = g_pHead;
    while(pTemp != NULL)
    {
       struct Node* pt = pTemp;
       pTemp = pTemp->pNext;
       free(pt);
    }
    //头尾清空
    g_pHead = NULL;
    g_pEnd = NULL;
}

(四)指定位置插入节点:

代码语言:javascript
复制
void AddListRand(int index,int a)
{
    //链表为空
    if(NULL == g_pHead)
    {
        printf("链表没有节点\n");
        return;
    }
    //找位置
    struct Node* pt = SelectNode(index);
    if(NULL == pt)
    {
        printf("没有指定节点\n");
        return;
    }
    //有此节点
    //给a创建节点
    struct Node*pTemp = (struct Node*)malloc(sizeof(struct Node));
    //给节点成员赋值
    pTemp->a = a;
    pTemp->pNext = NULL;
    
    //链接到链表上
    if(pt == g_pEnd)
    {
        //尾巴的下一个指向新的节点
        g_pEnd->pNext = pTemp;
        //新节点是最后一个,变成尾巴
        g_pEnd = pTemp;
    }
    else
    {
        //先连
        pTemp->pNext = pt->pNext;
        //后断
        pt->pNext = pTemp;
    }
}

(五)头删除:

栈 = 头添加+头删除;
在这里插入图片描述
在这里插入图片描述
逻辑:
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
void DeleListHead()
{
    //链表检测
    if(NULL == g_pHead)
    {
        printf("链表为空,无需释放!\n");
        return;
    }
    //记住旧的头
    struct Node* pTemp = g_pHead;
    //头的下一个节点变成新的头
    g_pHead = g_pHead->pNext;
    //释放旧的头
    free(pTemp);
}
队列 = 头添加+尾删除(尾添加+头删除)
在这里插入图片描述
在这里插入图片描述

(六)尾删除:

逻辑:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
void DeleListTail()
{
    //链表检测
    if(NULL == g_pHead)
    {
        printf("链表为空,无需释放!\n");
        return;
    }
    //链表不为空,考虑链表元素个数
    //链表有一个节点
    if(g_pHead == g_pEnd)
    {
        free(g_pHead);
        g_pHead = NULL;
        g_pEnd = NULL;
    }
    //有多个节点
    else
    {
        //找到尾巴前一个节点
        struct Node* pTemp = g_pHead;
        while(pTemp->pNext != g_pEnd)
        {
            pTemp = pTemp->pNext;
        }
        //找到了,删尾
        //释放
        free(g_pEnd);
        //尾巴前移
        g_pEnd = pTemp;
        //尾的下一指针赋值NULL;
        g_pEnd->pNext = NULL;

    }
}

(七)删除指定节点:

删除中间节点的逻辑:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
void DeleListRand(int a)
{
    //链表判断
    if(NULL == g_pHead)
    {
        printf("链表为空,无需释放!\n");
        return;
    }
   //链表有东西,找这个节点
   struct Node* pTemp = SelectNode(a);
   if(NULL == pTemp)
   {
       printf("查无此节点\n");
       return;
   }
   //找到了
   //只有一个节点
   if(g_pHead == g_pEnd)
   {
       DeleListHead();
   }
   //有两个节点
   else if(g_pHead->pNext == g_pEnd)
   {
       if(g_pHead == pTemp)
       {
           DeleListHead();
       }
       else
       {
           DeleListTail();
       }
   }
   //有多个节点
   else
   {
       if(g_pHead == pTemp)
       {
           DeleListHead();
       }
       else if(g_pEnd == pTemp)
       {
           DeleListTail();
       }
       //删除中间节点
       else
       {
        //找到要删除的节点的前一个节点
        struct Node* pT = g_pHead;
        while(pTemp->pNext != pTemp)
        {
            pT = pT->pNext;
        }
        //找到了
        //链接
        pT->pNext = pTemp->pNext;
        //释放
        free(pTemp);
       }
   }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前置知识:
    • 内存区域:
      • 一.内存四区:
      • 二、数据结构:
  • 链表的操作:
    • (一)链表的头尾添加:
      • (二):链表的遍历:
        • 1. 链表的全部遍历:
        • 2. 查询指定结点:
      • (三)链表清空:
        • (四)指定位置插入节点:
          • (五)头删除:
            • (六)尾删除:
              • (七)删除指定节点:
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档