#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义元素类型
typedef struct {
char* name; //元素名
int value; //元素值
}Elem;
//单链表结构。定义元素结点类型:
typedef struct LNode{
Elem* data; //每个结点存放一个元素指针(数据域)
LNode* next; //指针指向下一个结点(指针域)
}LNode, *LinkList;
/*上述定义方式等价于:
typedef struct LNode LNode; //强调这是一个结点
typedef struct LNode *LinkList; //强调这是一个链表
*/
/****************************************定义元素操作*****************************************/
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(LNode* p); //打印元素信息
/****************************************创建、初始化和释放*****************************************/
LinkList createList(); //创建一个空链表并初始化
void releaseList(LinkList list); //释放线性表开辟的内存空间
/*************************************************增*************************************************/
bool headInsertList(LinkList list, Elem* e); //头插。在表头位置插入元素e。插入成功返回true,失败返回false
bool tailInsertList(LinkList list, Elem* e); //尾插。在表尾插入元素e。插入成功返回true,失败返回false
bool insertList(LinkList list, int pos, Elem* e); //指定位置插入元素。在单链表的第pos(1≤pos≤n)个位置插入元素e,成功返回true,失败返回false。
/*************************************************删*************************************************/
bool headDeleteList(LinkList list); //头删,删除表中的第1个元素。删除成功返回true,失败返回false
bool tailDeleteList(LinkList list); //尾删,删除表尾元素。删除成功返回true,失败返回false
bool deleteList(LinkList list, int pos); //指定位置删除元素。删除单链表list的第pos(1≤pos≤n)个数据元素。删除成功返回true,删除失败返回false。
bool clearList(LinkList list); //清空单链表。清空成功返回true,清空失败返回false。
/*************************************************改*************************************************/
bool alterList(LinkList list, int pos, char* newName, int newValue); //修改表中第pos(1≤pos≤n)个元素的值。修改成功返回true,修改失败返回false。
/*************************************************查*************************************************/
int locateElemPosition(LinkList list, char* name, int value); //根据元素名和元素值来查找元素结点在链表中的位置,如果有,返回位置pos(1≤pos≤n);如果没有,返回-1
LNode* locateElemPointer(LinkList list, char* name, int value); //根据元素名和元素值来查找元素结点指针,并返回;如果找不到,就返回NULL
bool isNotLegalPosition(LinkList list, int pos); //判断插入位置pos(1≤pos≤n)是否非法。非法则返回true,合法则返回false。
bool isEmpty(LinkList list); //判断单链表是否为空
LNode* getPointer(LinkList list, int pos); //返回指向第pos(1≤pos≤n)个元素结点的指针
int listLength(LinkList list); //求单链表的长度
void printList(LinkList list); //打印单链表
/*************************************************其它*************************************************/ /*
LinkList mergeList(LinkList list1, LinkList list2); //合并单链表。将list2加入到list1后面,返回合并后的新表。合并失败返回NULL
LinkList reverseList(LinkList list); //反转单链表元素,返回一个倒序的新表。反转失败返回NULL。
LinkList reversePartList(LinkList list, int startPos, int endPos); //反转部分单链表元素。反转从第startPos到第endPos的元素,包括startPos和endPos位置的元素。反转失败返回NULL。
int sameElemCount(LinkList list1, LinkList list2); //返回两个单链表中相同元素个数
bool alterListFromOther(LinkList list, int pos, LinkList otherList, int otherPos); //将表list的第pos个元素设置设置为与表otherList的第otherPos个元素相同
*/
void main() {
LinkList list = createList(); //创建一个带头结点的空链表并初始化
printf("/*************************************************增*************************************************/\n");
//头插法插入元素
headInsertList(list, createElem("a", 1));
printf("头插法插入元素:(a,1),操作后表为:"); printList(list);
//指定索引处插入元素
insertList(list, 2, createElem("b", 2));
printf("在第2个位置插入元素:(b,2),操作后表为:"); printList(list);
insertList(list, 2, createElem("c", 3));
printf("在第2个位置插入元素:(c,3),操作后表为:"); printList(list);
printf("单链表的长度为:%d\n",listLength(list));
//尾插法插入元素
tailInsertList(list, createElem("d", 4));
printf("尾插法插入元素:(d,4),操作后表为:"); printList(list);
printf("/*************************************************查*************************************************/\n");
printf("元素(c,3)在顺序表中的位置为:%d\n", locateElemPosition(list, "c", 3));
printf("顺序表中第2个元素为:"); printElem(getPointer(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);
}
//指定元素名和元素值创建一个新元素
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(LNode* p) {
printf("(%s, %d)", p->data->name, p->data->value);
}
/****************************************创建、初始化和释放*****************************************/
//创建一个空链表并初始化
LinkList createList() {
LinkList list = (LinkList) malloc(sizeof(LNode)); //定义头结点
list->data = NULL; //数据域为NULL,表示不存放数据
list->next = NULL;
return list;
}
//释放线性表开辟的内存空间
void releaseList(LinkList list) {
LNode* p = list;
while(list != NULL) {
p = list; //定位要释放的结点
list = list->next;
//释放内存,注意根据条件释放多个位置的内存
if(p->data != NULL) {
if(p->data->name != NULL) {
free(p->data->name); //释放元素名指针
}
free(p->data); //释放元素指针
}
free(p); //释放结点指针
}
}
/*************************************************查*************************************************/
//求单链表的长度
int listLength(LinkList list) {
LNode* p = list;
int length = 0;
while(p->next != NULL) {
length += 1; //这个结点的位置为i
p = p->next; //往后找一个结点
}
return length;
}
//判断插入位置pos(1≤pos≤n)是否非法。非法则返回true,合法则返回false。?
bool isNotLegalPosition(LinkList list, int pos) {
if(pos < 1 || pos > listLength(list) + 1) {
return true;
}
return false;
}
//判断单链表是否为空
bool isEmpty(LinkList list) {
if(list == NULL || list->next == NULL) {
return true;
}
return false;
}
//返回指向第pos个元素结点的指针
LNode* getPointer(LinkList list, int pos) {
if(isNotLegalPosition(list, pos)) {
return NULL;
}
LNode* p = list;
//找到第pos个结点p,并返回指针
for(int i = 0; i < pos; i++) {
p = p->next;
}
return p;
}
//打印单链表
void printList(LinkList list) {
LNode* p = list;
while(p ->next != NULL) {
p = p->next; //定位结点
printf("(%s , %d) ", p->data->name, p->data->value);
}
printf("\n");
}
//根据元素名和元素值来查找数据元素e在表中的位置,如果有,返回位置pos(1≤pos≤n);如果没有,返回-1
int locateElemPosition(LinkList list, char* name, int value) {
if(list == NULL || name == NULL) {
return -1;
}
LNode* p = list;
int count = 0;
bool flag = false; //标识是否找到
while(p->next != NULL) {
p = p->next;
count += 1;
if(strcmp(p->data->name, name) == 0 && p->data->value == value) {
flag = true;
break;
}
}
return flag ? count : -1;
}
//根据元素名和元素值来查找元素结点指针,并返回;如果找不到,就返回NULL
LNode* locateElemPointer(LinkList list, char* name, int value) {
int pos = locateElemPosition(list, name, value);
return pos == -1 ? NULL : getPointer(list, pos);
}
/*************************************************增*************************************************/
//头插。在表头位置插入元素e。插入成功返回true,失败返回false
bool headInsertList(LinkList list, Elem* e) {
LNode* node = (LNode*) malloc(sizeof(LNode));
if(node == NULL || e == NULL) {
return false; //申请内存失败或元素不存在返回false
}
//给结点赋值
node->data = e;
//插入链表的头部
node->next = list->next;
list->next = node;
return true;
}
//指定位置插入元素。在单链表的第pos(1≤pos≤n)个位置插入元素e,成功返回true,失败返回false。
bool insertList(LinkList list, int pos, Elem* e) {
//判断pos是否小于1或者大于链表长度+1
if(isNotLegalPosition(list, pos)) {
return false;
}
//找到第pos-1个元素结点p
LNode* p = getPointer(list, pos - 1);
//创建新结点并赋值
LNode* newNode = (LNode*) malloc(sizeof(LNode));
newNode->data = e;
//将新结点插入到单链表中
newNode->next = p->next;
p->next = newNode;
return true;
}
//尾插。在表尾插入元素e。插入成功返回true,失败返回false
bool tailInsertList(LinkList list, Elem* e) {
if(list == NULL || e == NULL) {
return false;
}
//返回最后一个元素结点的指针
LNode* p = getPointer(list, listLength(list));
//在这个结点后插入新结点
LNode* newNode = (LNode*) malloc(sizeof(LNode));
newNode->data = e; //给结点数据域赋值
newNode->next = p->next;
p->next = newNode;
return true;
}
/*************************************************删*************************************************/
//头删,删除表中的第1个元素。删除成功返回true,失败返回false
bool headDeleteList(LinkList list) {
if(isEmpty(list)) {
return false;
}
LNode* p = list->next;
list->next = p->next;
//释放该结点
free(p->data->name); //释放结点名
free(p->data); //释放元素
free(p); //释放结点
return true;
}
//尾删,删除表尾元素。删除成功返回true,失败返回false
bool tailDeleteList(LinkList list) {
if(list == NULL) {
return false;
}
LNode* p = getPointer(list, listLength(list) - 1); //获取最后一个结点前面的结点的指针。也可以自己实现。
LNode* s = p->next;
p->next = s->next;
//释放结点s
free(s->data->name);
free(s->data);
free(s);
return true;
}
//指定位置删除元素。删除单链表list的第pos(1≤pos≤n)个数据元素。删除成功返回true,删除失败返回false。
bool deleteList(LinkList list, int pos) {
if(list == NULL) {
return false;
}
if(isNotLegalPosition(list, pos)) {
return false;
}
LNode* p = getPointer(list, pos -1); //获取第pos -1 个结点的指针
LNode* s = p->next; //s为要删除的结点
p->next = s->next;
//释放结点s
free(s->data->name);
free(s->data);
free(s);
return true;
}
//清空单链表。清空成功返回true,清空失败返回false。
bool clearList(LinkList list) {
if(list == NULL) {
return false; //list没有头结点
}
LNode* p = list->next; //定位要删除的结点
while(p != NULL) {
list->next = p->next; //头结点指向p的下一个
//删除p指向的结点
free(p->data->name);
free(p->data);
free(p);
//p重新指向list的下一个结点
p = list->next;
}
return true;
}
/*************************************************改*************************************************/
//修改表中第pos(1≤pos≤n)个元素的值。修改成功返回true,修改失败返回false。
bool alterList(LinkList list, int pos, char* newName, int newValue) {
if(list == NULL || newName == NULL) {
return false;
}
if(isNotLegalPosition(list, pos)) {
return false;
}
LNode* p = getPointer(list, pos);
alterElem(p->data, newName, newValue);
return true;
}