数据结构(C语言)之——顺序表

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//定义元素类型
typedef struct {	
	char* name; //元素名
	int value; //元素值
}Elem;
Elem* createElem(char* name, int value); //指定元素名和元素值创建一个新元素
bool alterElem(Elem* e, char* newName, int newValue); //修改元素的值为新的值
bool copyElem(Elem* eCopy, Elem* e); //将元素e的值复制给eCopy。(eCopy仅为一个指针)
bool isSameElem(Elem* e1, Elem* e2); //判断两个元素的所有属性是否相同(元素名和元素值都相同)
void printElem(Elem* e); //打印元素信息

//线性表结构
typedef struct {
    Elem** data;   //用数组存储线性表中的元素
    int length;		//顺序表的当前长度
	int maxSize;		//顺序表的最大长度
}SeqList;

/****************************************创建、初始化和释放*****************************************/
SeqList* createList(int maxSize); //创建一个最大长度为maxSize的空表并初始化
void releaseList(SeqList* list); //释放线性表开辟的内存空间
/*************************************************增*************************************************/
bool headInsertList(SeqList* list, Elem* e); //头插。在表头位置插入元素e。插入成功返回true,失败返回false
bool tailInsertList(SeqList* list, Elem* e); //尾插。在表尾插入元素e。插入成功返回true,失败返回false
bool insertList(SeqList* list, int pos, Elem* e); //指定位置插入元素。在顺序表的第pos(1≤pos≤n)个位置插入元素e,成功返回true,失败返回false。
/*************************************************删*************************************************/
bool headDeleteList(SeqList* list); //头删,删除表中的第1个元素。删除成功返回true,失败返回false
bool tailDeleteList(SeqList* list); //尾删,删除表尾元素。删除成功返回true,失败返回false
bool deleteList(SeqList* list, int index); //指定位置删除元素。删除顺序表list的第pos(1≤pos≤n)个数据元素。删除成功返回true,删除失败返回false。
bool clearList(SeqList* list); //清空顺序表。清空成功返回true,清空失败返回false。
/*************************************************改*************************************************/
bool alterList(SeqList* list, int pos, char* newName, int newValue); //修改表中第pos(1≤pos≤n)个元素的值。修改成功返回true,修改失败返回false。
/*************************************************查*************************************************/
int locateElem(SeqList* list, char* name, int value); //根据元素名和元素值来查找数据元素e在表中的位置,如果有,返回位置pos(1≤pos≤n);如果没有,返回-1
Elem* getElem(SeqList* list, int pos); //返回顺序表中第pos(1≤pos≤n)个元素的Elem指针。查找失败返回NULL。
bool isNotLegalPosition(SeqList* list, int pos); //判断插入位置pos(1≤pos≤n)是否非法。非法则返回true,合法则返回false。
bool isEmpty(SeqList* list); //判断顺序表是否为空
bool isFull(SeqList* list); //判断顺序表是否已满
int listLength(SeqList* list); //求顺序表的长度
void printList(SeqList* list); //打印顺序表
/*************************************************其它*************************************************/
SeqList* mergeList(SeqList* list1, SeqList* list2); //合并顺序表。将list2加入到list1后面,返回合并后的新表。合并失败返回NULL
SeqList* reverseList(SeqList* list); //反转顺序表元素,返回一个倒序的新表。反转失败返回NULL。
SeqList* reversePartList(SeqList* list, int startPos, int endPos); //反转部分顺序表元素。反转从第startPos到第endPos的元素,包括startPos和endPos位置的元素。反转失败返回NULL。
int sameElemCount(SeqList* list1, SeqList* list2); //返回两个顺序表中相同元素个数
bool alterListFromOther(SeqList* list, int pos, SeqList* otherList, int otherPos); //将表list的第pos个元素设置设置为与表otherList的第otherPos个元素相同


