数据结构:单链表的实现与Joseph环

实验目的:创建一个单链表

 

编制一个演示单链表插入、删除、查找等操作的程序

2.需求分析

本程序用C++编写,完成单链表的生成,任意位置的插入、删除,以及确定某一元素在单链表中的位置。

① 输入的形式和输入值的范围:插入元素时需要输入插入的位置和元素的值;删除元素时输入删除元素的

位置;查找操作时需要输入元素的值。在所有输入中,元素的值都是整数

② 输出的形式:在所有三种操作中都显示操作是否正确

查找操作后显示要查找元素的位置。

③ 程序所能达到的功能;

测试数据:

A. 插入操作中依次输入111213141516,生成一个单链表

B. 查找操作中依次输入121522 返回这3 个元素在单链表中的位置

3.概要设计

1)为了实现上述程序功能,需要定义单链表的抽象数据类型:

ADT LinkedList {

数据对象:D={ai|aiIntegerSet,i=0,1,2,…,n,n≥0}

数据关系:R={<ai,ai+1>|ai,ai+1D}

 

实验步骤

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&&current->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;
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值