C语言中不允许动态定义数组类型长度。前面程序中的数组长度是预先定义好的,在整个程序中是固定不变的。在实际编程中一般不能预先确定数据所需内存空间的大小。利用C语言的内存管理函数,可以根据实际需要动态的分配内存空间或回收释放空闲空间,合理有效的利用内存资源。
从键盘输入两个集合La和Lb,将所有在线性表Lb中但不存在La中的数据元素插入到La中
主要包含头文件以及定义的重命名还有模版
#pragma once
#include
#include //malloc等管理内存函数
#include //exit函数
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
typedef int Boolean; //布尔类型
typedef int ElemType;
#define LIST_INIT_SIZE 10 //线性表存储空间的初始分配量
#define LISTINCREMENT 2 //线性表存储空间的分配增量
typedef struct
{
ElemType* elem; //存储空间基质
int length; //当前长度
int listsize; //当前分配的存储量以(sizeof(ElemType)为单位
}SqList;
//采用线性表的动态分配顺序存储
int InitList(SqList* L); //初始化
int ListLength(SqList L);
int GetElem(SqList L, int i, ElemType* e);
int LocateElem(SqList L, ElemType e,int(*compare)(ElemType,ElemType));
int ListInsert(SqList* L, int i, ElemType e);
int ListTraverse(SqList L, void (*vi)(ElemType*));
int equal(ElemType c1, ElemType c2);
void Union(SqList* La, SqList Lb);
void print(ElemType* c); //打印
具体函数的实现
#include "sqlist.h"
//采用线性表的动态分配顺序存储结构
int InitList(SqList* L) //初始化
{
//构造一个空的线性表
//分配10个int型单元,储存空间基质赋给结构体elem单元
(*L).elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!(*L).elem)
{
exit(OVERFLOW); //分配空间失败
}
(*L).length = 0; //空表长度为零
(*L).listsize = LIST_INIT_SIZE;//初始储存容量
return OK;
}
//顺序线性表长度
int ListLength(SqList L)
{
//当顺序表L存在,返回长度
return L.length;
}
//获取线性表里面的元素
int GetElem(SqList L, int i, ElemType* e)
{
//线性表L存在, 用e返回l中第i个元素的值·
if (i <1 || i>L.length)
exit(ERROR);
*e = *(L.elem + i - 1);
return OK;
}
//确定位置
int LocateElem(SqList L, ElemType e, int(*compare)(ElemType, ElemType))
{
/*初始条件,顺序表L存在,compare()是数据元素的判定函数(1满足,否则0)*/
/*返回L中第一个与e满足关系的compare()数据元素的位序*/
ElemType* p;
int i = 1; //i初始值为第一个元素
p = L.elem; //p的初始值为第一元素的存储位置
while (i <= L.length && !compare(*p++, e))
{
++i;
}
if (i <= L.length)
{
return i;
}
else
{
return 0;
}
}
int ListInsert(SqList* L, int i, ElemType e)
{
/*顺序表L的i个位置插入新的元素,长度+1*/
ElemType *newbase, * q, * p;
if (i<1 || i>(*L).listsize)//当前存储空间已满,增加分配
{
newbase = (ElemType*)realloc((*L).elem, ((*L).listsize + LISTINCREMENT) * sizeof(ElemType));
if (!newbase) //储存分配失败
{
exit(OVERFLOW);
}
(*L).elem = newbase; //新的基质
(*L).listsize += LISTINCREMENT;//增加存储容量
}
q = (*L).elem + i - 1; //插入位置
for (p = (*L).elem + (*L).length - 1; p >= q; --p)
{
*(p + 1) = *p;
}
*q = e;//插入e
++(*L).length;
return OK;
}
int ListTraverse(SqList L, void(*vi)(ElemType*))
{
//线性表L存在,以此对L的每一个元素调用vi(),一旦vi()失败,这操作失败
//vi()的形参用“&”表明可以通过vi()改变元素值
ElemType* p;
p = L.elem;
for (int i = 1; i <= L.length; i++)
{
vi(p++);
}
cout << "\n";
return OK;
}
int equal(ElemType c1, ElemType c2)
{
if (c1 == c2)
{
return TRUE;
}
else
return FALSE;
}
void Union(SqList* La, SqList Lb) //将在Lb元素,不在La的插入La中
{
ElemType e;
int La_len, Lb_len;
La_len = ListLength(*La);
Lb_len = ListLength(Lb);
for (int i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, &e);
if (!LocateElem(*La, e, equal))
{
ListInsert(La, ++La_len, e);
}
}
}
void print(ElemType* c) //打印
{
cout << *c++ <<" ";
}
程序的主函数,具体函数的运用
#include "sqlist.h"
int main()
{
SqList La, Lb;
int i, j;
i = InitList(&La);
if (i == 1)
{
for (j = 1; j <= 5; j++) //在La表中插入5个元素
{
i = ListInsert(&La, j, j);
}
}
cout << "La=";
ListTraverse(La,print);
InitList(&Lb);
for (j = 1; j <= 5; j++) //在La表中插入5个元素
{
i = ListInsert(&Lb, j, 2*j);
}
cout << "Lb=";
ListTraverse(Lb, print);
Union(&La, Lb);
cout << "NEW La=";
ListTraverse(La, print);
return 0;
}
1)调用形势: (类型说明符)malloc(size)
例:
L.data = (ElemType*)malloc(sizeof(ElemType * InitSize))
2)功能:在内存的动态存储区中分配一块长度为size字节的连续区域。函数的返回值为该区域的首地址
3)“类型说明符”表示把该区域用于何种数据类型指针。malloc函数返回一个指针,需要强制转化为自己所定义元素类型指针
p = (char*)malloc(100)
表示分配100字节的内存空间,并强制转换位字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc。
1.调用形式:free(void* ptr);
2.功能释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量它所指向被释放区域的首地址。被释放区是由malloc或者calloc函数所分配的区域。
此外还有两种分配空间的函数realloc和calloc,在此就不过多赘述。