实验目的:创建一个单链表
编制一个演示单链表插入、删除、查找等操作的程序
2.需求分析
本程序用C++编写,完成单链表的生成,任意位置的插入、删除,以及确定某一元素在单链表中的位置。
① 输入的形式和输入值的范围:插入元素时需要输入插入的位置和元素的值;删除元素时输入删除元素的
位置;查找操作时需要输入元素的值。在所有输入中,元素的值都是整数
② 输出的形式:在所有三种操作中都显示操作是否正确
查找操作后显示要查找元素的位置。
③ 程序所能达到的功能;
测试数据:
A. 插入操作中依次输入11,12,13,14,15,16,生成一个单链表
B. 查找操作中依次输入12,15,22 返回这3 个元素在单链表中的位置
3.概要设计
1)为了实现上述程序功能,需要定义单链表的抽象数据类型:
ADT LinkedList {
数据对象:D={ai|ai∈IntegerSet,i=0,1,2,…,n,n≥0}
数据关系:R={<ai,ai+1>|ai,ai+1∈D}
实验步骤:
1.创建一个头文件LinkedList.h,用于实现单链表的结构和操作,创建一个CPP文件mainCode.cpp,用于检验单链表的各项功能。
2.单链表的实现:头文件中包含两个类,一个为节点类ListNode,一个为链表类LinkedList。ListNode类中包括link和data两个私有属性,两个重载的构造函数,析构函数,和两个属性的set与get方法。
3.链表操作的实现:在LinkedList类中,构造函数调用友元类ListNode的构造函数申请新节点并将节点连接起来,第一个节点为头结点,数据域为空。对于链表的操作有以下方法:
求表长:定义一个指针遍历整个单链表直到结尾,每访问一个节点将计数器加一,从而得出节点的数目
按照序号查找元素:从头指针开始依次访问各个节点,设置一个计数器记录已访问节点的数目,根据用户给出的序号找到对应的节点并返回指向该节点的指针。
前插与后插:前插时,从头结点开始依次访问找到该节点的前驱,将待插节点作为该节点前驱的后继,同时将该节点作为待插节点的后继。后插时,直接将当前节点的后继指向待插节点,而原后继作为待插节点的后继。
删除当前节点:首先通过逐个访问找到当前节点的前驱,然后将当前节点的前驱的后继指向当前节点的后继。
删除后继节点:首先获得当前节点的后继与后继的后继,然后将当前节点的后继指向后继的后继。
测试过程:首先根据用户依次输入的数据建立单链表,然后让用户选择接下来的操作并调用相应的函数。
1. 约瑟夫环
约瑟夫环使用的链表为循环链表,建立过程与单链表略有区别,在建链表是不再构造头结点,增加了尾指针指向链表的最后一个元素。在全部节点构建完成后,将最后一个节点的后继指向第一个节点。
在执行约瑟夫环时,首先由用户给出初始幸运数字,从第一个节点开始依次访问,直到访问到对应的节点,将该节点的属性luckyNumber作为新的幸运数字,删除该节点,并从下一个节点重新开始依次访问,当链表长度为1时,即得到最后一个未被淘汰的成员,返回该节点的属性number
测试代码
#include<iostream>
#include"mainCode.h"
using namespace std;
int main()
{
LinkedList* l = newLinkedList();
intfirstLucky;
intluckyNumber;
ListNode* current = l->first;
cin>>luckyNumber;
int len =l->length();
for(int i = 1;i < len;i++)
{
for(int j = 1;j++;j < luckyNumber)
{
current = current->link;
}
luckyNumber = current->luckyNumber;
ListNode*p = current;
current = p->link;
l->currentDelete(p);
}
cout<<"current->index;
system("pause");
return 0;
}
LinkedList.h
#include<iostream>
using namespace std;
class ListNode
{
friend class LinkedList;
private:
ListNode* link;
int data;
public:
//构造头结点
ListNode(ListNode* ptrlink)
{
link = ptrlink;
}
//构造其它节点
ListNode(int &item,ListNode* ptrlink)
{
data = item;
link = ptrlink;
}
//析构函数
~ListNode(void){}
ListNode* getLink()
{return link;}
int getData()
{
return data;
}
void setLink(ListNode* value)
{
link = value;
}
void setData(int value)
{
data = value;
}
};
class LinkedList
{
public:
//建立单链表
LinkedList()
{
//创建头节点
ListNode* p = new ListNode(NULL);
first = p;
//创建并连接其它节点
int value;
cin>>value;
while (value != 0)
{
ListNode* p1 = new ListNode(value,NULL);
p->link=p1;
p = p1;
rear = p;
cin>>value;
}
}
//求表长(含头节点)
int length()
{
ListNode* current = first;
int len = 0;
while(current)
{
len++;
current = current->link;
}
return len;
}
//按序号查找元素
ListNode* find(int k)
{
if(k < 1)
{
cout<<"enter error"<<endl;
return NULL;
}
ListNode* current = first->link;
int index = 1;
while(index < k && current)
{
current = current->link;
index++;
}
if(current)
{
return current;
}
return NULL;
}
int search(int x)
{
ListNode*current = first->link;
int index = 1;
while(current&¤t->data != x)
{
current = current->link;
index++;
}
if(current)return index;
return 0;
}
//将节点s前插到节点current前
void forwardInsert(ListNode* current,ListNode* s)
{
ListNode* q = first;
while(q->link != current)
{
q = q->link;
}
s->link = q->link;
q->link = s;
}
//将节点s后插到节点current后
void backwardInsert(ListNode* current,ListNode* s)
{
ListNode*q = current->link;
current->link = s;
s->link = q;
}
//删除当前节点
void currentDelete(ListNode*current)
{
ListNode* q = first;
while(q->link != current)
{
q = q->link;
}
q->link = current->link;
}
//删除后继节点
void backDelete(ListNode*current)
{
ListNode*q = current->link->link;
current->link = q;
}
//输出链表中的所有元素
void output()
{
ListNode* q = first->link;
while(q)
{
cout<<q->data<<" ";
q = q->link;
}
}
private:
ListNode* first;
ListNode* rear;
};