一、实验目的
- 理解和掌握线性表的类型定义方法。
- 掌握链表中的基本运算,包括顺序表的创建、元素的添加、删除,判空及判满等基本操作。
二、实验要求
【项目1 – 验证性实验:建立单链表】
定义单链表存储结构,用头插法和尾插法建立单链表,并显示建立好以后的结果
算法库包括两个文件:
头文件:linklist.h,包含定义顺序表数据结构的代码、宏定义、要实现算法的函数的声明;
源文件:linklist.cpp,包含实现各种算法的函数的定义
请采用程序的多文件组织形式,建立如上的两个文件,另外再建立一个源文件(如main.cpp),编制main函数,完成相关的测试工作。测试工作可以采用“渐进”的思路,每次涉及的函数应该尽可能少。
在建立算法库过程中,为了完成测试,再同一项目(project)中建立一个源文件(如main.cpp),编制main函数,完成相关的测试工作。
例如:
#include "linklist.h"
int main()
{
//定义指向链表头节点的指针
LinkList *L;
//初始化
//输出链表
//判断链表是否为空
//销毁链表
//用头插法创建单链表
//用尾插法创建单链表
//测试ListInsert
//输出链表
//输出链表长度
//测试ListDelete
//输出单链表的第7个元素;
//删除单链表的第10个节点;
//销毁链表
return 0;
}
为测试其基本操作算法的测试代码请自行设计main函数并实现测试过程。
程序代码:
#include <stdio.h>
#include <malloc.h>
#include <iostream>
#include "linklist.h"
int main()
{
printf("创建并初始化链表L:\n");
LinkList *L;
InitList(L);
DispList(L);
if(ListEmpty(L))
printf("该链表为空\n");
DestroyList(L);
printf("已销毁链表L\n\n");
printf("创建单链表L1和L2:\n");
LinkList *L1,*L2;
ElemType a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
int n=12;
CreateListF(L1,a,n);//头插法
CreateListR(L2,a,n);//尾插法
printf("头插法创建单链表L1,输出:\n");
DispList(L1);
printf("尾插法创建单链表L2,输出:\n");
DispList(L2);
printf("\n测试ListInsert,插入单链表L1后输出:\n");
ElemType i=1,e=8;
ListInsert(L1,i,e);
DispList(L1);
printf("单链表L1的长度为:%d\n",ListLength(L1));
printf("单链表L2的长度为:%d\n\n",ListLength(L2));
printf("在单链表L1测试ListDelete,后输出L1\n");
i=8;
ListDelete(L1,i,e);
DispList(L1);
printf("删除的元素值为%d\n\n",e);
printf("输出单链表L2的第7个元素\n");
i=7;
GetElem(L2,i,e);
printf("第7个元素值为%d\n\n",e);
printf("删除单链表L2的第10个节点\n");
i=10;
ListDelete(L2,i,e);
DispList(L2);
printf("删除的第10个节点的元素值为:%d\n\n",e);
DestroyList(L1);
DestroyList(L2);
printf("已销毁链表L1和L2");
return 0;
}
运行结果图:
【项目2 链表应用】
【题目1】设计一个算法,使这个单链表的倒置。实现这个算法,并完成测试。
程序代码:
Main.cpp:
#include <stdio.h>
#include <malloc.h>
#include <iostream>
#include "linklist.h"
int main()
{
printf("创建单链表L3:\n");
LinkList *L3;
ElemType a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
int n=12;
printf("尾插法创建单链表L3,输出:\n");
CreateListR(L3,a,n);
DispList(L3);
printf("单链表L3倒置后输出:\n");
myReverse(L3);
DispList(L3);
DestroyList(L3);
printf("已销毁链表L3");
return 0;
}
//添加倒置单链表的函数myReverse
void myReverse(LinkList *&L)
{
LinkList *p,*q;
p = L->next;
L->next = NULL;
while(p)
{
q = p->next;
p->next = L->next;
L->next = p;
p = q;
}
}
运行结果图:
【题目2】有一个带头节点的循环双链表L(含有两个以上节点),设计一个算法判断L中的数据节点是否对称。
程序代码:
main.cpp:
#include <stdio.h>
#include <malloc.h>
#include <iostream>
#include "linklist.h"
int main()
{
DLinkList *DL;
ElemType a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
int n=12;
CreateDLinkR(DL,a,n);
DispDLink(DL);
if(isSame(DL))
printf("是对称的\n");
else
printf("不是对称的\n");
DestroyDLink(DL);
return 0;
}
Linklist.h:
#ifndef LINKLIST_H_INCLUDED
#define LINKLIST_H_INCLUDED
typedef int ElemType;
typedef struct dnode
{
ElemType data;
struct dnode *next;
struct dnode *prior;
}DLinkList;
void CreateDLinkR(DLinkList *&L,ElemType a[],int n);//尾插法建立单链表
void DestroyDLink(DLinkList *&L); //销毁线性表
void DispDLink(DLinkList *L); //输出线性表
bool isSame(DLinkList *L);
#endif // LINKLIST_H_INCLUDED
List.cpp:
#include <stdio.h>
#include <malloc.h>
#include "linklist.h"
void CreateDLinkR(DLinkList *&L,ElemType a[],int n)
{
DLinkList *s,*r;
int i;
L=(DLinkList *)malloc(sizeof(DLinkList));
L->next=L;
L->prior=L;
r=L;
for (i=0; i<n; i++)
{
s=(DLinkList *)malloc(sizeof(DLinkList));
s->data=a[i];
r->next=s;
s->prior=r;
s->next=L;
L->prior=s;
r=s;
}
}
void DispDLink(DLinkList *L)
{
DLinkList *p=L->next;
while(p!=L)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
void DestroyDLink(DLinkList *&L)
{
DLinkList *p,*q;
q = L->next;
while(q != L)
{
p = q->next;
free(q);
q = p;
}
free(q);
printf("双链表被销毁\n");
}
bool isSame(DLinkList *L)
{
DLinkList *p = L->next;
DLinkList *q = L->prior;
bool same = true;
while(same)
{
if(p->data != q->data)
same = false;
else
{
if(p->next == q || p == q) break;
p = p->next;
q = q->prior;
}
}
return same;
}
运行结果图: