线性表的C/C++实现(数据结构 严蔚敏版)

下面的代码是项目文件:一个头文件、一个源文件、一个测试文件

1、头文件List.h:

#include<iostream>
using namespace std;
#include<malloc.h>

/*定义数据的类型,可以通过修改这里的数据类型,来实现不同类型的线性表
下面的数据类型可以更改,const引用是限制被调用的函数,不能修改主程序的数据,但可以查看,达到保护主程序数据安全。
不需要执行修改操作,而只要查看数据的线性表就用const限制 引用 
*/
typedef int Status;
typedef int ElemType;

#define LIST_INIT_SIZE 10  //初始化的空间分配容量 
#define LIST_ADD 10		//每次增加的分配空间增量 
#define ok 1
#define error 0
#define flow 0


//定义一个线性表结构,结构内有分配空间的基地址,分配空间的总长度,当前使用空间的大小。 
typedef struct{
	
	ElemType* elem;   //空间基地址 
	int length;		//当前已经使用的空间的长度 
	int listsize;	//当前分配的空间长度 
	
}SqList;


//初始化线性表 
Status InitList(SqList& L); 

//打印线性表
Status Print(SqList L);

//销毁线性表 
Status DestroyList(SqList& L);

//将线性表清空 
Status ClearList(SqList& L);

//判断线性表是否为空 
Status  ListEmpty(const SqList& L);

//返回线性表中元素的个数
Status ListLength(const SqList& L);

	
//获取线性表中的第i个元素的值 
Status Get(const SqList& L, int i, ElemType& e); 

	
//如果当前元素cur_e不是第一个数据,就pre_e返回它的前一个数据的值,否则返回error 
Status PriorElem(const SqList& L, ElemType cur_e, ElemType& pre_e);


//如果当前元素不会最后一个,就用next_e返回它的后一个数值,否则返回error
Status NextElem(const SqList& L, ElemType cur_e, ElemType& next_e);
	

//在第i个位置前插入数据e, 数据长度加一 
Status ListInsert(SqList& L, int i, ElemType e);
	

// 删除i个位置的数据,数据长度减一,并返回数据 
Status ListDelete(SqList& L, int i, ElemType& e);
	
//合并线性表LA和LB,将结果放入LA中 
Status Union(SqList& LA, const SqList& B); 

//合并线性表
Status MergeList(const SqList& LA, const SqList& LB, SqList& LC); 

//查询数据的位置 
int LocateElem(const SqList& L, ElemType e);

//插入n个数据
Status Insert(SqList& L, int n); 
 
 

2、源文件List.cpp:

#include "List.h" 

//这是功能实现源文件,其他程序可以通过头文件包含,使用这里的功能 
 
//初始化线性表 
Status InitList(SqList& L){
	L.elem = (ElemType* )(malloc( LIST_INIT_SIZE * sizeof(ElemType)));
	
	//如果地址分配错误,就返回0 
	if(!L.elem) exit(error);
	
	//将当前长度设置为0,分配长度设置为初始长度 
	L.length = 0;
	L.listsize = LIST_INIT_SIZE;
	
	return ok;
	 
}


//销毁线性表 
Status DestroyList(SqList& L){
	//如果地 
	if(!L.elem){
		cout<<"线性表不存在"<<endl;
		
	}else{
			free(L.elem);
			L.elem = NULL;
	}

	return ok;
} 

//打印线性表
Status Print(SqList L){
	cout<<"线性表的数据如下:"<<endl;
	if(L.length == 0){
		cout<<"线性表为空表, 请插入数据后再来打印数据\n\n"<<endl;
	}
	for(int i=0; i<L.length; i++){
		
		cout<<L.elem[i]<<" ";
	}
	
	
	cout<<endl;
} 



//将线性表清空 
Status ClearList(SqList& L){
	//如果线性表的当前长度不为0,就将数据全部清空,当前长度设置为0 
	if(L.length != 0){
		for(int i=0; i<L.length; i++){
			L.elem[i] = 0;
		}
		L.length = 0;
		
		
	}
	
	return ok;
}



//判断线性表是否为空 
Status  ListEmpty(const SqList& L){
	if(L.length != 0){
		
		//不为空表 
		return ok;
		
	}else{
		
		//为空表 
		return error;
	}
}



//返回线性表中元素的个数
Status ListLength(const SqList& L){
	return L.length; 
} 



//获取线性表中的第i个元素的值 
Status Get(const SqList& L, int i, ElemType& e){
	if(i > L.length || i < 0){
		cout<<"输入有误,退出"<<endl;
		return error;
		
	}else{
		e = L.elem[i-1];
		return ok;
	}
}



