1. 程式人生 > >資料結構:單鏈表的實現與Joseph環

資料結構:單鏈表的實現與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;
};