实验二:实现单链表各种基本运算的算法
一、实验目的与要求
目的:
领会单链表存储结构和掌握单链表中各种基本运算算法设计,以及完成以下任务
编写头插法和尾插法编写代码,并且在main函数中使用头插法和尾插法进行实现导入数据。
内容:
编写一个程序linklist.cpp,实现单链表的各种基本运算和整体建表算法(假设单链表的元素类型ElemType为char),并在此基础上设计一个程序exp2-2.cPp,完成如下功能:
(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++算法编程
三、实验原理及说明
顺序表必须占用一整块事先分配大小的存储空间,这样会降低存储空间的利用率,为此有了可以实现存储空间动态管理的链式存储结构--链表。
线性表的链式存储结构称为链表(linked list)。线性表的每个元素用一个内存结点存储,嗜每个内存结点不仅包含元素本身的信息(称为数据域),而且包含表示元素之间逻辑关系的信息.
在 C/C++语言中采用指针来实现,这称为指针域由于线性表中的每个元素最多只有一个前驱元素和一个后继元素,所以当采用链表存储时,一种最简单、最常用的方法是在每个结点中除包含数据域以外只设置一个指针域,用于指向其后继结点,这样构成的链表称为线性单向链接表,简称单链表(singly linked list)。
四、实验主要仪器设备和材料
序 号 | 名 称 | 主要用途 |
1 | 电脑 | 打开软件 |
2 | Dev c++ | 编写代码,运行代码 |
五、实验内容和步骤
根据《教程》中2.3.2节的算法得到linklist.cpp程序,其中包含如下函数:
ZInitList(LinkNode *&L):初始化单链表L。
DestroyList(LinkNode *L):释放单链表。
·ListEmpty(LinkNode *L):判断单链表是否为空表。
ListLength(LinkNode *L):返回单链表的元素个数。
DispList(LinkNode *):输出单链表。
GetElem(LinkNode *L,inti,ElemType&e):获取单链表L中第i个元素。
。LocateElem(LinkNode xL,ElemTypee):在单链表L中查找元素e。
ListInsert(linkNode *&L,inti,ElemTypee):在单链表L第i个位置上插人元素e。
ListDelete(LinkNode *&L,inti,ElemType &e):从单链表L中删除第i个元素
步骤:
创建一个linklist.cpp文件,将函数写入文件中
创建一个main.cpp文件,编写主函数,对函数进行验证
实验内容:
-
- 编写linklist函数
#include<iostream>
#include <malloc.h>
using namespace std;
typedef char ElemType;
typedef struct LNode {
ElemType data;
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->data = a[i];
s->next = L->next;
L->next = s;
}
}
//尾插法建立单链表
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->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
}
//初始化单链表
void InitList(LinkNode *&L) {
L = new LinkNode;
L->next = NULL;
}
//释放单链表
void DestroyList(LinkNode *&L) {
LinkNode *pre = L, *p = L->next;
while(p != NULL) {
delete pre;
pre = p;
p = pre->next;
}
delete pre;
}
//判断单链表L是否为空表
bool ListEmpty(LinkNode *&L) {
return (L->next == NULL);
}
//返回单链表L的元素个数
int ListLength(LinkNode *L) {
int i;
LinkNode *p = L;
for (i = 0; p->next != NULL; i++, p = p->next);
return i;
}
//输出单链表
void DispList(LinkNode *L) {
LinkNode *p = L->next;
while( p != NULL) {
cout << p->data<<" ";
p = p->next;
}
cout << endl;
}
//获取单链表L中第i个元素
bool GetElem(LinkNode *L, int i, ElemType &e) {
int j = 0;
LinkNode *p = L;
if (i <= 0) return 0;
while(j < i && p != NULL) {
j++;
p = p->next;
}
if (p == NULL)
return 0;
else {
e= p->data;
return 1;
}
}
//在单链表中查找元素e
int LocateElem(LinkNode *L, ElemType e) {
int i = 1;
LinkNode *p = L->next;
while(p->data != e && p != NULL) {
p = p->next;
i++;
}
if (p == NULL) return 0;
else return (i);
}
//在单链表L第i个位置上插入元素e
bool ListInsert(LinkNode *&L, int i, ElemType e) {
int j = 0;
LinkNode *p = L, *s;
if (i <= 0) return 0;
while(j < i - 1 && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) {
return 0;
}
else {
s = new LinkNode;
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
}
//从单链表L中删除第i个元素
bool ListDelete(LinkNode *&L, int i, ElemType &e) {
int j = 0;
LinkNode *p = L, *q;
while(j < i - 1 && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) {
return 0;
}
else {
q = p->next;
if (q == NULL) {
return 0;
}
else {
e = q->data;
p->next = q->next;
delete q;
return 1;
}
}
}
编写main函数
#include "linklist.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');
*/
char ch[5] = {'a', 'b', 'c', 'd', 'e'};
//cout << "采用头插法用数组一并插入a,b,c,d,e元素" << endl;
//CreateListF(h, ch, 5);
cout << "采用尾插法用数组一并插入a,b,c,d,e元素" << endl;
CreateListR(h, ch, 5);
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');
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;
}
运行结果:
六、实验小结与分析
在此次实验中我领会了单链表存储结构,掌握了单链表中的各种基本运算算法设计,知道了如何使用C++语言中的指针来实现存储空间的动态管理,实现了单链表的各种基本运算和整体见表算法。并且了解了头插法和尾插法的原理,以及编写代码实现头插法和尾插法并进行了验证。