线性顺序表动态内存分配(C语言实现)

2021-05-28 05:01

阅读:441

标签:key   length   原理   定义数据   delete   归并   empty   后退   语言   

/***********************************线性表顺序存储结构的ADT定义(数组实现)**********************************************
   ADT List
   {
        数据对象:D={ ai | ai ∈ElemSet, i=1,2,...,n,  n≥0 } 
        数据关系:R1={ |ai-1 ,ai∈D,  i=2,...,n }
        基本操作:
                 (1)线性表的初始化操作 
				      InitList(&L,n)
                      操作结果:将L初始化为空表,申请空间的大小为n。
                 (2)线性表元素输入操作 
				      ListInput(&L)
				      初始条件:线性表L已存在 。
                      操作结果:线性表中的部分元素或全部元素已被赋值。     
                 (3)线性表的置空操作 
				      ClearList(&L) 
                      初始条件:线性表L已存在且不为空 。
                      操作结果:将表L置为空表。
                 (4)线性表的判空操作 
				      ListIsEmpty(&L)
                      初始条件:线性表L已存在。
                      操作结果:如果L为空表则返回1,否则返回0。
                 (5)获取线性表元素个数的操作 
				      ListLength(L)
                      初始条件:线性表L已存在。
                      操作结果:如果L为空表则返回0,否则返回表中的元素个数。
                 (6)获取线性表第i个元素的操作(用元素的位序查找元素的值) 
				      GetItem(L,i,&e)
                      初始条件:表L已存在且不为空,1
#include   //使用了malloc、realloc、free函数 

//******************************************自定义符号常量******************************************* 

#define LIST_INIT_SIZE 100  //线性表存储空间的初始分配量
#define LISTINCREMENT 10    //线性表存储空间的分配增量 
#define OVERFLOW -2         //内存溢出错误常量
#define ILLEGAL -1          //非法操作错误常量 
#define OK 1                //表示操作正确的常量 
#define ERROR 0             //表示操作错误的常量

//******************************************自定义数据类型********************************************

typedef int Status;
typedef float ElemType;
typedef struct{
	ElemType *elem;   //线性表存储空间初始分配量
	int length;       //当前长度 
	int listsize;     //当前分配的存储容量(以sizeof(ElemType)为单位) 
}SqList;

//******************************************线性表的主要操作****************************************** 

//1.--------------------线性表的初始化操作---------------------------- 

/*
	函数:InitList_Sq
	参数:SqList &L 线性表引用 
	      int n 线性表最多能存储n个元素 
	返回值:状态码,OK表示操作成功 
	作用:构造一个空线性表L  
*/
Status InitList_Sq(SqList &L, int n) { 

	//申请线性表的内存空间,申请n个元素大小的内存空间 
	L.elem = (ElemType *)malloc(n * sizeof(ElemType));  
	
	//判断内存是否分配成功 
	if(!L.elem){ //if(!L.elem)  if(L.elem == NULL) 
		printf("内存申请失败!\n");
		exit(OVERFLOW); //若内存分配失败,则退出程序
	}//if
	printf("内存申请成功!\n"); 
	
	//设置线性表的各个参数 
	L.length = 0;    //设置线性表的长度为0 
	L.listsize = n;  //设置线性表的空间大小为100个元素所占空间的大小
	
	printf("线性表创建成功!\n");
	//操作成功后返回OK 
	return OK;   
}//InitList_Sq

//2.----------------------输入线性表元素的操作-------------------