void main() {
	SeqList* list = createList(100);
	printf("/*************************************************增*************************************************/\n");
	//头插法插入元素
	headInsertList(list, createElem("a", 1));
	printf("头插法插入元素:(a,1),操作后表为:");printList(list);
	//指定索引处插入元素
	insertList(list, 2, createElem("b", 2));
	printf("在第二个位置插入元素:(b,2),操作后表为:");printList(list);
	insertList(list, 3, createElem("c", 3));
	printf("在第三个位置插入元素:(c,3),操作后表为:");printList(list);
	//尾插法插入元素
	tailInsertList(list, createElem("d", 4));
	printf("尾插法插入元素:(d,4),操作后表为:");printList(list);
	printf("顺序表的长度为:%d\n",listLength(list));

	printf("/*************************************************查*************************************************/\n");
	printf("元素(c,3)在顺序表中的位置为:%d\n", locateElem(list, "c", 3));
	printf("顺序表中第2个元素为:"); printElem(getElem(list, 2)); printf("\n");
	printf("/*************************************************改*************************************************/\n");
	alterList(list, 4, "x", 100);
	printf("修改顺序表中第4个元素的值为(x, 100),操作后表为:"); printList(list); 
	
	printf("/*************************************************删*************************************************/\n");
	//头删法删除元素
	headDeleteList(list);
	printf("头删法删除元素,操作后表为:");printList(list);
	//指定索引处删除元素
	deleteList(list, 2);
	printf("删除第2个元素,操作后表为:");printList(list);
	//尾删法删除元素
	tailDeleteList(list);
	printf("尾删法删除元素,操作后表为:");printList(list);
	//清空顺序表
	clearList(list);
	printf("清空顺序表,操作后表为:");printList(list);
	printf("顺序表的长度为:%d\n",listLength(list));
	releaseList(list);

	printf("/*************************************************其它*************************************************/\n");
	//合并表
	printf("表1:(a,1) (b,2) (c,3);");
	SeqList* list1 = createList(100);
	tailInsertList(list1, createElem("a", 1));
	tailInsertList(list1, createElem("b", 2));
	tailInsertList(list1, createElem("c", 3));
	printf("表2:(c,3) (d,4) (e,5); ");
	SeqList* list2 = createList(100);
	tailInsertList(list2, createElem("c", 3));
	tailInsertList(list2, createElem("d", 4));
	tailInsertList(list2, createElem("e", 5));
	printf("表1和表2相同元素个数为:%d", sameElemCount(list1, list2));
	SeqList* list12 = mergeList(list1, list2);
	printf("\n合并后:"); printList(list12);
	SeqList* list21 = reverseList(list12); printf("反转所有元素,反转后:"); printList(list21);
	printf("将合并表的第3个元素设置位反转表的第2个元素,设置后合并表为:"); alterListFromOther(list12, 3, list21, 2); printList(list12);
	printf("合并表和反转表相同元素个数为:%d\n", sameElemCount(list12, list21));
	SeqList* list21_part = reversePartList(list12, 2, 5); 
	printf("反转第2到第5的元素,反转后:"); printList(list21_part); printf("\n");
	releaseList(list1);
	releaseList(list2);
	releaseList(list12);
	releaseList(list21);
	releaseList(list21_part);
}

//指定元素名和元素值创建一个新元素
Elem* createElem(char* name, int value) { 
	Elem* e = (Elem*) malloc(sizeof(Elem));
	if(e == NULL) { //开辟失败则直接返回
		printf("创建元素失败!\n");
		return NULL;
	}
	e->name = (char*) malloc(sizeof(char)*(strlen(name)+1));
	strcpy(e->name, name);
	e->value = value;
	return e;
}

//修改元素的值为新的值。修改成功返回true,修改失败返回false。
bool alterElem(Elem* e, char* newName, int newValue) {
	if(e == NULL || newName == NULL) {
			return false;
	}
	free(e->name);
	e->name = (char* ) malloc(sizeof(char)*(strlen(newName)+1));
	strcpy(e->name, newName);
	e->value = newValue;
	return true;
}