//如果当前元素cur_e不是第一个数据,就pre_e返回它的前一个数据的值,否则返回error 
Status PriorElem(const SqList& L, ElemType cur_e, ElemType& pre_e){
	int flag = LocateElem(L, cur_e);
	
	if(flag == -1){
		cout<<"找不到数据"<<endl; 
		return error;
	}
	
	if(flag == 0){
		cout<<"数据不存在直接前驱"<<endl; 
	
	}else{
			pre_e = L.elem[flag-1];
	}
	 	
} 



//如果 当前元素不会最后一个,就用next_e返回它的后一个数值,否则返回error
Status NextElem(const SqList& L, ElemType cur_e, ElemType& next_e){
	int flag = LocateElem(L, cur_e);
	
	if(flag = -1){
		cout<<"数据不存在"<<endl; 
		
	}else if(flag == L.length){
		cout<<"该数据不存在直接后继"<<endl;
	}else{
		next_e = L.elem[flag+1];
	}
} 



//在第i个位置前插入数据e, 数据长度加一 
Status ListInsert(SqList& L, int i, ElemType e){
 
	if(i<1 || i > L.length+1) {
		cout<<"输入的位置有问题"<<endl; 
		return error;

	}
	
	if(L.length == L.listsize){
		//增加LIST_ADD长度的地址空间 
		L.elem = (ElemType*)(realloc(L.elem, (LIST_ADD) * sizeof(ElemType)));
		
		if(!L.elem) exit(flow); 
		
		//更新分配的长度 
		L.listsize = L.listsize + LIST_ADD;
		
		//取要插入位置的地址 
		ElemType* q = &(L.elem[i-1]);
		
		//如果地址p比插入的地址q大或则等于,就将数据复制到后面一位空间里面,空出地址q的存储空间 
		for(ElemType* p = &(L.elem[L.length-1]); p>= q; p--){
			*(p+1) = *p;
		
		}	
		
		//给地址空间q赋值 
		*q = e;
		
		//当前长度+1 
		L.length++;
		
	}else{
		
		//如果分配空间没有使用完,执行下面操作
		 
			//取要插入位置的地址 
		ElemType* q = &(L.elem[i-1]);
		
		//如果地址p比插入的地址q大或则等于,就将数据复制到后面一位空间里面,空出地址q的存储空间 
		for(ElemType* p = &(L.elem[L.length-1]); p>= q; p--){
			*(p+1) = *p;
		
		}	
		
		//给地址空间q复制 
		*q = e;
		
		//当前长度+1 
		L.length++;
		
	}
	return ok;

	
} 


// 删除i个位置的数据,数据长度减一,并返回数据 
Status ListDelete(SqList& L, int i, ElemType& e){
	if(i > L.length || i<0){
		cout<<"你删除的数据不存在\n\n"<<endl;
		return error; 
	}else{
		ElemType* q = &L.elem[i-1];
		e = *q;
		q = &L.elem[L.length-1];
		
		for(ElemType* p = &L.elem[i-1]; p<= q; p++){
			*p = *(p+1);
		}
		
		L.length--;
		cout<<"删除成功\n\n"<<endl;
		
		return ok;
	} 
} 

//合并线性表,将LA和LB合并后的结果替换为LA 
Status Union(SqList& LA, const SqList& LB){
	int LA_length = LA.length;
	int LB_length = LB.length;
	ElemType e;
	
	for(int i=0; i<= LB_length; i++){
		//获取LB的第i个位置的数据 
		 Get(LB, i, e);
		
		for(int i=0; i<LB_length; i++){
			
			//在LA中查询数据e是否存在,不存在就返回i,存在就返回-1 
			int index = LocateElem(LA,  e);
			
			//不为-1就在LA中插入数据 e 
			if(index != -1){
				ListInsert(LA, ++LA.length, e); 
				
			}
		}	
		
	
	} 
	
	cout<<"线性表合并完成, 查看第一个线性表可以查看合并后的数据"<<endl;
	return ok;
} 



//合并有序线性表,并排序,将结果放有序入LC中 
Status MergeList(const SqList& LA, const SqList& LB, SqList& LC){
	InitList(LC);
	int i, j, k;
	i = j = 1;
	k = 0;
	ElemType a, b;
	
	int la_length = LA.length; 
	int lb_length = LB.length;
	
	while((i  <= la_length) && (j <= lb_length)){
		Get(LA, i, a); Get(LB, j, b);
		
		if(a <= b){
			{
				ListInsert(LC, ++k, a);
				i++;
			}
			
		}else{
			ListInsert(LC, ++k, b);
			j++;
		}
	}
	
	while(i <= la_length){
		Get(LA, i++, a);
		ListInsert(LC, ++k, a);
	}
	
	while(j <= lb_length){
		Get(LB, j++, b);
		ListInsert(LC, ++k, b);
	}
	
	
} 



