精华内容
下载资源
问答
  • 动态内存分配链表

    千次阅读 2018-04-26 17:55:37
    首先考虑这样一个问题: char t[10]=”hi”: char *p=”hi” 两者的区别: 可以清除的看到,第一个内存的动态存储区,第...动态内存分配: 1.malloc函数: void *malloc(unsigned int size) 解释:在内存的动态...

    首先考虑这样一个问题:
    char t[10]=”hi”: char *p=”hi” 两者的区别:
    可以清除的看到,第一个内存的动态存储区,第二个为内存的静态存储区,对于第二个而言,hi是常量所以不能够修改指针指向的地址其中的数据不能够做动态改变。

    1>动态内存分配:
    1.malloc函数:

    void *malloc(unsigned int size)

    解释:在内存的动态存储区域(堆)中分配一个长度为size的连续空间,其参数是一个无符号整形,返回值是一个系统所分配的连续内存空间的起始地址。分配失败的话(内存不足)返回NULL。

    该函数仅仅对指针有作用引用malloc.h头文件(库)

    应用举例:

    #include<stdio.h>
    #include<malloc.h>
    void main()
    {
        char *a;
        a=(char*)malloc(10*sizeof(char));
         //申请一个10个单位的char则会么长的动态内存,返回一个void*指针(首地址)
         //第一个括号为强制类型转换
        if(a==NULL)
            {
                printf("失败”);
                exit;
            }
        else
        *a='h';
        *(a+1)='e';
        *(a+2)='l';
        printf(a);        //打印字符串
    }
    

    2.free 函数
    作用释放动态内存。
    例子:

    void *free(void *p)
    
    //举例:
    char*a,*b;
    a=(char *)malloc(10*sizeof(char));
    b=a;
    
    free(a);  //释放掉a指针指向的动态内存。效果和free(b)相同
    
    //如果申请了动态内存,最后一定要释放掉这些动态内存。

    二、链表:
    链表有线性结构和链式结构。例如数组就是最基本的线性结构。但是数组有一些很不方便的地方,比如插入元素不方便,需要大部分移动。
    链表:链表是动态爆粗一些数据,不需要预先分配内存空间,在需要的时候动态申请内存。可以根据需要扩大或者缩小。
    例子:链表的创建

    展开全文
  • 链表的C语言实现 含动态内存分配

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   

    链表的C语言实现(含动态内存分配)

    上 链表的C语言实现之动态内存分配

     

    一、为什么用动态内存分配

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

    float score[30];

      但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?

      在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道该班级的学生的人数,那么你就要把数组定义得足够大。这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。即使你知道该班级的学生数,但是如果因为某种特殊原因人数有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。

      那么有没有其它的方法来解决这样的外呢体呢?有,那就是动态内存分配。

      所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于景泰内存分配的特点:

      1、不需要预先分配存储空间;

      2、分配的空间可以根据程序的需要扩大或缩小。

    二、如何实现动态内存分配及其管理

      要实现根据程序的需要动态分配存储空间,就必须用到以下几个函数

      1、malloc函数

      malloc函数的原型为:

    void *malloc (unsigned int size)


      其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。还有一点必须注意的是,当函数未能成功分配存储空间(如内存不足)就会返回一个NULL指针。所以在调用该函数时应该检测返回值是否为NULL并执行相应的操作。

    下例是一个动态分配的程序:

    #include "malloc.h"#include "stdlib.h"main(void){/*count是一个计数器,array是一个整型指针,也可以理解为指向一个整型数组的首地址*/int count;int *array;array=malloc(10 * sizeof(int));if(array==NULL){printf("Out of memory!\n");exit(1);}/*给数组赋值*/for(count=0;count<10;count++){array[count]=count;}/*打印数组元素*/for(count=0;count<10;count++){printf("%2d\n",array[count]);}}




      上例中动态分配了10个整型存储区域,然后进行赋值并打印。例中if((array(int *) malloc(10*sizeof(int)))==NULL)语句可以分为以下几步:

      1)分配10个整型的连续存储空间,并返回一个指向其起始地址的整型指针

      2)把此整型指针地址赋给array

      3)检测返回值是否为NULL

      2、free函数

      由于内存区域总是有限的,不能不限制地分配下去,而且一个程序要尽量节省资源,所以当所分配的内存区域不用时,就要释放它,以便其它的变量或者程序使用。这时我们就要用到free函数。

      其函数原型是:

    void free(void *p)


      作用是释放指针p所指向的内存区。

      其参数p必须是先前调用malloc函数或calloc函数(另一个动态分配存储区域的函数)时返回的指针。给free函数传递其它的值很可能造成死机或其它灾难性的后果。

      注意:这里重要的是指针的值,而不是用来申请动态内存的指针本身。例:

    int *p1,*p2;
    p1=malloc(10*sizeof(int));
    p2=p1;
    ……
    free(p2) /*或者free(p2)*/


      malloc返回值赋给p1,又把p1的值赋给p2,所以此时p1,p2都可作为free函数的参数。

      malloc函数是对存储区域进行分配的。

      free函数是释放已经不用的内存区域的。

      所以由这两个函数就可以实现对内存区域进行动态分配并进行简单的管理了。

     

    中 链表的C语言实现之单链表的实现

    一、单链表的建立

      有了动态内存分配的基础,要实现链表就不难了。

      所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分为单链表、双向链表和循环链表等。我们先讲讲单链表。所谓单链表,是指数据接点是单向排列的。一个单链表结点,其结构类型分为两部分:

      1、数据域:用来存储本身数据

      2、链域或称为指针域:用来存储下一个结点地址或者说指向其直接后继的指针。

      例:

    typedef struct node{ char name[20]; struct node *link;}stud; 


     

    这样就定义了一个单链表的结构,其中char name[20]是一个用来存储姓名的字符型数组,指针*link是一个用来存储其直接后继的指针。

      定义好了链表的结构之后,只要在程序运行的时候数据域中存储适当的数据,如有后继结点,则把链域指向其直接后继,若没有,则置为NULL。

      下面就来看一个建立带表头(若未说明,以下所指链表均带表头)的单链表的完整程序。

    #include <stdio.h>#include <stdlib.h>#include <malloc.h> /*包含动态内存分配函数的头文件*/#define N 10 /*N为人数*/ typedef struct node{  char name[20];  struct node *link;}stud;stud * creat(int n) /*建立单链表的函数,形参n为人数*/{stud *p,*h,*s;/* *h保存表头结点的指针,*p指向当前结点的前一个结点,*s指向当前结点*/int i;/*计数器*/if((h=(stud *)malloc(sizeof(stud)))==NULL) /*分配空间并检测*/{printf("不能分配内存空间!");exit(0);}h->name[0]='\0'; /*把表头结点的数据域置空*/h->link=NULL; /*把表头结点的链域置空*/p=h; /*p指向表头结点*/for(i=0;i<n;i++){if((s=(stud *) malloc(sizeof(stud)))==NULL) /*分配新存储空间并检测*/{printf("不能分配内存空间!");exit(0);}p->link=s; /*把s的地址赋给p所指向的结点的链域,这样就把p和s所指向的结点连接起来了*/printf("请输入第%d个人的姓名",i+1);scanf("%s",s->name); /*在当前结点s的数据域中存储姓名*/s->link=NULL;p=s;}return(h);}main(){  int number; /*保存人数的变量*/  stud *head; /*head是保存单链表的表头结点地址的指针*/number=N;head=creat(number);/*把所新建的单链表表头地址赋给head*/

      这样就写好了一个可以建立包含N个人姓名的单链表了。写动态内存分配的程序应注意,请尽量对分配是否成功进行检测。

     

    下 链表的C语言实现之循环链表及双向链表

     

    一、循环链表

      循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。

      循环链表的运算与单链表的运算基本一致。所不同的有以下几点:

      1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。

      2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL。

      二、双向链表

      双向链表其实是单链表的改进。

      当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。

      在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。在c语言中双向链表结点类型可以定义为:

    typedef struct node{int data; /*数据域*/struct node *llink,*rlink; /*链域,*llink是左链域指针,*rlink是右链域指针*/}JD;


     

    当然,也可以把一个双向链表构建成一个双向循环链表。

      双向链表与单向链表一样,也有三种基本运算:查找、插入和删除。

      双向链表的基本运算:

      1、查找

      假若我们要在一个带表头的双向循环链表中查找数据域为一特定值的某个结点时,我们同样从表头结点往后依次比较各结点数据域的值,若正是该特定值,则返回指向结点的指针,否则继续往后查,直到表尾。

      下例就是应用双向循环链表查找算法的一个程序。

    #include <stdio.h>#include <malloc.h>#define N 10typedef struct node{ char name[20]; struct node *llink,*rlink;}stud;stud * creat(int n){ stud *p,*h,*s; int i; if((h=(stud *)malloc(sizeof(stud)))==NULL) {  printf("不能分配内存空间!");  exit(0); } h->name[0]=’\0’; h->llink=NULL; h->rlink=NULL; p=h; for(i=0;i<n;i++) {  if((s= (stud *) malloc(sizeof(stud)))==NULL)  {   printf("不能分配内存空间!");   exit(0);  }  p->rlink=s;  printf("请输入第%d个人的姓名",i+1);  scanf("%s",s->name);  s->llink=p;  s->rlink=NULL;  p=s; } h->llink=s; p->rlink=h; return(h);}stud * search(stud *h,char *x){ stud *p; char *y; p=h->rlink; while(p!=h) {  y=p->name;  if(strcmp(y,x)==0)   return(p);  else p=p->rlink; } printf("没有查找到该数据!");}void print(stud *h){ int n; stud *p; p=h->rlink; printf("数据信息为:\n"); while(p!=h) {  printf("%s ",&*(p->name));  p=p->rlink; } printf("\n");}main(){ int number; char studname[20]; stud *head,*searchpoint; number=N; clrscr(); head=creat(number); print(head); printf("请输入你要查找的人的姓名:"); scanf("%s",studname); searchpoint=search(head,studname); printf("你所要查找的人的姓名是:%s",*&searchpoint->name);}


     

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • 1 动态内存分配 1.1 malloc //malloc函数动态申请内存,返回类型是申请的同变量类型的指针 //如果申请失败,则返回空指针NULL typename* p1=(typename*)malloc(sizeof(typename)); //对应malloc的内存释放 free...

    1 动态内存分配

    1.1 malloc

    //malloc函数动态申请内存,返回类型是申请的同变量类型的指针
    //如果申请失败,则返回空指针NULL 
    typename* p1=(typename*)malloc(sizeof(typename));
    //对应malloc的内存释放
    free(p1); 

    1.2 new

    //new运算符申请动态空间
    //如果申请失败,则会启动C++异常机制处理 
    typename* p2=new typename; 
    //对应new的内存释放
    delete(p2); 

    2 动态链表

    2.1 链表结点

    //链表结构体
    struct node{
    	int data;	//数据域 
    	node* next; 
    };

    2.2 创建链表

    //创建链表
    node* create(int array[]){
    	node *p,*pre,*head;	//pre是前驱结点,head是头结点
    	head=new node;	//创建头结点 
    	head->next=NULL; 	//头结点不需要数据域,指针域初始化为NULL 
    	pre=head;	//记录pre为head 
    	for(int i=0;i<5;i++){
    		p=new node;			//新建节点
    		p->data=array[i];	//赋值给新结点作为数据域 
    		p->next=NULL;		//指针域为NULL 
    		pre->next=p;		//连上前驱结点的指针域 
    		pre=p;				//把p设为下个结点的前驱结点 
    	} 
    	return head;	//前驱结点 
    } 

    2.3 查询元素

    //在以head为头结点的链表上计数元素x的个数
    int search(node* head,int x){
    	int count=0;
    	node* p=head->next;
    	while(p!=NULL){
    		if(p->data==x)
    			count++;
    		p=p->next;
    	}
    	return count;
    }

    2.4 插入结点

    //将x插入以head为头结点的链表的第pos个位置上
    void insert(node* head,int pos,int x){
    	node* p=head;
    	for(int i=0;i<pos-1;i++)
    		p=p->next;
    		
    	node* q=new node;
    	q->data=x;
    	q->next=p->next;
    	p->next=q;
    }

    2.5 删除结点

    //删除以head为头结点的链表中所有数据域为x的结点
    void del(node* head,int x){
    	node* p=head->next;
    	node* pre=head;
    	while(p!=NULL){
    		if(p->data==x){
    			printf("YES\n");
    			pre->next=p->next;
    			delete(p);
    			p=pre->next;
    		}else{
    			pre=p;
    			p=p->next;
    		}
    	}
    }

    3 静态链表

    //静态链表
    struct Node{
    	typename data;	//数据域
    	int next;		//指针域 
    }node[size]; 

     

    展开全文
  • 动态内存分配以及链表的基本操作

    千次阅读 2017-08-06 18:38:01
    一、c/c++中的动态内存分配 1、在c中申请动态内存使用的是malloc函数,malloc函数位于stdlib.h头文件下,其返回类型是申请的同变量类型的指针。例如申请一个node类型结构体变量使用以下的方式: node* p = (node*)...

    一、c/c++中的动态内存分配

    1、在c中申请动态内存使用的是malloc函数,malloc函数位于stdlib.h头文件下,其返回类型是申请的同变量类型的指针。例如申请一个node类型结构体变量使用以下的方式:
    node* p = (node*) malloc(sizeof(node));
    用malloc函数申请的内存空间用完后需要使用free函数释放,例如释放前面申请的内存空间 :free(p);

    2、在c++中申请动态内存使用的是new运算符,其返回类型为申请的同变量类型的指针,例如申请一个node类型的结构体变量使用以下的方式:
    node* p = new node;
    用new申请的内存空间用完后需要使用delete运算符释放,例如释放前面申请的内存空间:delete(p);

    二、链表的基本操作

    1、创建链表
    以创建结点类型为int型的链表为例,比如创建一个链表:1 -> 2 -> 3 -> 4 -> 5
    struct node{
    	int data;
    	node* next;
    };

    node* create(int Array[]){
    	node *p, *pre, *head;
    	head = new node;
    	head->next = NULL;
    	pre = head;
    	for(int i = 0; i < 5; i++){
    		p = new node;
    		p->data = Array[i];
    		p->next = NULL;
    		pre->next = p;
    		pre = p; 
    	}
    	return head;
    }

    2、查找元素

    int search(node* head, int x){
    	int count = 0;
    	node* p = head->next;
    	while(p != NULL){
    		if(p->data == x){
    			count++;
    		}
    		p = p->next;
    	}
    	return count;
    }

    3、插入元素
    void insert(node* head, int pos, int x){
    	node* p = head;
    	for(int i = 0; i < pos - 1; i++){
    		p = p->next;
    	}
    	node* q = new node;
    	q->data = x;
    	q->next = p->next;
    	p->next = q;
    }

    4、删除元素
    void del(node* head, int x){
    	node* p = head->next;
    	node* pre = head;
    	while(p != NULL){
    		if(p->data = x){
    			pre->next = p->next;
    			delete(p);
    			p = pre->next;
    		}
    		else{
    			pre = p;
    			p = p->next;
    		}
    	}
    }


    展开全文
  • 链表的C语言实现(含动态内存分配) 上 链表的C语言实现之动态内存分配   一、为什么用动态内存分配  但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组。...
  • 本文使用隐式空闲链表实现简单的动态内存分配动态内存分配器维护一个大块区域,也就是堆,处理动态内存分配请求。分配器将堆视为一组不同大小的块的集合来维护,每个块要么是已分配的,要么是空闲的。 实现...
  • 动态分配内存链表

    千次阅读 2016-04-04 14:21:23
    C/C++学习笔记之八 上一节我们讲到了结构体,结构体是一个...1.动态内存分配(malloc/free) 原因:数组的长度定死了,无法改变,这才引入了动态内存的分配  例: struct Student{ int id;//学号 char name[10];
  • 简单理解动态内存分配和静态内存分配的区别

    千次阅读 多人点赞 2015-06-22 13:38:22
    在我看来,静态内存分配动态内存分配比较典型的例子就是数组和链表,数组的长度是预先定义好的,在整个程序中是固定不变的,所以他在内存分配时是以静态内存分配的方式进行的。而链表,它的信息有可能会随时更改,...
  • 1、mm_init()从内存系统得到4个字,并将它们初始化为填充字、序言块头部、序言块脚部、结尾块。然后调用extend_heap()函数,将堆扩展CHUNKSIZE字节,并创建初始空闲块。(见mm.c) 2、extend_heap()为保持双字...
  • 【 声明:版权所有,...大家都知道,链表内存分配就是从链表中快速找到最合适的内存块分配给用户线程。因为这种分配是随机的,所以一般来说内存碎片是不可避免的。但是,我们在编写代码的时候还是应该注意内存合并的
  • 作者: 杜红超 何青青一、为什么用动态内存分配 但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组。比如说我们要存储一个班级学生的某科分数,总是定义一个float型...
  • C语言 动态内存分配

    千次阅读 2016-12-09 10:32:13
    动态内存分配涉及到堆栈的概念:堆栈是两种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。 栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,...
  • c++中创建链表可以直接通过new对象的方式创建节点,然后将节点之间的关系通过next指针来关联起来,另外,也可以通过malloc来分配内存,创建节点。这里介绍如何通过malloc来创建链表。 malloc分配内存的方式为...
  • 动态内存分配与释放

    千次阅读 2018-04-15 21:16:47
    1. 动态内存分配 动态内存分配与释放经常在数据结构的链表、树和图结构中。动态内存分配在需要时进行,不需要时即释放,不需要提前分配,就是根据实际需要而分配。 内存的动态分配需要使用函数 malloc、函数free和...
  • Dynamic Memory Allocate(动态内存分配)

    千次阅读 2016-12-11 23:00:39
    介绍 空闲链表 ...介绍动态内存分配:在程序运行时给相应变量分配内存。因为在很多时候我们只有在运行的时候才知道内存,提前分配要么就会太大,浪费了空间;要么就是太小,信息存放不下。动态内存
  • 动态内存分配(C语言)

    千次阅读 多人点赞 2021-05-13 20:43:50
    动态内存分配 不放过每一个值得关注的点 文章目录动态内存分配前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 我们创建一个一维的数组的时候,可以是静态分配的,也可以是动态分配的。 静态分配...
  • 动态内存分配器 专 业 计算机科学与技术 计算机科学与技术学院 mm.c源代码见文章末尾 目 录 第1章 实验基本信息... - 4 - 1.1 实验目的... - 4 - 1.2 实验环境与工具... - 4 - 1.2.1 ...
  • 链表——动态存储分配的数据结构

    千次阅读 2017-05-31 23:46:03
    但是涉及长度定义的问题,所以就出现了动态链表。 ② 动态链表:在程序执行过程中从无到有建立起来,一个一个地开辟结点和输入各结点的数据,并建立前后相连的关系。 单链表——所有结点都是单线联系 ① 特点:(1)...
  • 操作系统原理:动态内存分配

    千次阅读 2017-04-12 23:21:13
    动态内存分配背后的机制深刻的体现了计算机科学中的这句名言: All problem in CS can be solved by another level of indirection. — Butler Lampson ...
  • 题目:C语言 定义一个单向链表,依次从键盘输入10个整数,通过动态内存分配建立链表的节点,将节点按保存整数值从小到大的顺序插入到单链表中,最后输出这个单链表 是不是要先排序再建立动态链表,再建立输出链表呀...
  • 实验报告 实 验(八) 题 目 Dynamic Storage Allocator ... 动态内存分配器 专 业 计算机类 学 号 1180800811 班 级 1803002 学 生 姓 名 张瑞豪 指 导 教 师 史先俊 实 验 ...
  • 链表内存管理

    千次阅读 2018-07-31 21:05:41
    链表 链表由一个个节点组成。...单链表有一个头节点head,指向链表内存的首地址。无论在表中访问那一个节点,都需要从链表的头开始,顺序向后查找。链表的尾节点由于无后续节点,其指针域为空,写作为NULL。...
  • 动态内存分配之循环首次适应算法

    千次阅读 2016-12-22 17:11:04
    1.已分配区和空闲区是分别表示的 2.采用的是单向链表 3.采用了尾指针tail,单纯的用来指向尾空闲区域 4.写了3天,好吧,我确实很菜,但是引用请注明出处,谢谢了 #include #include #include <malloc.
  • 模拟内存分配(链表实现)

    千次阅读 2016-02-03 11:20:18
    我们拥有长度为m字节的内存,输入的第一行是两个整数,分别代表对内存的操作次数以及m的大小,输入的第二行是一个字符串,也就是这个模拟内存分配程序 所支持的三种操作: 1.alloc n – 分配n字节的连续内存,并...
  • 使用链表管理内存

    千次阅读 2016-07-28 10:09:50
    使用链表管理内存的使用,这儿重新定义了 malloc,realloc,free函数,使用了mymalloc,myrealloc,myfree自己重定义了函数 mem.h #include #include void * mymalloc(size_t size); void *myrealloc(void *p, ...
  • Linux内核动态内存分配

    千次阅读 2013-09-23 09:49:19
    内存分配按其对象大致可分为三类:1. 连续页框;2. 专用或通用对象;3. 非连续的内存区。如果所请求的内存区得以满足,将返回一个页描述符地址或线性地址;否则,返回NULL。 第一类:连续页框【Buddy Allocator】...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 166,086
精华内容 66,434
关键字:

链表动态内存分配