本文对链表以及C/C++中的动态链表做详细诠释。

什么是链表?
  链表是一种重要的数据结构,它最大的优点是可以进行动态的存储分配。链表有单向链表,双向链表,循环链表。对于c,这里我们只讨论单向链表。
  我们知道,内存是由栈和堆组成的。栈空间是由操作系统和编译系统控制的,比如我们定义int a;这个a就是在栈中开辟内存单元的。而堆空间,则允许给用户提供了虚拟空间,          在堆中是没有变量名这个说法的,只能通过地址来找到内存中存放的东西。

  既然是动态内存分配,当然有动态分配的特殊方法。在c中是以函数的形式实现的。
1.malloc函数
函数原型:void *malloc(unsigned int size)
函数的作用是:在内训的动态存储区开辟一个size个字节的连续空间,返回所分配区域的首字节地址。
可以看到,函数返回值是一个void指针,请注意,void指针不是一个可以指向任何类型数据的指针,而是 说,不指向任何类型的数据,仅仅是提供了一个地址。
因而,你想让这个指针指向int型数据,要进行显式的类型转换(强制类型转换),即在前面加(int *)。一般来说,如果不加,是可以自动进行隐式类型转换的。

2.calloc函数
函数原型:void *calloc(unsigned n,unsigned size)
作用:开辟n个长度为size的连续空间。一般用来保存一个数组。
3.realloc函数
原型:void *realloc(void *p,unsigned int size)
作用:用来重新分配已经分配的动态空间的大小。
4.free函数
原型:void free(void *p)
作用:把已经分配的动态空间释放掉。

======================================================================

言归链表:
  一个链表,是由许多节点组成的。可以自由的删除、添加。指向首节点的指针叫做head指针,它是链表的唯一标示。每个节点包含两部分,一是数据,而是下一个节点的地址。通过这个下个节点的地址,建立了整个链表的联系。

如何建立一个链表呢?
  用结构体建立链表当然是再合适不过了。
  比如:现在建立一个静态链表。
  struct S
  {
    int a;
    struct S *next;
  }S1,S2,S3;
  struct S *head;
  S1.a=1;S2.a=2;S3.a=3;

  head=&S1;
  S1.next=&S2;
  S2.next=&S3;
  S3.next=NULL; //请注意让最有一个节点存放的地址为NULL。

  这样,我们就建立了一个有三个节点的静态链表。
  

如何建立一个动态链表呢?又如何添加、删除节点,更进一步说,怎么使得链表有序,并且进行删除添加操作后使之依然有序 ?

建立动态链表,就是可以随时根据需要来增加结点 。看代码:
  #include<stdio.h>
  #include<stdlib.h>
  #define LEN sizeof(struct S)
  struct S
  {
    int a;
    struct S *next;
  };
  int n; //全局变量n,记录节点个数。未赋初值默认为0;
  struct S *creat_autolist(void) //函数,来创建一个动态链表
  {
    struct S *head; //头指针;
    struct S *p0,*p1; //p0为当前节点;
    p0=p1=(struct S*)malloc(LEN);//用malloc函数开辟一个结点的空间 ;
    scanf("%d",&p0->a);//输入数据;
    head=NULL;
  while(p0->a!=0) //循环,输入的a不为0则继续输入;
  {
    n++;
    if(n==1) head=p0; //是否为第一个结点;
    else p1=p0->next;

    p1=p0; //让p1也指向p0所指向的结点
    p0= (struct S*)malloc(LEN); //在开辟一个节点;
    scanf("%d",&p0->a);
   }
   p1->next=NULL;//尾结点的指针部分为NULL
   return (head);
  }
  

  void main()
  {
    struct S *head,*pt;
    head=creat();
    pt=head;

    /*
    这是输出链表的方法
    */
    if(head!=NULL)
    {
    do
    {
      printf("%d\n",pt->a);
      pt=pt->next;
    }while(pt!=NULL);
    }
  }

至此,动态链表的创建和输出已经实现。

怎么删除结点呢?实际上就是改变要删除的结点的前后的两个节点中地址的指向。
怎么添加结点呢?实际上也是改变指向。
使其做到有序?
那么,我们就要进行一个大小比较的过程了。不过,要考虑在表首,表中,表尾三种情况。

下面给出一个小栗子:

要进行链表的结点添加,并顺序。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define LEN sizeof(struct Student)

struct Student
{
  long num;
  double score;
  struct Student *next;
};
int n=0;

void print(struct Student *head)
{
  struct Student *pt;
  pt=head;
  printf("there are %d records:\n");
if(head!=NULL)
{
  do
  {
    printf("%ld,%5.1lf",pt->num,pt->score);
    pt=pt->next;
  }while(pt!=NULL);
}

}

struct Student *creat()
{
  struct Student *head,*p0,*p1;
  head=NULL;
  printf("*****creat list*****");
  printf("please input record(0,0 for exit)\n");
  p0=(struct Student *)malloc(LEN);
  scanf("%ld,%lf",&p0->num,&p0->score);
while(p0->num!=0)
{
  head=insert(head,p0);
  p0=(struct Student *)malloc(LEN);
  scanf("%ld,%lf",&p0->num,&p0->score);
}
return (head);
}

