实验题1:实现顺序表的各种基本运算的算法
题目描述
编写一个程序sqlist.cpp,实现顺序表的各种基本运算和整体建表异法(假设顺序表的元素类型 Elem Type为char),并在此基础上设计一个程序exp2-1.cpp完成以下功能。
(1)初始化顺序表L。
(2)依次插入元素a、b、c、d、e。
(3)输出顺序表L。
(4)输出顺序表L的长度。
(5)判断顺序表L 是否为空。
(6)输出顺序表L的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素的位置上插入元素f。
(9)输出顺序表L。
(10)删除顺序表L的第3个元素。
(11)输出顺序表L。
(12)释放顺序表L。
sqlist.cpp程序,其中包含如下函数:
· InitList(SqList*&L):初始化顺序表L。
· DestroyList(SqList*L):释放顺序表L。
· ListEmpty(SqList*L.):判断顺序表L是否为空表。
· ListLength(SqList *L):返回顺序表L中的元素个数。
· DispList(SqList*L):输出顺序表L。
·GetElem(SqList *L,int i,ElemType &e):获取顺序表L中的第i个元素。
· LocateElem(SqList *L.ElemType e):在顺序表L中查找元素e。
· ListInsert(SqList*&L,inti,ElemType e):在顺序表L中的第i个位置上插入元素c。
· ListDelete(SqList*&L,int i,ElemType &e):从顺序表L中删除第i个元素。
运行代码
sqlict.cpp
#include <iostream>
#include<malloc.h>
using namespace std;
#define MAXSIZE 100
typedef char ElemType;
typedef struct {
ElemType data[MAXSIZE];
int length;
} SqList;//表明表的类型
//整体建立顺序表
void GreateList(SqList* L, ElemType a[], int n) {
L = (SqList*)malloc(sizeof(SqList));
for (int i = 0; i < n; i++)
L->data[i] = a[i];
L->length = n;
}
// 初始化顺序表 L
void InitList(SqList* L) {
L = (SqList*)malloc(sizeof(SqList));
L->length = 0;
}
// 释放顺序表 L
void DestroyList(SqList*& L) {
delete L;
}
// 判断顺序表 L 是否为空表
bool ListEmpty(SqList* L) {
return L->length == 0;
}
// 返回顺序表 L 中的元素个数
int ListLength(SqList* L) {
return L->length;
}
// 输出顺序表 L
void DispList(SqList* L) {
for (int i = 0; i < L->length; i++) {
cout << L->data[i] << " ";
}
cout << endl;
}
// 获取顺序表 L 中的第 i 个元素
bool GetElem(SqList* L, int i, ElemType& e) {
if (i < 1 || i > L->length) {
return false;
}
e = L->data[i - 1];
return true;
}
// 在顺序表 L 中查找元素 e
int LocateElem(SqList* L, ElemType e) {
for (int i = 0; i < L->length && L->data[i] != e; i++) {
if (i > L->length)
return 0;
else
return i + 1;
}
return 0;
}
// 在顺序表 L 中的第 i 个位置上插入元素 e
bool ListInsert(SqList*& L, int i, ElemType e) {
if (i < 1 || i > L->length + 1 || L->length == MAXSIZE) {
return false;
}
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1];
}
L->data[i - 1] = e;
L->length++;
return true;
}
// 从顺序表 L 中删除第 i 个元素
bool ListDelete(SqList*& L, int i, ElemType& e) {
if (i < 1 || i > L->length) {
return false;
}
e = L->data[i - 1];
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j];
}
L->length--;
return true;
}
exp2-1.cpp
#include <iostream>
#include "sqlist.cpp"
using namespace std;
int main() {
SqList* L;
cout << "顺序表的基本运算如下:" << endl;
cout << " (1)初始化顺序表L:" << endl;
InitList(L);
cout << " (2)依次插入元素a,b,c,d,e:" << endl;
ListInsert(L, 1, 'a');
ListInsert(L, 2, 'b');
ListInsert(L, 3, 'c');
ListInsert(L, 4, 'd');
ListInsert(L, 5, 'e');
cout << " (3)输出顺序表L:";
DispList(L);
cout << " (4)顺序表 L 的长度为:" << ListLength(L) << endl;
cout << " (5)判断顺序表 L 是否为空:" << (ListEmpty(L) ? "是" : "否") << endl;
ElemType e;
GetElem(L, 3, e);
cout << " (6)顺序表 L 的第 3 个元素为:" << e << endl;
cout << " (7)元素 a 的位置为:" << LocateElem(L, 'a') << endl;
cout << " (8)在第4个元素位置上插入元素f" << endl;
ListInsert(L, 4, 'f');
cout << " (9)插入元素 f 后的顺序表 L 为:";
DispList(L);
cout << " (10)删除第 3 个元素:" << endl;
ListDelete(L, 3, e);
cout << " (11)输出顺序表 L :";
DispList(L);
cout << " (12)释放顺序表 L :" << endl;
DestroyList(L);
return 1;
}
代码结果与思路
-
GreateList
函数:该函数用于整体建立顺序表。- 首先动态分配一个
SqList
类型的内存空间,并将其地址赋给传入的指针L
。 - 然后通过循环将给定的数组
a
中的元素逐个复制到新创建的顺序表L
的data
数组中。 - 最后设置顺序表的长度为传入的数组元素个数
n
。
- 首先动态分配一个
-
InitList
函数:用于初始化顺序表。- 动态分配一个
SqList
类型的内存空间,并将其地址赋给传入的指针L
。 - 将顺序表的长度初始化为 0。
- 动态分配一个
-
DestroyList
函数:释放顺序表所占用的内存空间。使用delete
操作符释放传入的指针L
所指向的内存。 -
ListEmpty
函数:判断顺序表是否为空表。通过检查顺序表的长度是否为 0 来确定顺序表是否为空。 -
ListLength
函数:返回顺序表中的元素个数。直接返回顺序表的长度属性。 -
DispList
函数输出顺序表中的所有元素。通过循环遍历顺序表的data
数组,逐个输出其中的元素。 -
GetElem
函数:获取顺序表中指定位置的元素。- 首先检查传入的位置参数
i
是否合法(大于等于 1 且小于等于顺序表长度)。 - 如果合法,将顺序表中对应位置的元素赋值给传入的引用参数
e
,并返回true
;否则返回false
。
- 首先检查传入的位置参数
-
LocateElem
函数- 在顺序表中查找指定元素的位置。
- 通过循环遍历顺序表的
data
数组,逐个比较元素与查找的目标元素e
。 - 如果找到目标元素,返回其位置(从 1 开始计数);如果遍历完整个顺序表都未找到目标元素,返回 0。
-
ListInsert
函数:在顺序表的指定位置插入元素。- 首先检查插入位置参数
i
是否合法(大于等于 1 且小于等于顺序表长度加 1,同时顺序表未满)。 - 如果合法,通过循环将插入位置及之后的元素向后移动一位,为新元素腾出位置。
- 将新元素插入到指定位置,更新顺序表的长度,并返回
true
;否则返回false
。
- 首先检查插入位置参数
-
ListDelete
函数 : 从顺序表中删除指定位置的元素。首先检查删除位置参数i
是否合法(大于等于 1 且小于等于顺序表长度)。如果合法,将指定位置的元素赋值给传入的引用参数e
。通过循环将删除位置之后的元素向前移动一位,覆盖被删除的元素。更新顺序表的长度,并返回true
;否则返回false
。
实验题2:实现单链表的各种基本运算的算法
题目描述
编写一个程序Linklist.cpp,实现单链表的各种基本运算和整体建表算法(假设单
链表的元素类型 ElemType为char)在此基础上设计一个程序exp2-2.cpp完成以下功能:
(1)初始化单链表h。
(2)依次采用尾插法插入元素a,b.c、d、e。
(3)输出单链表h。
(4)输出单链表h的长度。
(5)判断单链表h是否为空。
(6)输出单链表的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素的位置上插入元素l。
(9)输出单链表人。
(10)删除单链表h的第3个元素。
(11)输出单链表系h。
(12)释放单链表为h。
Linklist.cpp程序,其中包含如下函数:
· InitList(LinkNode·&.L):初始化单链表L。
· DestroyList(LinkNode·L);释放单链表L。
· ListEmpty(LinkNode·L);判断单链表L.是否为空表。
· ListLength(LinkNode·L.);返同单链表L中的元素个数。
· DispList(LinkNode·L);输出单链表L。
· GetElem(LinkNode ·L.inti.ElemType &-e):获取单链表I中的第;个元素。
· LocateElem(LinkNode·L,ElemTypee);在单链表L中查找元素e。
· ListInsert(LinkNode·&L,inti.ElemTypee);在单链表L的第i个位置上插入元素w。
· ListDelete(LinkNode·8L.inti.ElemType &e):从单链表L.中删除第i个元素
运行代码
Linklist.cpp
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct LNode {
ElemType data;
struct LNode* next;
} LinkNode;
// 用头插法建立单链表
void CreateListF(LinkNode*& L, ElemType a[], int n) {
LinkNode* s;
L = (LinkNode*)malloc(sizeof(LinkNode));
L->next = NULL;
for (int i = 0; i < n; i++) {
s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = a[i];
s->next = L->next;
L->next = s;
}
}
// 用尾插法建立单链表
void CreateListR(LinkNode*& L, ElemType a[], int n) {
LinkNode* s, * r;
L = (LinkNode*)malloc(sizeof(LinkNode));
L->next = NULL;
r = L;
for (int i = 0; i < n; i++) {
s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
}
// 初始化线性表
void InitList(LinkNode*& L) {
L = (LinkNode*)malloc(sizeof(LinkNode));
L->next = NULL;
}
// 销毁线性表
void DestroyList(LinkNode*& L) {
LinkNode* pre = L;
LinkNode* p = pre->next;
while (p != NULL) {
free(pre);
pre = p;
p = pre->next;
}
free(pre);
}
// 判断线性表是否为空表
bool ListEmpty(LinkNode* L) {
return (L->next == NULL);
}
// 求线性表的长度
int ListLength(LinkNode* L) {
int i = 0;
LinkNode* p = L;
while (p->next != NULL) {
i++;
p = p->next;
}
return i;
}
// 输出线性表
void DispList(LinkNode* L) {
LinkNode* p = L->next;
while (p != NULL) {
printf("%c ", p->data);
p = p->next;
}
printf("\n");
}
// 求线性表中第 i 个元素的值
bool GetElem(LinkNode* L, int i, ElemType& e) {
int j = 0;
LinkNode* p = L;
if (i <= 0) return false;
while (j < i && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) return false;
else {
e = p->data;
return true;
}
}
// 查找第一个值域为 e 的元素的序号
int LocateElem(LinkNode* L, ElemType e) {
int i = 1;
LinkNode* p = L->next;
while (p != NULL && p->data != e) {
p = p->next;
i++;
}
if (p == NULL) return 0;
else return i;
}
// 在单链表中第 i 个位置插入元素 e
bool ListInsert(LinkNode*& L, int i, ElemType e) {
int j = 0;
LinkNode* p = L;
if (i <= 0) return false;
while (j < i - 1 && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) return false;
else {
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
}
// 从单链表中删除第 i 个元素
bool ListDelete(LinkNode*& L, int i, ElemType& e) {
int j = 0;
LinkNode* p = L;
LinkNode* q;
if (i <= 0) return false;
while (j < i - 1 && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) return false;
else {
q = p->next;
if (q == NULL) return false;
e = q->data;
p->next = q->next;
free(q);
return true;
}
}
excp2-2.cpp
#include <stdio.h>
#include <stdlib.h>
#include "Linklist.cpp"
int main() {
LinkNode* h;
ElemType e;
printf("单链表的基本运算如下:\n");
printf("(1)初始化单链表 h\n");
InitList(h);
printf("(2)依次采用尾插法插入元素 a,b,c,d,e\n");
ListInsert(h, 1, 'a');
ListInsert(h, 2, 'b');
ListInsert(h, 3, 'c');
ListInsert(h, 4, 'd');
ListInsert(h, 5, 'e');
printf("(3)输出单链表 h:");
DispList(h);
printf("(4)单链表 h 长度:%d\n", ListLength(h));
printf("(5)单链表 h 为%s\n", ListEmpty(h) ? "空" : "非空");
GetElem(h, 3, e);
printf("(6)单链表 h 的第 3 个元素:%c\n", e);
printf("(7)元素 a 的位置:%d\n", LocateElem(h, 'a'));
printf("(8)在第 4 个元素位置上插入元素 f\n");
ListInsert(h, 4, 'f');
printf("(9)输出单链表 h:");
DispList(h);
printf("(10)删除 h 的第 3 个元素\n");
ListDelete(h, 3, e);
printf("(11)输出单链表 h:");
DispList(h);
printf("(12)释放单链表 h\n");
DestroyList(h);
return 0;
}
代码结果与思路
-
CreateListF
(头插法建立单链表)- 首先为单链表创建一个头节点,并将其
next
指针初始化为NULL
。 - 然后遍历给定的字符数组
a
,对于数组中的每个元素,创建一个新的节点s
。 - 将新节点
s
的next
指针指向当前头节点的next
,然后将头节点的next
指针指向新节点s
,实现头插法插入节点。
- 首先为单链表创建一个头节点,并将其
-
CreateListR
(尾插法建立单链表)- 同样先为单链表创建一个头节点,并将其
next
指针初始化为NULL
。同时定义一个指针r
指向头节点,用于跟踪单链表的尾节点。 - 遍历给定的字符数组
a
,对于数组中的每个元素,创建一个新的节点s
。 - 将新节点
s
插入到r
所指节点的后面,然后更新r
指向新的尾节点。最后将尾节点的next
指针置为NULL
。
- 同样先为单链表创建一个头节点,并将其
-
InitList
(初始化单链表)为单链表分配一个头节点的内存空间,并将头节点的next
指针初始化为NULL
,表示单链表为空。 -
DestroyList
(销毁单链表)从单链表的头节点开始,遍历单链表,逐个释放每个节点的内存空间。使用两个指针pre
和p
,pre
始终指向当前要释放的节点的前一个节点,p
指向当前要释放的节点。释放完一个节点后,移动指针继续释放下一个节点,直到遍历完整个单链表。 -
ListEmpty
(判断单链表是否为空表)检查单链表的头节点的next
指针是否为NULL
,如果是,则表示单链表为空,返回true
;否则返回false
。 -
ListLength
(求单链表的长度)从单链表的头节点开始遍历单链表,使用一个计数器i
记录节点的数量。当遍历到单链表的尾节点时,返回计数器的值,即为单链表的长度。 -
DispList
(输出单链表)从单链表的第一个数据节点开始遍历单链表,逐个输出每个节点的data
域的值,直到遍历到单链表的尾节点。 -
GetElem
(求单链表中第i
个元素的值)从单链表的头节点开始遍历单链表,使用一个计数器j
记录当前遍历到的节点位置。当j
等于i
时,表示找到了第i
个节点,将其data
域的值赋给传入的引用参数e
,并返回true
;如果遍历完单链表还未找到第i
个节点,则返回false
。 -
LocateElem
(查找第一个值域为e
的元素的序号)从单链表的第一个数据节点开始遍历单链表,逐个比较每个节点的data
域与给定的元素e
。如果找到相等的节点,则返回该节点的序号(从 1 开始计数);如果遍历完单链表都未找到,则返回 0。 -
ListInsert
(在单链表中第i
个位置插入元素e
)
- 从单链表的头节点开始遍历单链表,找到第
i - 1
个节点。如果找不到或者i
不合法,则返回false
。 - 如果找到了第
i - 1
个节点,创建一个新的节点s
,将其data
域赋值为e
,并将其next
指针指向第i
个节点,然后将第i - 1
个节点的next
指针指向新节点s
,实现插入操作。
11.ListDelete
(从单链表中删除第 i
个元素)
- 从单链表的头节点开始遍历单链表,找到第
i - 1
个节点。如果找不到或者i
不合法,则返回false
。 - 如果找到了第
i - 1
个节点,将其下一个节点q
保存下来。如果q
为NULL
,表示不存在第i
个节点,返回false
。 - 如果
q
不为NULL
,将q
节点的data
域的值赋给传入的引用参数e
,然后将第i - 1
个节点的next
指针指向q
的下一个节点,释放q
节点的内存空间,实现删除操作。