#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)