目录
内存
1.内存管理:
1.malloc
2.free
2.内存溢出:
3.内存泄露:
4.内存碎片:
链表:
1,为什么要使用链表:
2,链表类型的定义:
3,头链表的创建:
4,新链表的写入:
5,链表的输出:
6,链表内容的替换:
7,链表数据的删除:
8,链表空间的释放:
void *malloc(size_t size);
功能:
申请堆区空间
参数:
size:申请堆区空间的大小
返回值:
返回获得的空间的首地址
失败返回NULL
void free(void *ptr);
功能:
释放堆区空间
注意:
1.free只能释放堆区空间
2.一个空间只能被free一次,多次free程序会崩溃
3.malloc需要和free搭配使用,如果只有malloc没有free会内存泄露
malloc和free的使用参考如下:
#include
#include
int main(void)
{
int *p = NULL;
p = malloc(4);
if(NULL == p)
{
printf("malloc faild!\n");
return -1;
}
*p = 100;
printf("*p = %d\n",*p);
free(p);
return 0;
}
练习:要求申请堆区空间,将"hello world"存放到堆区空间,完成打印
参考如下:
#include
#include
#include
int main(void)
{
char *p = NULL;
p = malloc(12);
if(NULL == p)
{
printf("fall");
return -1;
}
strcpy(p,"hello world");
printf("p = %s\n",p);
free(p);
return 0;
}
在函数间传参时,利用使用malloc和free函数创造出来的空间来传递也是一个方便的新方法
参考如下:
#include
#include
#include
char *fun(void)
{
char *pa = NULL;
pa = malloc(12);
if(pa == NULL)
{
return NULL;
}
strcpy(pa,"hello world");
return pa;
}
int main(void)
{
char *p = NULL;
p = fun();
printf("%s\n",p);
return 0;
}
内存溢出也称为内存越界
程序中malloc的空间没有被释放
由于频繁申请和释放,导致连续的空间分散成一些小的碎片空间,当malloc超过碎片空间时,则无法获得该空间(空间不连续),将这样的空间称为内存碎片
======================================================================================================================================================
区别于数组中每个元素只储存数据
链表的构成中每个元素都由两部分组成包括:
元素储存的数据和指向下一个链表的地址
——————————
数据 | 地址
——————————
链表分为:
有头链表和无头链表
1,对比于数组它的数据处理速度快
2,由于链表所占空间不连续,能更有效地利用零碎空间
先介绍一个函数
typedef函数
作用:
主要用于给用户自主构造的数据类型例如构造体赋予简单的类型名
定义形式:
typedef 数据类型 新类型名;
参考:
#include
#include
#include
typedef int DataType;
int main(void)
{
return 0;
}
那么利用typedef函数和构造体的知识我们就可以构造出一个链表类型LinkNode
参考如下:
#include
#include
#include
typedef struct node
{
DataType Data;
struct node *pNext;
}LinkNode;
这里我们采用封装函数的方法创建新的头链表
因为我们要返回一个链表形式的返回值,所以函数类型我们定义为上面构造的链表类型
参考如下:
LinkNode *CreateLinkList(void)
{
LinkNode *pTmpNode = NULL;
pTmpNode = malloc(sizeof(LinkNode));
if(pTmpNode == NULL)
{
return NULL;
}
pTmpNode->pNext = NULL;
return pTmpNode;
}
int main(void)
{
LinkNode *LinkList = NULL;
LinkList = CreatLinkList();
return 0;
}
(这里的写入方法是头插法)
这里的实参传的是上面定义的头链表
参考如下:
int InsertLinkList(LinkNode *pHead,DataType TmpData)
{
LinkNode *pTmpNode = NULL;
pTmpNode = malloc(sizeof(LinkNode));
if(pTmpNode == NULL)
{
return -1;
}
pTmpNode->Data = TmpData;
pTmpNode->pNext = pHead->pNext;
pHead->pNext = pTmpNode;
return 0;
}
int main(void)
{
InsertLinkList(LinkList,新数据);
return 0;
}
将头链表传入函数,然后遍历输出即可
参考如下:
int ShowLinkList(LinkNode *pHead)
{
LinkNode *pTmpNode = NULL;
pTmpNode = pHead->pNext;
while(pTmpNode != NULL)
{
printf("%d ",pTmpNode->Data);
pTmpNode = pTmpNode->pNext;
}
printf("\n");
return 0;
}
int main(void)
{
ShowLinkList(Linklist);
return 0;
}
参考如下:
int ReplaceLinkList(LinkNode *pHead,DataType OldData,DataType NewData)
{
LinkNode *pTmpNode = NULL;
pTmpNode = pHead->pNext;
while(pTmpNode != NULL)
{
if(pTmpNode->Data == OldData)
{
pTmpNode->Data = NewData;
}
pTmpNode = pTmpNode->pNext;
}
return 0;
}
int main(void)
{
ReplaceLinkList(LinkList,被替换数据,新数据);
return 0;
}
数据的删除也就代表着相应链表空间的删除,所以我们在遍历到需删除的数据时,也要将对应空间释放,并注意在本次循环中只需要将靠近尾部的指针后移即可
参考如下:
int DeleteLinkList(LinkNode *pHead,DataType DeleteData)
{
LinkNode *pTmpNode = NULL;
LinkNode *pPreNode = NULL;
pTmpNode = pHead->pNext;
pPreNode = pHead;
while(pTmpNode != NULL)
{
if(pTmpNode->Data == DeleteData)
{
pPreNode->pNext = pTmpNode->pNext;
free(pTmpNode);
pTmpNode = pTmpNode->pNext;
}
else
{
pTmpNode = pTmpNode->pNext;
pPreNode = pPreNode->pNext;
}
}
return 0;
}
int main(void)
{
DeleteLinkList(LinkList,要删除的数据);
return 0;
}
这里需要注意的是头链表指针还指向着已经被回收的头链表空间,该空间在被回收后内容为乱码,为了避免出现bug,函数里采用二级指针将头链表指针的内容更改为NULL
参考如下:
int DestroyLinkList(LinkNode **pHead)
{
LinkNode *pTmpNode = NULL;
LinkNode *pFreeNode = NULL;
pFreeNode = *pHead;
pTmpNode = pFreeNode->pNext;
while(pTmpNode != NULL)
{
pTmpNode = pTmpNode->pNext;
free(pFreeNode);
pFreeNode = pTmpNode;
}
*pHead = NULL;
return 0;
}
int main(void)
{
DestroyLinkList(&LinkList);
return 0;
}
1.封装函数在链表中实现尾插法
int InsertTailLinkList(LinkNode *pHead, DataType TmpData);
2.从终端接收一个字符串,将字符串倒置后输出
"how are you"
"you are how"
1,参考答案:
#include
#include
#include
typedef struct node
{
int Data;
struct node *pNext;
}LinkNode;
LinkNode *CreatLinkList(void)
{
LinkNode *pTmpNode =NULL;
pTmpNode = malloc(sizeof(LinkNode));
if(pTmpNode == NULL)
{
return NULL;
}
pTmpNode->pNext = NULL;
return pTmpNode;
}
int InsertHeadLinkList(LinkNode *pHead,int TmpData)
{
LinkNode *pTmpNode = NULL;
LinkNode *pInserNode = NULL;
pInserNode = malloc(sizeof(LinkNode));
if(pInserNode == NULL)
{
return -1;
}
pTmpNode = pHead;
while(pTmpNode->pNext != NULL)
{
pTmpNode = pTmpNode->pNext;
}
pInserNode->pNext = NULL;
pInserNode->Data = TmpData;
pTmpNode->pNext = pInserNode;
return 0;
}
int ShowLinkList(LinkNode *pHead)
{
LinkNode *pTmpNode = NULL;
pTmpNode = pHead->pNext;
while(pTmpNode != NULL)
{
printf("%d ",pTmpNode->Data);
pTmpNode = pTmpNode->pNext;
}
printf("\n");
return 0;
}
int DestroyLinkList(LinkNode **ppHead)
{
LinkNode *pTmpNode = NULL;
LinkNode *pFreeNode = NULL;
pTmpNode = pFreeNode = *ppHead;
while (pTmpNode != NULL)
{
pTmpNode = pTmpNode->pNext;
free(pFreeNode);
pFreeNode = pTmpNode;
}
*ppHead = NULL;
return 0;
}
int main(void)
{
LinkNode *LinkList = NULL;
LinkList = CreatLinkList();
InsertHeadLinkList(LinkList,1);
InsertHeadLinkList(LinkList,2);
InsertHeadLinkList(LinkList,3);
InsertHeadLinkList(LinkList,4);
InsertHeadLinkList(LinkList,5);
ShowLinkList(LinkList);
DestroyLinkList(&LinkList);
return 0;
}
2,参考答案:
#include
#include
int InverFun(char *pa,int len,int lin)
{
int i = lin;
char tmp = 0;
while(i < len-1)
{
tmp = pa[i];
pa[i] = pa[len-1];
pa[len-1] = tmp;
i++;
len--;
}
return 0;
}
int SmartInverFun(char *pa,int len)
{
int i = 0;
int j = 0;
InverFun(pa,len,j);
while(pa[i] != '\0')
{
if(pa[i] == ' ')
{
InverFun(pa,i,j);
j = i + 1;
}
i++;
}
InverFun(pa,len,j);
return 0;
}
int main(void)
{
char a[32] = {0};
int len = 0;
gets(a);
len = strlen(a);
SmartInverFun(a,len);
puts(a);
return 0;
}
C语言阶段学习结束