//将元素e的值复制给eCopy。(eCopy仅为一个指针)
bool copyElem(Elem* eCopy, Elem* e) {
	eCopy->name = (char*) malloc(sizeof(char)*(strlen(e->name)+1)); //注意加1,因为有'\0'
	if(eCopy->name == NULL) {
		return NULL;
	}
	strcpy(eCopy->name, e->name); //复制元素名
	eCopy->value = e->value; //复制元素值
	return true;
}

//判断两个元素属性是否相同(元素名和元素值都相同)
bool isSameElem(Elem* e1, Elem* e2) {
	//如果有一个是NULL,返回false
	if(e1 == NULL || e2 == NULL) {
		return false;
	}
	return strcmp(e1->name, e2->name) == 0 ?  e1->value == e2->value : false;
}

//打印元素信息
void printElem(Elem* e) {
	printf("(%s, %d)", e->name, e->value);
}

//创建一个最大长度为maxSize的空表并初始化
SeqList* createList(int maxSize) {
	SeqList* list = (SeqList *) malloc(sizeof(SeqList)); //开辟线性表内存空间
	list->data = (Elem **) malloc(sizeof(Elem*) * maxSize); //开辟元素指针数组的内存空间
	//给元素指针数组的每一个元素指针指向一个元素空间
	for(int i = 0; i < maxSize; i++) {
		list->data[i] = (Elem*) malloc(sizeof(Elem));
	}
	list->length = 0; //线性表长度初始化为0
	list->maxSize = maxSize; //设置最大长度
	return list;
}

//释放线性表开辟的内存空间
void releaseList(SeqList* list) {
	//释放元素指针数组的各个指针所指的内存Elem
	for(int i = 0; i < list->length; i ++) {
		free(list->data[i]->name); //释放元素名指针所指空间(char* name)
		free(list->data[i]); //释放元素指针所指空间(*Elem list->data[i])
	}
	free(list->data); //释放元素指针数组所占的内存(Elem** data)
	free(list); //释放顺序表所占内存(SeqList* list)
}

//头插,在表头位置插入元素e。插入成功返回true,失败返回false
bool headInsertList(SeqList* list, Elem* e) {
	//判断该表是否已满
	if(isFull(list)) {
		return false;
	}
	//将所有元素后移
	for(int i = list->length-1; i >= 0; i--) {
		list->data[i+1] = list->data[i];
	}
	list->data[0] = e; //在头部插入新的元素
	list->length += 1; //线性表长度加1
	return true;
}

//头删,删除表中的第一个元素。删除成功返回true,失败返回false
bool headDeleteList(SeqList* list) {
	//判断该表是否为空
	if(isEmpty(list)) {
		return false;
	}
	//释放第0个元素指针所指内存
	free(list->data[0]);
	//将第1个至第n-1个元素依次前移一位
	for(int i = 1; i < list->length; i ++) {
		list->data[i-1] = list->data[i];
	}
	list->length -= 1; //顺序表长度减1
	return true;
}  

//尾插,在表尾插入元素e。插入成功返回true,失败返回false
bool tailInsertList(SeqList* list, Elem* e) {
	//判断该表是否已满
	if(isFull(list)) {
		return false;
	}
	list->data[list->length] = e; //在表尾插入元素
	list->length += 1; //顺序表长度加1
	return true;
}

//尾删,删除表尾元素。删除成功返回true,失败返回false
bool tailDeleteList(SeqList* list) {
	//判断该表是否为空
	if(isEmpty(list)) {
		return false;
	}
	//释放最后一个元素指针所指的内存
	free(list->data[list->length-1]);
	//将顺序表长度减1
	list->length -= 1;
	return true;
} 

//指定位置插入元素。在顺序表的第i个位置(1≤i≤n)插入元素e,成功返回true,失败返回false
bool insertList(SeqList* list, int pos, Elem* e) {
	//判断插入位置是否非法
	if(isNotLegalPosition(list, pos)) {
		return false;
	}
	//判断该表是否已满
	if(isFull(list)) {
		return false;
	}
	//将第i个及之后的元素后移
	int i;
	for(i = list->length-1; i >= pos-1; i--) {
		list->data[i+1] = list->data[i];
	}
	list->data[pos-1] = e; //在第pos位放入元素e
	list->length += 1; //线性表的长度加1
	return true;
}