//查询某个数据e的位置
int LocateElem(const SqList& L, ElemType e){
	if(L.length == 0){
		return -1;
	}
	
	for(int i=0; i<L.length; i++){
		if(L.elem[i] == e){
			return i+1;
			
		}else{
			return -1;
		}
	}
	
} 


//插入n个数据
 Status Insert(SqList& L, int n){
 	ElemType e;
 	
 	if(n + L.length > L.listsize){
 		L.elem = (ElemType*)(realloc(L.elem, (LIST_ADD) * sizeof(ElemType)));
 		
 		//如果地址分配失败,就返回错误 
 		if(!L.elem)  return error;
 		
 		L.listsize = L.listsize + LIST_ADD;
	 }
	 
	cout<<"请输入你要插入的"<<n<<"数据"<<endl;
	  
 	for(int i=L.length; i<n; i++){
 		cin>> L.elem[i];
 		
	 }
	 
	 cout<<"数据插入完成\n\n"<<endl; 
	 L.length = L.length + n;
	 return ok;
	 
  }
 
 
 

3、测试文件test.cpp:

#include <iostream>
#include "List.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

//测试一个线性表功能 
int main(int argc, char** argv) {
	SqList L;
	
	cout<<"请输入你的操作"<<endl;
	cout<<"		0-----退出\n"<<endl;
	cout<<"		1-----初始化线性表\n"<<endl;
	
	int n;
	int i;
	ElemType e;
	
	//初始化线性表 
	InitList(L);
	
	while(1){
		cout<<"请输入你的操作"<<endl;
		cin>>n;
		
		if(n>1 || n < 0){
			cout<<"你输入的有问题,请重新输入"<<endl;
		}else{
			break;
		}
	} 
	
	if(n == 0){
		cout<<"你已退出"<<endl;
		exit(flow);
		
	}
	
	//进入操纵
	while(1){
		switch(n){
			
			case 0:	
				//销毁之后重新进行初始化,并退出 
				DestroyList(L);
				cout<<"线性表销毁成功\n\n"<<endl;
				cout<<"你已退出"<<endl;
				exit(flow);	
			
			case 1:
				//重新初始化线性表 
				if(L.elem){
					free(L.elem);
					cout<<"重新初始化成功,原来数据被清空\n\n"<<endl;
				}
				InitList(L); break;
				
			case 2:
				//查看线性表所有数据 
				Print(L); break;
				
			case 3:
				//数据插入 
				cout<<"请输入你要插入的位置和数据\n"<<endl;
				
				cin>>i;
				cin>>e;
				
				if(ListInsert(L, i, e)){
					cout<<"插入成功\n\n"<<endl;
				} else{
					cout<<"插入失败\n\n"<<endl;
				}
				 break;
							
			case 4:
				//删除功能 
				cout<<"请输入你要删除的位置"<<endl;
				cin>>i;
				ListDelete(L, i, e);
				break;
					
			case 5:
				//查询数据 
				cout<<"请输入你要查询的数据"<<endl;
				cin>>e;
				 
				i = LocateElem(L, e);
				if(i != -1){
					cout<<"你查询的数据是第"<<i<<"个位置\n\n"<<endl;
					
				}else{
					cout<<"你查询的数据不存在\n\n"<<endl; 
				}
				break;
				
			case 6:
				//判断线性表是否为空 
				if(!ListEmpty(L)){
					cout<<"线性表为空表\n\n"<<endl;
				}else{
					cout<<"线性表不为空\n\n"<<endl;
				}
				break;
				
		
				
			
			
		}
		
		cout<<"		0-----退出,并销毁线性表\n"<<endl;
		cout<<"		1-----重新初始化线性表\n"<<endl;
		cout<<"		2-----打印线性表\n"<<endl;
		cout<<"		3-----插入数据\n"<<endl;
		cout<<"		4-----删除某个数据\n"<<endl;
		cout<<"		5-----查询数据的位置\n"<<endl;
		cout<<"		6-----判断线性表是否为空\n"<<endl;
		
		
		cout<<"请输入你的操作"<<endl;
		
		
		//控制操作输入 
		while(1){
			//输入操作方式 
			cin>>n;
			cout<<endl;
			
			if(n>6 || n < 0){
				cout<<"你输入的有问题,请重新输入"<<endl;
			}else{
				break;
			}
		} 
	}
	
	
	return 0;
}


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
数据结构及算法C语言蔚敏。VC6运行通过,这个是源代码CPP文件,包含顺序线性、单链的插入、删除、查找。包含监视哨查找,折半查找,直接插入排序,希尔排序,冒泡排序,快速排序,选择排序。里面包含超大量的注释,包括对VC6的语法解释和算法的解释和理解。具体效果可以看 http://download.csdn.net/detail/changechange/8236207 我上次上传的 EXE demo,带输入输出,能与用户交互。在运行的时候会把整个运算的过程都显示出来。摘录代码如下://数据结构 上机第一次 栈应用,转换进制题目。 //请用每一个cpp作为一个项目,不要把多个cpp放到同一个项目中,因为我为每个cpp都定义了main。 //这个教材上没有,只能自己补全了 #include using namespace std; //p10 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; //下面这行书上没找到,自己补的。 typedef int SElemType; //p46书上的。 #define STACK_INIT_SIZE 100 //定义最初申请的内存的大小 #define STACKINCREMENT 10 //每一次申请内存不足的时候扩展的大小 typedef struct { SElemType *base; //在栈构造之前和销毁之后,base的值为null SElemType *top; //栈顶指针 int stacksize; //当前已分配的存储空间,以元素为单位 }SqStack; //定义顺序栈别名。 //构造一个空栈S Status InitStack(SqStack &S) { // 参考之前的 List.cpp中队malloc的解释。 S.base=(SElemType *) malloc(STACK_INIT_SIZE * sizeof (SElemType)); if (!S.base) exit(OVERFLOW); // 存储分配失败 S.top = S.base; //初始时栈顶等于栈低 S.stacksize = STACK_INIT_SIZE; //初始栈容量 return OK; } //end of InitStack //插入元素e为新的栈顶元素 Status Push(SqStack &S, SElemType e) { if (S.top - S.base >= S.stacksize) // 栈满,追加存储空间 { S.base = (SElemType *) realloc(S.base, //原栈底指针 (S.stacksize + STACKINCREMENT) * sizeof (SElemType)); //新大小 if (!S.base) exit(OVERFLOW); // 存储分配失败 //调整栈顶的位置 S.top = S.base + S.stacksize; //修改栈大小为新的大小 S.stacksize += STACKINCREMENT; } //*符号为求值符。 *S.top++ = e; //先把e压入栈顶,S.top再增1指向栈顶元素e的下一个位置 return OK; } //end of Push // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR Status Pop(SqStack &S, SElemType &e) { if (S.top == S.base) //栈顶=栈底示空栈,如果空栈,报错 return ERROR; e = *--S.top; //S.top先减1指向栈顶元素,再取值,赋值给e用于返回。 return OK; } //这个书上没有,自己加的 //书上没有,自己写的,用来处理每一个元素的data Status PrintEach(SElemType e){ cout<<e<<";"; return OK; } //从栈底依次对栈中每个元素调用函数visit(),主要用于输出 //关于visit的解释参考 List.cpp Status StackTraverse(SqStack &S,Status(* visit)(SElemType)){ int l = S.top-S.base; S.top=S.base; //从栈底开始输出 for(int i=0;i<l;i++) //用长度控制输出的个数 { (* visit)(*(S.top)++); } return OK; } // 若栈S为空栈,则返回TRUE,否则返回FALSE Status StackEmpty(SqStack &S) { //栈顶指针S.top是否等于栈底指针S.base是判断栈是否为空的条件 if (S.top == S.base) return TRUE; else return FALSE; } //p48 进行进制转换 //对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 void conversion() // 算法3.1 { SqStack S; //声明顺序栈S unsigned int N; //unsigned 示无符号,unsigned int 从0开始,非负整数 SElemType e; //栈元素e InitStack(S); //构造空栈S cout<=0)"<<endl; scanf("%d",&N); //获取用户的输入,%d 是对数据的格式化。 &N 示对变量 N 引用。 while (N) //只要n不等于0就循环。从n为用户输入的十进制数开始,一直到n等于0为止 { Push(S, N % 8); //n除以8的余数(8进制的低位)入栈 //先压入的余数是八进制的低位,后压入的余数是八进制的高位 N = N / 8; //令n等于n整除以8的商,进入下轮循环 } //我自己加的,先输出一遍栈内的内容。 cout<<"从底到顶输出栈内的内容,用于调试:"; StackTraverse(S,PrintEach); cout<<endl; //循环结束时,n等于0 while (!StackEmpty(S)) //只要栈S没pop空就不断循环,直到pop出栈底元素栈S为空为止 { Pop(S, e); //pop出栈顶元素且赋值给e进行返回 //先pop出的是八进制的高位,后pop出的是八进制的低位 printf("%d", e); //依次输出e } //循环结束时,栈S为空 cout<<endl; } int main() { for(int i=0;i<4;++i) conversion(); return 0; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圣诞节不感冒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值