1. 程式人生 > 其它 >C++實現單鏈表(2)

C++實現單鏈表(2)

單鏈表操作之結點刪除,結點插入,連結串列翻轉

前面一節實現了連結串列的基本操作,本節實現連結串列常用操作,雖然很常用,實現起來卻比較複雜。

1、結點刪除

  刪除結點可以按照位置刪除,也可以按照資料刪除,這裡實現的是按照位置刪除。在刪除之前,取需要判斷刪除位置是否合法,以及刪除的位置是否會大於連結串列的總長度。

template<typename Datatype>
inline void LinkList<Datatype>::Delete(int delete_location)
{
    if (0 >= delete_location || this->Length() <= delete_location)
        
throw "刪除位置錯誤"; int count = 1; Node<Datatype>* p = this->first; while (count < delete_location) { count++; p = p->next; } /** * 當p為待插入位置的上一個元素時,退出迴圈 */ Node<Datatype>* q = p->next; p->next = q->next; //釋放空間,刪除乾淨
delete q; }

  這裡了的遍歷需要遍歷到刪除位置元素的前一個元素,因為遍歷到刪除元素無法向前遍歷,除非是雙向連結串列或者建立一個變數來儲存前一個結點的指標,這裡完全沒有必要。同時刪除元素也要將對應結點的空間釋放掉,防止記憶體洩漏。

2、結點插入

  結點插入同樣需要遍歷到插入位置的前一個結點,同時允許插入位置大於連結串列總長度+1,實現尾插。同時插入結點是要申請堆區記憶體空間用來儲存需要插入的結構體。

template<typename Datatype>
inline void LinkList<Datatype>::Insert(const Datatype& insert_data, int
insert_location) { if (0 >= insert_location || this->Length() + 1 < insert_location) throw "插入位置錯誤"; int count = 1; Node<Datatype>* p = this->first; while (count < insert_location) { count++; p = p->next; } /** * 當p為待插入位置的上一個元素時,退出迴圈 * 初始化待插入結點 * 將節點用頭插的方式插入連結串列中 */ Node<Datatype>* s = new Node<Datatype>; s->Data = insert_data; s->next = p->next; p->next = s; }

3、連結串列翻轉

連結串列翻轉使用以下方法:

1-判斷連結串列長度是否大於1,如果大於1,則進行第2步,否則,退出函式。

2-堆區開闢記憶體申請一個結點大小的記憶體空間,將其作為新連結串列頭結點,初始化。

3-從頭遍歷原連結串列每個元素並依次將元素插入到新連結串列的頭結點之後,釋放原連結串列每個結點記憶體。

4-將原連結串列頭指標指向新連結串列頭結點。

template<typename Datatype>
inline void LinkList<Datatype>::Reverse()
{
    int length = this->Length();
    if (0 == length || 1 == length)    return;

    Node<Datatype>* p = this->first, * p_next = p->next;

    //如果連結串列長度小於等於1,初始化新連結串列頭結點
    Node<Datatype> *p_tar = new Node<Datatype>;
    p_tar->next = nullptr;

    for (int i = 0; i < length; i++)
    {
        //為待插入新連結串列的結點分配空間
        Node<Datatype> *s = new Node<Datatype>;

        //待插入結點填入資料
        Datatype data = p_next->Data;
        s->Data = data;

        //新節點頭插方式插入新連結串列
        s->next = p_tar->next;
        p_tar->next = s;

        //釋放舊結點空間
        delete p;

        //p和p_next指標後移
        p = p_next;
        p_next = p_next->next;
    }
    //將新頭結點指標賦值給first
    this->first = p_tar;
}

4、測試程式碼

#include <iostream>
#include <string>
#include "LinkList.hpp"

using namespace std;

int main()
{
    string string_array[] = { " This ", " is ", " string_list ", " test." };
    //使用帶參構造資料域為string型別的連結串列
    LinkList<string>* list_string_p = new LinkList<string>
        (string_array, sizeof(string_array) / sizeof(string_array[0]));

    try 
    {
        cout << "連結串列帶參構造後遍歷:"; 
        list_string_p->PrintList();
        cout << "string連結串列第4個元素:" << list_string_p->Get(4) << endl;

        list_string_p->Insert(" a ", 3);
        cout << "在第三個位置插入a:";
        list_string_p->PrintList();

        list_string_p->Delete(3);
        cout << "刪除第三個元素後:";
        list_string_p->PrintList();

        list_string_p->Reverse();
        cout << "連結串列翻轉:";
        list_string_p->PrintList();

        //list_string_p->Empty();
        cout << "連結串列長度:" << list_string_p->Length() << endl;
    }
    catch (const char* catch_string)
    {
        cout << catch_string << endl;
    }

    delete list_string_p;
    system("pause");
    return 0;
}

5、測試結果

6、 總結

異常的測試也通過,這裡不再演示。

新人才疏學淺,有錯的地方敬請指正!!

本文來自部落格園,作者:夏末終年,轉載請註明出處:https://www.cnblogs.com/xiamozhongnian/p/15890390.html