线性表的顺序存储结构

顺序存储结构封装需要三个属性:

1.存储空间的起始位置,数组data,它的存储位置就是线性表存储空间的存储位置
2.线性表的最大存储容量,数组的长度MaxSize
3.线性表的当前长度:length

当前长度与数组长度区别:数组长度就是该顺序表的总长度,如果不进行扩容的话,就是不变的。而当前长度在数据的变化中,就会发生相应的变化。

PS:线性表是正常的读数方法,一下标1开始的。

存储时间性能:O(1)

性能:存取以及读取不管是在哪个位置,其时间复杂度都是O(1),而在插入还是删除其时间复杂度都是O(n)

结论:比较适合数据的存取而不适合经常性增删的情况。

顺序存储结构的优缺点

1.优点:
- 无须为表示表中元素之间的逻辑关系而增加额外的存储空间
- 可以快速的存取表中任意位置的元素。
2.缺点:
- 插入以及删除操作需要移动大量的元素。
- 当线性表长度变化较大时,难以确定存储空间的容量。
- 容易造成存储空间的碎片。

具体代码的实现:

// 头文件部分,进行常量参数初始化
#define LIST_INT_SIZE 10  //线性顺序表初始动态分配内存大小
#define INCREAMENT 2    //线性表扩容一次性增量
#define    OK      1
#define   ERROW   -1
#define  OVERFLOW -2


#include<stdio.h>
#include <stdlib.h>//malloc函数包含在其中


typedef int Elemtype;     //线性表的数据类型
typedef int Status;      // 状态数据类型
// 顺序表存储结构定义
typedef struct {
	Elemtype *elem;      //定义线性表内数据元素的数据类型
	int length;          //表当前长度
	int listsize;        //表当前空间容量大小
} SqList;                //表名
// 初始化一个顺序表
Status InitList(SqList &L) {
	L.elem = (Elemtype *)malloc(LIST_INT_SIZE * sizeof(Elemtype)) ;//动态分配内存,分配后可以将l.elem作为数组使用
	if(!L.elem) {                    //对内存分配的结果判断
		exit(OVERFLOW);
	}   //这个地方可以去查一下资料
//	if(L.elem == NULL) {
//		printf("分配内存失败")
//		exit(1);
//	}
	//关于内存分配结果的判断,又该如何去进行判断
	//这种方法进行判断又是否正确
	L.length = 0;                      //对表长初始化归0
	L.listsize = LIST_INT_SIZE;
	return OK;
}

// 创建一个顺序表
Status CreateList(SqList &L) {
	int i;
	InitList(L);
	printf("请输入元素个数:\n");
	scanf("%d",&L.length);
	printf("\n请输入您要输入的元素\n");
	for(i=0; i<L.length; i++) {
		scanf("%d",&L.elem[i]);
	}
	printf("顺序表已创建成功,打印表请选择功能 *3\n");
	return OK;
}
// 顺序表的遍历
Status TraverseList(SqList &L) {
	int i;
	printf("表中元素为:\n");
	for(i=0; i<L.length; i++)
		printf("%d  ",L.elem[i]);
	printf("\n\n顺序表输出完毕!\n");
}
//顺序表的插入
// 表L 位置 i  Elemtype  要插入的元素
Status InsertList(SqList &L,int i,Elemtype e) {
	int* newbase;
	int j;
	if(i < 1 ||i > L.length+1) {   // 判断所要插入的位置
		return ERROW;
	}
	if(L.length>=L.listsize) {
		newbase = (Elemtype*)realloc(L.elem,(L.listsize+INCREAMENT)*sizeof(Elemtype));
		if(!newbase) {
			exit(OVERFLOW);
		}
		L.elem = newbase;
		L.listsize += INCREAMENT;
	}
	for(j = L.length-1; j>i-1; j--) {
		L.elem[j+1]=L.elem[j];
	}
	L.elem[i-1] = e;
	L.length++;
	return OK;
}
//删除指定位置元素并返回出来
Status deleteListElem(SqList &L,int i) {
	Elemtype e;
	int j;
	if(i<1 || i>L.length) {
		return ERROW;
	}
	e = L.elem[i-1];
	for(j = i-1 ; j<=L.length; j++) {
		L.elem[j] = L.elem[j+1];
	}
	L.length--;
	return e;
}
//判断一个值是不是线性表中的元素并返回第几个元素
Status ifElemExit(SqList &L,Elemtype e) {
	int i = 0;
	for(; i<L.length; i++) {
		if(e==L.elem[i])
			break;
	}
	if(i>=L.length) {
		return ERROW;
	} else {
		return i;
	}
}

//输出一个位置的数据元素
Status GetElem(SqList &L,int i) {
	if(i<1||i>L.length) {
		return ERROW;
	}
	return L.elem[i-1];
}
//根据元素的值来进行删除
Status deleteElemByR(SqList &L,Elemtype e) {
	int i = 0;
	i = ifElemExit(L,e);
	if(i==-1) {
		printf("该值不再线性表中:");
		return ERROW;
	} else {
		deleteListElem(L,i+1);
		printf("删除成功!删除的是位置为%d,值为%d",i,e);
		return OK;
	}
}
//将线性表进行递减排序操作
Status SortByMao(SqList &L) {
	Elemtype e;
	for(int j=0; j<L.length; j++) {
		for(int i=0; i<L.length-i-j; i++) {
			if(L.elem[i]<L.elem[i+1]) {
				e = L.elem[i];
				L.elem[i] = L.elem[i+1];
				L.elem[i+1]=e;
			}
		}
	}
}
void UnionTwo(SqList &la,SqList &lb) {
	
	int la_length = la.length;
	int lb_length = lb.length;
	for(int i=1;i<=lb.length;i++){
		Elemtype e= GetElem(Lb,i);
		if(ifElemExit(La,e)==-1){
			InsertList(La,la_length,e);
			la_length++;
			la.length++;
		}
	}
	
	
	
} 


/***主提示输出函数***/


void printlin() {
	printf("\n");
	printf("\t\t\t线性顺序表基本操作学习系统\n");
	printf("\t\t\t      ***主菜单***\n\n");
	printf("\t\t\t    *1 创建一个顺序表\n");
	printf("\t\t\t    *2 定位输出一个数据元素\n");
	printf("\t\t\t    *3 输出顺序表中所有元素\n");
	printf("\t\t\t    *4 定位插入一个数据元素\n");
	printf("\t\t\t    *5 定位删除一个数据元素\n");
	printf("\t\t\t    *6 定值删除一个数据元素\n");
	printf("\t\t\t    *7 清空顺序表\n");
	printf("\t\t\t    *8 销毁顺序表\n");
	printf("\t\t\t    *9 对表内数据元素进行非递减排序\n");
	printf("\t\t\t    *0 结束程序\n");
}
//清空线性表
void clearList(SqList &L) {
	if(L.length!=0) {
		L.length = 0;   //由于顺序表的用得是与数组一样的内存空间,
		//所以标的清空只要将表长归零即可,由此可见,表长是线性表非常重要的部分
	}
}
//销毁线性表
void destoryList(SqList &L) {
	if(L.length!=0) {
		free(L.elem);
		L.elem = NULL;//使用free后就需要对元素进行赋空操作
	}

}



int main() {
	int i,j,k;
	Elemtype e;
	SqList L;
	L.length=0;
	printf("编写此程序目的是自我学习线性表顺序表\n");
	printlin();
	while(1) {
		int t;
		scanf("%d",&t);
		if(t!=0)
			if(t==1||L.length!=0) {
				switch(t) {
					case 1:
						if(L.length!=0) {
							printf("顺序表已存在,是否重新创建顺序表?\n");
							printf("*1 是   *2 否\n");
							scanf("%d",&i);
							if(i==1)
								CreateList(L);
						} else
							CreateList(L);
						break;
					case 0:
						break;
					case 3:
						TraverseList(L);
						break;
					case 7:
						clearList(L);
						printf("清空完毕,返回主菜单\n\n");
						break;
					case 4:
						printf("输入要插入的位置\n");
						scanf("%d",&i);
						printf("请输入要插入的数据\n");
						scanf("%d",&j);
						k=InsertList(L,i,j);
						if(k==-1) {
							printf("插入位置不合法,插入数据操作失败!\n\n");
						} else
							printf("插入数据成功\n\n");
						break;
					case 5:
						printf("请输入要删除数据位置\n");
						scanf("%d",&i);
						e = deleteListElem(L,i);
						printf("删除掉的元素是第%d个位置,它的值是%d",i,e);
						break;
					case 2:
						printf("请输入要需要得到数据位置:");
						scanf("%d",&i);
						e = GetElem(L,i);
						printf("第%d个位置上的元素值为:%d",i,e);
						break;
					case 6:
						printf("请输入需要删除的值:");
						scanf("%d",&e);
						deleteElemByR(L,e);
						break;
					case 8:
						destoryList(L);
						printf("销毁成功!");
						break;
					case 9:
						SortByMao(L);
						break;
					default: {
						printf("输入有误,可以重新选择,退出按0!\n");
					}
				}
			} else
				printf("顺序表未创建或已清空或销毁,请先创建顺序表\n");
		system("pause");
		system("CLS");
		printlin();
		if(t==0)
			break;
	}
	return 0;
}


posted @ 2017-07-21 21:56  startor  阅读(531)  评论(1编辑  收藏  举报