//指定位置删除元素。删除顺序表list的第pos个数据元素。删除成功返回true,删除失败返回false。
bool deleteList(SeqList* list, int pos) {
	//判断删除位置是否非法
	if(isNotLegalPosition(list, pos)) {
		return false;
	}
	//判断该表是否为空
	if(isEmpty(list)) {
		return false;
	}
	//释放第pos个元素指针所指内存
	free(list->data[pos-1]);
	//删除该元素
	for(int i = pos; i < list->length; i++) {
		list->data[i-1] = list->data[i];
	}
	list->length -= 1;
	return true;
}

//清空顺序表。清空成功返回true,清空失败返回false。
bool clearList(SeqList* list) {
	//判断是否已经为空
	if(isEmpty(list)) {
		return true;
	}
	//清空元素指针数组的所有指针指向的元素Elem内存
	for(int i = 0; i < list->length; i++) {
		free(list->data[i]);
	}
	list->length = 0; //顺序表长度置为0
	return true;
}

//修改表中第pos个元素的值。修改成功返回true,修改失败返回false。
bool alterList(SeqList* list, int pos, char* newName, int newValue) {
	//判断index是否非法
	if(isNotLegalPosition(list, pos)) {
		return false;
	}
	//判断表是否为空
	if(isEmpty(list)) {
		return false;
	}
	return alterElem(list->data[pos-1], newName, newValue);
}

//根据元素名和元素值来查找第一个相同的数据元素e在表中的位置,如果有,返回位置pos;如果没有,返回-1
int locateElem(SeqList* list, char* name, int value) {
	//判断表是否为空
	if(isEmpty(list)) {
		return -1;
	}
	int result = -1;
	//strcmp(char* a,char* b)就可以比较出两字符串是否相等
	for(int i = 0; i < list->length; i++) {
		if(strcmp(list->data[i]->name, name) == 0 
			&& list->data[i]->value == value) {
			result = i+1;
			break;
		}
	}
	return result;
}

//返回顺序表中指向第pos个元素Elem指针。索引失败返回NULL。
Elem* getElem(SeqList* list, int pos) {
	//判断index索引是否非法
	if(isNotLegalPosition(list, pos)) {
		return NULL;
	}
	return list->data[pos-1];
}

//判断插入位置pos是否非法。非法则返回true,合法则返回false。
bool isNotLegalPosition(SeqList* list, int pos) {
	if(pos-1 < 0 || pos-1 > list->length) {
		return true;
	}else {
		return false;
	}
}

//判断顺序表是否为空
bool isEmpty(SeqList* list) {
	if(list->length == 0) {
		return true;
	}else {
		return false;
	}
}

//判断顺序表是否已满
bool isFull(SeqList* list) {
	if(list->length >= list->maxSize) {
		return true;
	} else {
		return false;
	}
}

//求顺序表的长度
int listLength(SeqList* list) {
	return list->length;
}

//打印顺序表
void printList(SeqList* list) {
	for(int i = 0; i < list->length; i++) {
		printElem(list->data[i]);
		printf(" ");
	}
	printf("\n");
}

//合并顺序表。将list2加入到list1后面,返回合并后的表。合并失败返回NULL
SeqList* mergeList(SeqList* list1, SeqList* list2) {
	//创建一个新表,最大长度是两表最大长度之和
	SeqList* newList = createList(list1->maxSize + list2->maxSize);
	//将list1的元素复制到新表中
	newList->length = list1->length + list2->length;
	int i;
	for(i = 0; i < list1->length; i++) {
		copyElem(newList->data[i], list1->data[i]);
	}
	//将list2的元素也复制到新表中
	for(i = list1->length; i < newList->length; i++) {
		copyElem(newList->data[i], list2->data[i - list1->length]);
	}
	return newList;
}

