实验四:实现循环单链表各种基本运算的算法
一、实验目的与要求
目的:
领会循环单链表存储结构和掌握循环单链表中各种基本运算算法设计。
内容:
编写一个程序clinklist.cpp,实现循环单链表的各种基本运算和整体建表算法(假设循环单链表的元素类型ElemType为char),并在此基础上设计一个主程序,完成如下功能:
(1)初始化循环单链表h。
(2)依次采用尾插法插入a、b、c、d、e元素
(3)输出循环单链表h。
(4)输出循环单链表h长度
(5)判断循环单链表h是否为空。
(6)输出循环单链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素位置上插入f元素。
(9)输出循环单链表h。
(10)删除循环单链表h的第3个元素
(11)输出循环单链表h。
(12)释放循环单链表h。
二、实验类型
C++算法编程
三、实验原理及说明
循环链表(circular linked list)是另一种形式的链式存储结构。循环链表有循环单链表和循环双链表两种类型,循环单链表的结点类型和非循环单链表的结点类型LinkNode 相同,循环双链表的结点类型和非循环双链表的结点类型 DinkNode 相同。把单链表改为循环单链表的过程是将它的尾结点的next指针域由原来为空改为指向头结点,整个单链表形成一个环。由此,从表中任一结点出发均可找到链表中的其他结点。
四、实验主要仪器设备和材料
序 号 | 名 称 | 主要用途 |
1 | 电脑 | 打开软件 |
2 | Dev c++ | 编写代码,运行代码 |
五、实验内容和步骤
根据《教程》中2.3.4节的算法得到clinklist.cpp程序,其中包含如下函数InitList(LinkNode *&L):初始化循环单链表L。
DestroyList(LinkNode*L):释放循环单链表L。
ListEmpty(LinkNodexL):判断循环单链表是否为空表
ListLength(LinkNode *L):返回循环单链表工的元素个数。
DispList(LinkNode xL):输出循环单链表。
GetElem(LinkNode *L,inti,ElemType &e):获取循环单链表L中第i个元素。
LocateElem(LinkNode *L,ElemTypee):在循环单链表L中查找元素e。
ListInsert(LinkNode *&L,inti,ElemTypee):在循环单链表L中第i个位置上插入元素e。
ListDelete(LinkNode *&L,inti,ElemType &e):从循环单链表L中删除第i个元素。
步骤:
创建一个linklist.cpp文件,将函数写入文件中
创建一个main.cpp文件,编写主函数,对函数进行验证
实验内容:
-
- 编写clinklist
#include <iostream>
#include <malloc.h>
using namespace std;
typedef char ElemType;
typedef struct LNode
{
ElemType date;
struct LNode * next;
} LinkNode;
//头插法创建循环单链表
void CreateListF(LinkNode * &L, ElemType a[], int n) {
LinkNode *s;
L = new LinkNode;
L->next = NULL;
for (int i = 0; i < n; i++) {
s = new LinkNode;
s->date = a[i];
s->next = L->next;
L->next = s;
}
//下面步骤确保了当L链表非空时,s仍能指向L链表的最后结点
s = L->next;
while(s->next != NULL) {
s = s->next;
}
s->next = L;
}
//尾插法创建循环单链表
void CreateListR(LinkNode * &L, ElemType a[], int n) {
LinkNode *s, *r;
L = new LinkNode;
L->next = NULL;
r = L;
for (int i = 0; i < n; i++) {
s = new LinkNode;
s->date = a[i];
r->next = s;
r = s;
}
r->next = L;
}
//初始化循环单链表
void InitList(LinkNode *&L) {
L = new LinkNode;
L->next = L;
}
//释放循环单链表
void DestroyList(LinkNode *L) {
LinkNode *pre = L , *p = pre->next;
while(p != L) {
delete pre;
pre = p;
p = pre->next;
}
delete pre;
}
//判断循环单链表是否为空
bool ListEmpty(LinkNode *L) {
return (L->next == NULL);
}
//返回循环单链表的长度
int ListLength(LinkNode *L) {
LinkNode *s = L;
int i = 0;
while(s->next != L) {
s = s->next;
i++;
}
return i;
}
//输出单链表
void DispList(LinkNode *L) {
LinkNode *p = L->next;
while(p != L ) {
cout << p->date << " ";
p = p->next;
}
cout << endl;
}
//获取循环单链表L中的第i个元素
bool GetElem(LinkNode *L, int i, ElemType &e) {
int j = 1;
LinkNode *p = L->next;
if (i <= 0|| L->next == L) return 0;
if (i == 1) {
e = p->date;
}
else {
while(j < i && p!= L) {
j++;
p = p->next;
}
if (p == L)
return 0;
else {
e = p->date;
return 1;
}
}
}
//在循环单链表L中查找元素e
int LocateElem(LinkNode *L, ElemType e) {
int i = 1;
LinkNode *p = L->next;
while(p != L && p->date != e) {
p = p->next;
i++;
}
if (p == L)
return 0;
else
return i;
}
bool ListInsert(LinkNode *&L, int i, ElemType e) {
int j = 1;
LinkNode *p = L, *s;
if(i <= 0) return 0;
if (p->next == p || i == 1) {
s = new LinkNode;
s->date = e;
s->next = p->next;
p->next = s;
return 1;
}
else {
p = L->next;
while(j < i - 1 && p != L) {
j++;
p = p->next;
}
if (p == L)
return 0;
else {
s = new LinkNode;
s->date = e;
s->next = p->next;
p->next = s;
return 1;
}
}
}
bool ListDelete(LinkNode *&L, int i, ElemType &e) {
int j = 1;
LinkNode *p = L, *q;
if (i <= 0 || L->next == L) return 0;
if (i == 1) {
q = p->next;
e = q->date;
L->next = q->next;
delete q;
return 1;
}
else {
p = L->next;
while(j < i - 1 && p != L) {
j++;
p = p->next;
}
if(p == L)
return 0;
else {
q = p->next;
e = q->date;
p->next = q->next;
delete q;
return 1;
}
}
}
编写main函数
#include "clinklist.cpp"
int main() {
LinkNode *h;
ElemType e;
cout << "单链表的基本运算如下 " << endl;
cout << " (1)初始化单链表h" << endl; InitList(h);
cout << " (2)依次采用尾插法插入a,b,c,d,e元素" << endl;
ListInsert(h,1,'a');
ListInsert(h,2,'b');
ListInsert(h,3,'c');
ListInsert(h,4,'d');
ListInsert(h,5,'e');
cout << " (3)输出单链表h:"; DispList(h);
cout << " (4)单链表长度为:"<< ListLength(h)<< endl;
cout << " (5)单链表h为"<< (ListEmpty(h)? "空":"非空") << endl;
GetElem(h,3,e); cout << "(6)单链表h的第3个元素:" << e << endl;
cout <<"(7)元素a的位置:"<< LocateElem(h,'a') << endl;
cout << "(8)在第4个元素位置上插入f元素\n"; ListInsert(h,4,'f');
cout << "(9)输出单链表h:"; DispList(h);
cout << "(10)删除h的第3个元素\n"; ListDelete(h,3,e);
cout << "(11)输出单链表h:"; DispList(h);
cout << "(12)释放单链表h\n"; DestroyList(h);
return 1;
}
运行结果:
六、实验小结与分析
在此次实验中我领会了循环单链表链表存储结构,掌握了循环单链表链表中的各种基本运算算法设计,循环单链表是另一种形式的链式存储结构,但是它可以在单链表的基础上修改而来,将单链表中尾结点next指针域由原来的空改为指向头节点,这样就是单链表形成一个环,这种可以不用双链表的形式就可以实现快速找到尾结点等功能。