/*
	函数:ListInput_Sq
	参数:SqList &L 线性表引用 
	返回值:状态码,OK表示操作成功 
	作用:初始化线性表L中的元素 
*/
Status ListInput_Sq(SqList &L){

	//i声明在这里不是好的写法,应该将i写在for循环中,有利于缩短i的作用域,及早回收其内存空间。
	//但是由于C语言不兼容这种写法,考虑到兼容性所以将i写在外面。(C++支持这种写法) 
    int n, i;   //n代表元素的个数,i用作循环变量
    
    //从键盘接收元素的个数,用户输入正确后退出此循环 
	while(1){ //while(1)是一个死循环,除非在循环体内执行break语句,否则永远无法退出循环 
		//先确定元素的个数 
		printf("您想输入几个元素,请输入个数,最多不可以超过:%d\n", L.listsize);  
		scanf("%d",&n);
		if(n  100) {
			//如果发生非法操作,就提醒用户重新输入
			printf("您的输入非法,请重新输入!!!\n");   
		}//if  
		else {
			break;	
		}//else    
    }//while
    
    //使用键盘输入的方式初始化每一个元素
    printf("请输入线性表L的元素,中间用空格隔开,最多不可以超过100个元素\n");
	for(i = 0; i  L.length + 1) { 
	    return ERROR;    //i的值不合法,返回错误 
	}//if
	
	//插入操作之前需要先检查存储空间是否够用,若不够用就需要扩容 
	if(L.length >= L.listsize) {   //当前存储已满,需要扩容 

		//realloc函数第一个参数是已经分配了的那部分存储空间的首地址,
		//第二个参数是重新分配的内存的大小,这个参数的值一般情况下
		//会比已经分配的内存空间大一些或者小一些,但是需要注意的是
		//如果新的大小小于原内存大小,可能会导致数据丢失。
		
		//realloc函数的工作原理: 先判断当前的指针是否有足够的连续空间,
		//如果有,扩大mem_address指向的地址,并且将mem_address返回,
		//如果空间不够,先按照newsize指定的大小分配空间,将原有数据
		//从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域
		//(注意:原来指针是自动释放,不需要使用free),
		//同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
		
		//realloc函数的特点:如果我们只扩大不缩小,原先已分配内存的保存的数据不会丢失
		//这部分数据会被realloc函数转移到新的内存空间中,我们不需要
		//手工写拷贝数据的代码,也不需要手工释放第一个参数指示的已分配内存空间。
		//我们只需要接收返回值,就能得到新的内存空间的首地址 
		
		//使用realloc函数为线性表重新分配内存空间
		newbase = (ElemType *)realloc(L.elem, 
			(LIST_INIT_SIZE + L.listsize) * sizeof(ElemType));  
		
		//判断内存空间是否分配成功 
		if(!newbase){ //if(!newbase)    if(newbase == NULL)
		    printf("内存申请失败!\n");
		    //若内存分配失败,则后续操作就没有意义了,此时应退出程序
		    exit(OVERFLOW); 
	    }//if
		printf("内存申请成功!\n");
		L.elem = newbase;  //将线性表新基址赋给elem
		L.listsize += LISTINCREMENT;  //增加存储容量 
	}//if
	
	//找到插入位置 
	q = &(L.elem[i - 1]);  //q指示了插入位置
	
	//将插入位置及之后的元素后移
	for(p = &(L.elem[L.length - 1]); p >= q; --p) { 
	    *(p + 1) = *p;
	}//for 
	
	//将e插入到q指示的插入位置 
	*q = e;
	
	//插入元素e后表长应该增加1  
	++L.length;
	
	//操作成功 
	return OK; 
}//ListInsert_Sq 

//5.----------------------线性表中删除元素的操作----------------------------