//反转顺序表元素,返回一个倒序的新表
SeqList* reverseList(SeqList* list) {
	SeqList* newList = createList(list->maxSize);
	if(newList == NULL) {
		return NULL;
	}
	newList->length = list->length;
	//将list表中所有元素复制过来
	for(int i = 0; i < list->length; i++) {
		copyElem(newList->data[i], list->data[list->length - i -1]);
	}
	return newList;
}

//反转部分顺序表元素。反转从第startPos到第endPos的元素,包括startPos和endPos位置的元素。反转失败返回NULL。
SeqList* reversePartList(SeqList* list, int startPos, int endPos) {
	SeqList* newList = createList(list->maxSize);
	if(newList == NULL) {
		return NULL;
	}
	if(startPos < 1 || endPos > list->length) {
		return NULL;
	}
	newList->length = list->length;
	int i;
	for(i = 0; i <= startPos - 2; i ++) {
		copyElem(newList->data[i], list->data[i]);
	}
	for(i = startPos - 1; i <= endPos - 1; i++) {
		copyElem(newList->data[i], list->data[(endPos -1) + (startPos - 1) - i]);
	}
	for(i = endPos; i < list->length; i++) {
		copyElem(newList->data[i], list->data[i]);
	}
	return newList;
}

//返回两个顺序表中相同元素个数
int sameElemCount(SeqList* list1, SeqList* list2) {
	int count = 0;
	for(int i = 0; i < list1->length; i++) {
		for(int j = 0; j < list2->length; j++) {
			if(isSameElem(list1->data[i], list2->data[j])) {
				count += 1;
				break;
			}
		}
	}
	return count;
}

//将表list的第pos个元素设置设置为与表otherList的第otherPos个元素相同
bool alterListFromOther(SeqList* list, int pos, SeqList* otherList, int otherPos) {
	if(list == NULL || otherList == NULL) {
		return false;
	}
	if(isNotLegalPosition(list, pos) || isNotLegalPosition(otherList, otherPos)) {
		return false;
	}
	alterElem(list->data[pos -1], otherList->data[otherPos - 1]->name, otherList->data[otherPos -1]->value);
	return true;
}
结果:
/*************************************************增*************************************************/
头插法插入元素:(a,1),操作后表为:(a, 1)
在第二个位置插入元素:(b,2),操作后表为:(a, 1) (b, 2)
在第三个位置插入元素:(c,3),操作后表为:(a, 1) (b, 2) (c, 3)
尾插法插入元素:(d,4),操作后表为:(a, 1) (b, 2) (c, 3) (d, 4)
顺序表的长度为:4
/*************************************************查*************************************************/
元素(c,3)在顺序表中的位置为:3
顺序表中第2个元素为:(b, 2)
/*************************************************改*************************************************/
修改顺序表中第4个元素的值为(x, 100),操作后表为:(a, 1) (b, 2) (c, 3) (x, 100)
/*************************************************删*************************************************/
头删法删除元素,操作后表为:(b, 2) (c, 3) (x, 100)
删除第2个元素,操作后表为:(b, 2) (x, 100)
尾删法删除元素,操作后表为:(b, 2)
清空顺序表,操作后表为:
顺序表的长度为:0
/*************************************************其它*************************************************/
表1:(a,1) (b,2) (c,3);表2:(c,3) (d,4) (e,5); 表1和表2相同元素个数为:1
合并后:(a, 1) (b, 2) (c, 3) (c, 3) (d, 4) (e, 5)
反转所有元素,反转后:(e, 5) (d, 4) (c, 3) (c, 3) (b, 2) (a, 1)
将合并表的第3个元素设置位反转表的第2个元素,设置后合并表为:(a, 1) (b, 2) (d, 4) (c, 3) (d, 4) (e, 5)
合并表和反转表相同元素个数为:6
反转第2到第5的元素,反转后:(a, 1) (d, 4) (c, 3) (d, 4) (b, 2) (e, 5)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值