struct Student *insert(struct Student *head,struct Student *stu)
{
  struct Student *p0,*p1,*p2;
  p0=stu;
if(head==NULL)
{
  head=p0;
  p0->next=NULL;
}
else
{
  p1=head;
  while(p0->num>p1->num&&p1->next!=NULL) //这是个遍历
{
  p2=p1;
  p1=p1->next;
}
  if(p0->num<=p1->num)
{
  if(head==p1)
{
  head=p0;
  p0->next=p1;
}
else
{
  p2.next=p0;
  p0.next=p1;
}
}
else
{
  p1.next=p0;
  p0.next=NULL;
}

}

n++;
return(head);

}  
  

 

 

 

 

 

【C/C++】动态内存分配和链表的更多相关文章

  1. 郑州尚学堂:链表的C语言如何实现动态内存分配

    一.为什么用动态内存分配 但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组.比如说我们要存储一个班级学生的某科分数,总是定义一个float型(存在0.5分)数 ...

  2. c 链表和动态内存分配

    兜兜转转又用到了c.c的一些基本却忘记的差不多了(笑哭)!! 动态内存分配 当malloc完将返回的指针类型强制转换成想要的类型后,指针中存有该指针的数据结构,而分配的内存恰好可用于该数据结构. 链表 ...

  3. SQLite剖析之动态内存分配

    SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.保存查询结果. 1.特性    SQLite内核和它的内存分配子系统提供以下特性 ...

  4. 转: Linux C 动态内存分配 malloc及相关内容 .

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

  5. iOS开发——C篇&动态内存分配

    再C语言中关于内存是一个很重要的知识点,所以今天我就从c语言的内存分配开始为大家解析一下C语言再iOS开发中非常重要的一些知识. 1:malloc函数的介绍 C语言中开辟内存空间:malloc函数 再 ...

  6. C—动态内存分配之malloc与realloc的区别

    在程序的执行期间分配内存时,内存区域中的这个空间称为堆(heap).还有另一个内存区域,称为堆栈(stack),其中的空间分配给函数的参数和本地变量.在执行完该函数后,存储参数和本地变量的内存空间就会 ...

  7. Linux C 动态内存分配--malloc,new,free及相关内容

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

  8. C和指针--动态内存分配

    1.为什么需要使用动态内存分配 数组的元素存储于内存中连续的位置上,当一个数组被声明时,它所需要的内存在编译时就被分配.当你声明数组时,必须用一个编译时常量指定数组的长度.但是,数组的长度常常在运行时 ...

  9. molloc堆区的动态内存分配

    [前言]前面有一篇文章介绍了堆区栈区的区别.栈区的核心主要集中在操作一个栈结构,一般由操作系统维护.堆区,主要是我们程序员来维护,核心就是动态内存分配. 这篇笔记结束就不在高新CSAPP的读书笔记了, ...

随机推荐

  1. SQLSERVER操作字段约束,修改字段名称等

    -- 表加注释EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'注释内容' , @level0type=N'SCHEM ...

  2. MySQL表结构变更,不可不知的Metadata Lock

    在线上进行DDL操作时,相对于其可能带来的系统负载,其实,我们最担心的还是MDL其可能导致的阻塞问题. 一旦DDL操作因获取不到MDL被阻塞,后续其它针对该表的其它操作都会被阻塞.典型如下,如阻塞稍久 ...

  3. Beta阶段团队成员贡献分分配规则

    Beta阶段团队成员贡献分分配规则 Alpha阶段贡献分分配有些负责,在这里进行一些修改: 对任务完成得分部分进行了简化 对发现bug的惩罚措施进行了修改 移除了优化得分,不鼓励修改他人代码 移除了帮 ...

  4. 2198: 小P当志愿者送餐

    题目描述 在ICPC程序设计大赛期间,小P作为志愿者的任务是给各个学校送盒饭,小P一次最多可以携带M份盒饭.总共有N个学校来参加比赛,这N个学校的休息点在一条笔直的马路边一字排开,路的一头是小P取盒饭 ...

  5. Randomized Online PCA Algorithms with Regret Bounds that are Logarithmic in the Dimension

    目录 Setup of Batch PCA and Online PCA Hedge Algorithm 改进算法 用于矩阵 \(rounding()\) 前俩次,都用到了\(rounding()\) ...

  6. rest-framework总结

    1. CBV: pass 2 .APIView class BookView(APIView):pass url(r'^books/$', views.BookView.as_view(),name= ...

  7. [转帖]cnblog 新闻 : 亚太云计算市场报告:腾讯位列前五 份额首超谷歌

    亚太云计算市场报告:腾讯位列前五 份额首超谷歌 投递人 itwriter 发布于 2019-03-18 12:06 评论(1) 有213人阅读 原文链接 [收藏] « » 美国市场研究机构 Syner ...

  8. 网络编程--使用TCP协议发送接收数据

    package com.zhangxueliang.tcp; import java.io.IOException; import java.io.OutputStream; import java. ...

  9. Collections斗地主案例

    package com.zhangxueliang.doudizhu; import java.util.ArrayList; import java.util.Collections; public ...

  10. 剑指offer(15)

    题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 书中的思路: 按照这个思路我们很容易写出以下代码: import java.util.S ...