/*
	函数:ListDelete_Sq
	参数:SqList &L 线性表引用
	      int i 删除位置,1  if(ListIsEmpty_Sq(L) != 0)
	if(ListIsEmpty_Sq(L)) {
	    return ERROR; 
	}//if
	 
	//判断删除位置的参数i的值是否合法 
	if(i  L.length) { 
	    return ERROR;    //i的值不合法,返回错误
	}//if
	
	//找到删除位置,p指示了被删除元素的位置 
	p = &(L.elem[i - 1]);
	
	//保存将被删除的元素 
	e = *p;
	
	//找到表尾元素的位置,q指示了表尾元素的位置 
	q = L.elem + L.length - 1;
	
	//从被删除元素之后开始到表尾元素位置,将被删除元素之后的所有元素前移一位
	//当此循环结束时,被删除元素被其紧随其后的元素覆盖了,也就是删除了 
	for(++p; p 
    int main(){
	      int max(int, int), min(int, int), add(int, int);
          void process(int, int, int (*fun)(int, int));
          int a, b;
          printf("enter a and b:");  
          scanf("%d,%d", &a, &b);
          process(a, b, max);
          process(a, b, min);
          process(a, b, add);
    }//main
    
    process(int x, int y, int (*fun)(int, int)){ 
	      int result;
          result = (*fun)(x, y);
          printf("%d\n",result);
    }//process
    
	max(int x, int y) {   
	      printf(“max=”);
          return(x > y ? x : y);
    }//max
    
    min(int x, int y){    
	      printf(“min=”);
          return(x  if(ListIsEmpty_Sq(L) != 0)
	if(ListIsEmpty_Sq(L)) { 
	    return ERROR;  
	}//if
	
	//设置查找的起始位置 
	int i = 1;        //i的初值为第一个元素的位序
	p = L.elem;       //p的初值为第一个元素的存储位置
	
	//以compare函数返回值为基准在线性表中查找元素e 
	while(i  if(ListIsEmpty_Sq(La) != 0)
     if(ListIsEmpty_Sq(La)) {
     	return ERROR;
     }//if 
	
	 //if(ListIsEmpty_Sq(Lb))  if(ListIsEmpty_Sq(Lb) != 0)
	 if(ListIsEmpty_Sq(Lb)) {
	 	return ERROR; 
	 }//if 
	
	 //工作指针pa, pb保存了线性表a、b存储元素内存空间的首地址 
     pa = La.elem;  
	 pb = Lb.elem;
	 
	 //合并后的线性表c表长等于被合并的线性表a和b的表长之和 
     Lc.listsize = Lc.length = La.length + Lb.length;
     
     //确定线性表c的长度之后为其申请内存空间,大小等于a和b两表之和 
     pc = Lc.elem = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));
     
	 //检查内存分配是否成功 
	 if(!Lc.elem){ //if(!Lc.elem)  if(Lc.elem == NULL)
		printf("内存申请失败!");
		exit(OVERFLOW); //若内存分配失败,则退出程序
	 }//if
	 
	 //计算出线性表a和b的表尾元素所在位置,分别赋给对应的指针变量pa_last和pb_last 
     pa_last = La.elem + La.length - 1;
     pb_last = Lb.elem + Lb.length - 1;
     
     //合并pa和pb到pc
	 
	 //首先将线性表a和b中较短的一个完全合并到pc,另一个只合并一部分 
     while (pa  if(ListIsEmpty_Sq(L) != 0)
	if(ListIsEmpty_Sq(L)) { 
	    return ERROR; 
	}//if
	
	//设置变量的初始值 
	int low = 0;   
    int high = L.length-1;  
    int tmp, j;  
    while (low  L.elem[j + 1]) {  
                tmp = L.elem[j]; 
				L.elem[j] = L.elem[j + 1];
				L.elem[j + 1] = tmp;  
            }//if
    	}//for
    	
    	//修改high值, 前移一位 
        --high;  
        
        //反向冒泡,找到最小者
		for (j = high; j > low; --j) {   
            if (L.elem[j]  if(visit(L.elem[i]) != ERROR) 
		if(!visit(L.elem[i])) { 
			return ERROR; //如果访问某个元素失败则退出 
		}//if 
	}//for
	
	//便利完成后打印空行,作用是在控制台输出时能够区分开不同的输出
	//使输出清楚美观 
	printf("\n");
	return OK;
}//ListTraverse_Sq


//***************************************主函数******************************************** 
int main(int argc, char *argv[]){ 

    SqList L1, L2, L3;  //声明三个线性表 
    int i;              //i代表元素的位序 
	ElemType e;         //e用于传入和保存元素的值 
	
	printf("*******************************线性顺序表测试程序*******************************\n");
	
	//---------------------------------测试初始化功能----------------------------------
	printf("---------------------------------测试初始化功能---------------------------------\n");	 
	printf("->初始化线性表L1\n");  
    InitList_Sq(L1, LIST_INIT_SIZE);             //初始化线性表1 
	ListInput_Sq(L1);  //为L1中的元素赋值
    printf("恭喜您,线性表L1初始化并赋值完毕!\n\n");
			
	printf("->初始化线性表L2\n");
	InitList_Sq(L2, LIST_INIT_SIZE);             //初始化线性表2 
	ListInput_Sq(L2);  //为L2中的元素赋值
	printf("恭喜您,线性表L2初始化并赋值完毕!\n\n");
	
	//-----------------------------测试输出功能---------------------------------------
	printf("----------------------------------测试输出功能----------------------------------\n"); 
	printf("初始化操作之后L1、L2的元素为:\n");
	printf("->输出线性表L1的所有元素:\n");
	ListTraverse_Sq(L1, Print);                           //在执行其他操作之前先输出一遍所有元素,以供参考 
	printf("->输出线性表L2的所有元素:\n");
	ListTraverse_Sq(L2, Print);
	
	//-----------------------------测试插入功能---------------------------------------
	printf("\n----------------------------------测试插入功能----------------------------------\n"); 

	printf("->现在为L1插入元素\n");                        //为线性表L1插入一个元素 
	printf("您想在线性表L1的哪个位置之前插入值?\n");
	scanf("%d", &i);
	printf("您想在线性表L1的该位置之前插入的值为多少?\n");
	scanf("%f", &e);
	ListInsert_Sq(L1,i,e);
	printf("执行插入操作后线性表L1的所有元素为:\n");      //输出执行操作后的线性表,以便与原始结果对比 
	ListTraverse_Sq(L1,Print);
	
    printf("->现在为L2插入元素\n");
	printf("您想在线性表L2的哪个位置之前插入值?\n");      //为线性表L2插入一个元素
	scanf("%d", &i);
	printf("您想在线性表L2的该位置之前插入的值为多少?\n");
	scanf("%f", &e);
	ListInsert_Sq(L2, i, e);
	printf("执行插入操作后线性表L2的所有元素为:\n");     //输出执行操作后的线性表,以便与原始结果对比 
	ListTraverse_Sq(L2, Print);
	printf("\n插入操作执行完毕!\n\n");
	
	//-----------------------------测试删除功能---------------------------------------
	printf("----------------------------------测试删除功能----------------------------------\n");
	
	printf("->现在在L1中删除元素\n");                        //在L1中删除一个元素 
	printf("您想在线性表L1的哪个位置之前删除值?\n");
	scanf("%d", &i);
	ListDelete_Sq(L1, i, e);
	printf("被删除的元素为%f\n", e);
	printf("执行删除操作后线性表L1的所有元素为:\n");      //输出执行操作后的线性表,以便与原始结果对比 
	ListTraverse_Sq(L1, Print);
	
    printf("->现在在L2中删除元素\n");                        //在L2中删除一个元素 
	printf("您想在线性表L2的哪个位置之前删除值?\n");
	scanf("%d", &i);
	ListDelete_Sq(L2, i, e);
	printf("被删除的元素为%f\n", e);
	printf("执行删除操作后线性表L2的所有元素为:\n");      //输出执行操作后的线性表,以便与原始结果对比 
	ListTraverse_Sq(L2, Print);
	printf("\n删除操作执行完毕!\n\n");
	
	//-----------------------------测试查找功能---------------------------------------
	printf("----------------------------------测试查找功能----------------------------------\n");	
	printf("您想在线性表L1中查找的值为:\n");
	scanf("%f", &e);
	i = LocateElem_Sq(L1, e, compare);
	if(i == 0){ 
		printf("对不起,没有找到您输入的元素!\n");
    }//if 
	else {
	    printf("恭喜,找到啦!您想要的元素在表中的位序为%d\n",i); 
	}//else
	
    printf("您想在线性表L2中查找的值为:\n");
	scanf("%f", &e);
	i = LocateElem_Sq(L2, e, compare);
	if(i == 0) {
		printf("对不起,没有找到您输入的元素!\n");
	}//if
    else {
	    printf("恭喜,找到啦!您想要的元素在表中的位序为%d\n", i);
	}//else
	
	printf("\n查找操作执行完毕!\n\n");
	
	//---------------------------------测试排序功能---------------------------------------
	printf("----------------------------------测试排序功能----------------------------------\n"); 
	printf("排序前 L1、L2的元素为:\n");
	printf("->线性表L1的所有元素:\n");
	ListTraverse_Sq(L1, Print);                           //在执行操作之前先输出一遍所有元素,以供参考 
	printf("->线性表L2的所有元素:\n");
	ListTraverse_Sq(L2, Print);
	
	SortList_Sq(L1);                            //分别对L1和L2进行排序 
	SortList_Sq(L2); 
	
	printf("排序后 L1、L2的元素为:\n");
	printf("->线性表L1的所有元素:\n");
	ListTraverse_Sq(L1, Print);                           //执行操作之后再输出一遍所有元素
	printf("->线性表L2的所有元素:\n");
	ListTraverse_Sq(L2, Print);
	printf("\n排序操作执行完毕!\n\n");
	
	//-----------------------------测试归并(合并)功能---------------------------------------
	printf("----------------------------------测试归并功能----------------------------------\n");	
	printf("->初始化线性表L3\n");
	InitList_Sq(L3, L1.listsize + L2.listsize);         //初始化线性表3,空间大小为L1与L2的和,但不给元素赋值
	printf("线性表L3初始化成功!开始归并操作\n\n");
	MergeList_Sq(L1, L2, L3); 
	printf("->线性表L3的所有元素:\n");
	ListTraverse_Sq(L3, Print); 
	printf("归并操作执行完毕!\n\n");
	
	//--------------------------------测试销毁功能------------------------------------------
	printf("----------------------------------测试销毁功能----------------------------------\n");
	printf("->销毁线性表L1:");
	DestoryList_Sq(L1); 
	printf("->销毁线性表L2:");
	DestoryList_Sq(L2);
	printf("->销毁线性表L3:");
	DestoryList_Sq(L3);
	printf("销毁操作执行完毕!\n\n");
	
	printf("所有操作执行完毕,测试成功!\n"); 
	return 0;	
}

/* ---------------------------------     运行结果     ------------------------------ 

	*******************************线性顺序表测试程序*******************************
	---------------------------------测试初始化功能---------------------------------
	->初始化线性表L1
	内存申请成功!
	线性表创建成功!
	您想输入几个元素,请输入个数,最多不可以超过:100
	5
	请输入线性表L的元素,中间用空格隔开,最多不可以超过100个元素
	1 45 7 89 6
	该线性表初始化操作已完成!
	恭喜您,线性表L1初始化并赋值完毕!
	
	->初始化线性表L2
	内存申请成功!
	线性表创建成功!
	您想输入几个元素,请输入个数,最多不可以超过:100
	10
	请输入线性表L的元素,中间用空格隔开,最多不可以超过100个元素
	45 75 24 16 23 45 89 62 51 44
	该线性表初始化操作已完成!
	恭喜您,线性表L2初始化并赋值完毕!
	
	----------------------------------测试输出功能----------------------------------
	初始化操作之后L1、L2的元素为:
	->输出线性表L1的所有元素:
	  1.00  45.00   7.00  89.00   6.00
	->输出线性表L2的所有元素:
	 45.00  75.00  24.00  16.00  23.00  45.00  89.00  62.00  51.00  44.00
	
	----------------------------------测试插入功能----------------------------------
	->现在为L1插入元素
	您想在线性表L1的哪个位置之前插入值?
	2
	您想在线性表L1的该位置之前插入的值为多少?
	55
	执行插入操作后线性表L1的所有元素为:
	  1.00  55.00  45.00   7.00  89.00   6.00
	->现在为L2插入元素
	您想在线性表L2的哪个位置之前插入值?
	6
	您想在线性表L2的该位置之前插入的值为多少?
	33
	执行插入操作后线性表L2的所有元素为:
	 45.00  75.00  24.00  16.00  23.00  33.00  45.00  89.00  62.00  51.00  44.00
	
	插入操作执行完毕!
	
	----------------------------------测试删除功能----------------------------------
	->现在在L1中删除元素
	您想在线性表L1的哪个位置之前删除值?
	4
	被删除的元素为7.000000
	执行删除操作后线性表L1的所有元素为:
	  1.00  55.00  45.00  89.00   6.00
	->现在在L2中删除元素
	您想在线性表L2的哪个位置之前删除值?
	2
	被删除的元素为75.000000
	执行删除操作后线性表L2的所有元素为:
	 45.00  24.00  16.00  23.00  33.00  45.00  89.00  62.00  51.00  44.00
	
	删除操作执行完毕!
	
	----------------------------------测试查找功能----------------------------------
	您想在线性表L1中查找的值为:
	55
	恭喜,找到啦!您想要的元素在表中的位序为2
	您想在线性表L2中查找的值为:
	99
	对不起,没有找到您输入的元素!
	
	查找操作执行完毕!
	
	----------------------------------测试排序功能----------------------------------
	排序前 L1、L2的元素为:
	->线性表L1的所有元素:
	  1.00  55.00  45.00  89.00   6.00
	->线性表L2的所有元素:
	 45.00  24.00  16.00  23.00  33.00  45.00  89.00  62.00  51.00  44.00
	排序后 L1、L2的元素为:
	->线性表L1的所有元素:
	  1.00   6.00  45.00  55.00  89.00
	->线性表L2的所有元素:
	 16.00  23.00  24.00  33.00  44.00  45.00  45.00  51.00  62.00  89.00
	
	排序操作执行完毕!
	
	----------------------------------测试归并功能----------------------------------
	->初始化线性表L3
	内存申请成功!
	线性表创建成功!
	线性表L3初始化成功!开始归并操作
	
	->线性表L3的所有元素:
	  1.00   6.00  16.00  23.00  24.00  33.00  44.00  45.00  45.00  45.00  51.00  55.00  62.00  89.00  89.00
	归并操作执行完毕!
	
	----------------------------------测试销毁功能----------------------------------
	->销毁线性表L1:内存空间释放成功!
	->销毁线性表L2:内存空间释放成功!
	->销毁线性表L3:内存空间释放成功!
	销毁操作执行完毕!
	
	所有操作执行完毕,测试成功!
	
	--------------------------------
	Process exited with return value 0
	Press any key to continue . . .

*/ 

线性顺序表动态内存分配(C语言实现)

标签:key   length   原理   定义数据   delete   归并   empty   后退   语言   

原文地址:https://www.cnblogs.com/btlord/p/14791023.html


评论


亲,登录后才可以留言!