1. 程式人生 > >C++資料結構雙鏈表

C++資料結構雙鏈表

《資料結構》實驗二:

                線性表綜合實驗

一.實驗目的

     鞏固線性表的資料結構的儲存方法和相關操作,學會針對具體應用,使用線性表的相關知識來解決具體問題,鞏固課堂學習。


實驗內容

1.建立一個由n個學生成績的順序表,n的大小由自己確定,每一個學生的成績資訊由自己確定,實現資料的對錶進行插入、刪除、查詢等操作。分別輸出結果。


這裡用雙鏈表來實現。


//

//  main.cpp

//  雙鏈表

//

//  Created by 樑華建 on 2017/9/17.

//  Copyright © 2017 樑華建. All rights reserved.

//

#include <iostream>

template<class DataType>

struct DulNode

{

    DataType data;

    DulNode<DataType> *prior,*next;

};

template<class DataType>

class LinkList

{

    public :

    LinkList();                   //無參建構函式,建立只有頭結點的雙鏈表

    LinkList(DataType a[],int n); //有參建構函式,建立有n個元素的雙鏈表

    ~LinkList();                 

//解構函式,在物件被清空時候呼叫

    int Length();                 //求雙鏈表的長度

    DataType Get(int i);          //按位置查詢,在雙鏈表中查詢到第i個節點的袁術

    int locate(DataType x);       //按位置查詢,在雙鏈表中查詢到值為x的元素

    void Insert(int i ,DataType x);//插入操作,在第i個位置插入元素值為x的元素

    DataType Delete(int i);        //刪除在第i個位置的元素

    void PrintList();              //遍歷輸出所有雙鏈表的函式

    private :

    DulNode<DataType >*first;         //雙鏈表的頭指標

    

};


//遍歷函式

template<class DataType>

void LinkList<DataType>::PrintList()

{

    DulNode<DataType> * p=NULL;          //建立工作結點

    p=first->next;

    

    while (p!=NULL) {

        std::cout<<p->data<<" ";   //遍歷輸出所有元素直到尾部

        p=p->next;

    }

}


//刪除函式

template<class DataType>

DataType LinkList<DataType>::Delete(int i)

{

    DulNode<DataType> * p=first;//p指向頭結點

    int count=0;

    DataType x;

    while (p!=NULL && count<i) {//遍歷找到i-1的結點

        p=p->next;

        count++;

    }

    if (p==NULL||p->next==NULL) throw "i節點不存在或i的後續節點為空";

    else {

        //        p為待刪除節點

        x=p->data;

        (p->prior)->next=p->next;   //pprior指向pnext  a(i-1)->a(i+1)

        (p->next)->prior=p->prior;  //pnext指向pprior  a(i+1)->a(i-1)

    }

    return x;

    

}

//插入函式

template<class DataType>

void LinkList<DataType>::Insert(int i, DataType x)

{

    DulNode<DataType> *s;

    DulNode<DataType> * p=first;//p指向頭結點

    int count=0;

    while (p!=NULL&&count<i-1) {//遍歷找到i-1的結點

        p=p->next;

        count++;

    }

    if (p==NULL) throw "i節點不存在";

    else{  s=new DulNode<DataType>;

        s->data=x; //建立新結點

        s->prior=p;         //s插入i-1i

        s->next=p->next;

        p->next->prior=s;   //摘除i-1i之間的鏈

        p->next=s;

        

        //        s->next=p->next;p->next=s;     //將結點s放在結點p之後

    }

}


//查詢函式 通過值

template<class DataType>

int LinkList<DataType>::locate(DataType x)

{

    DulNode<DataType> *p=NULL;

    p=first;

    int count=1;

    while (p!=NULL) {

        if (p->data==x) {

            return count;

        }

        else{

            p=p->next;

            count++;

        }

    }

    return count;

}


//查詢函式 通過下標

template<class DataType>

DataType LinkList<DataType>::Get(int i)

{

    DulNode<DataType>* p=NULL;

    p=first->next;

    int count=1;

    while (p!=NULL && count<i) {

        p=p->next;

        count++;

    }

    if (p==NULL) throw "輸入的x有誤";

    else return p->data;

}


//求線性表長度演算法

template<class DataType>

int LinkList<DataType>::Length()

{

    DulNode<DataType> *p=first->next;

    int count=0;

    while (p!=NULL) {

        p=p->next;

        count++;

    }

    return count;

}



template <class DataType>

LinkList<DataType>::LinkList(DataType a[], int n) //尾插法

{

    DulNode<DataType> *s, *r;

    first = new DulNode<DataType>;

    r = first;

    for (int i = 0; i < n; i++)

    {

        s = new DulNode<DataType>;

        s->data = a[i];

        r->next = s;

        r= s;

    }

    r->next = NULL;

}



//無參建構函式

template<class DataType>

LinkList<DataType>::LinkList()

{

    DulNode<DataType>*p;

    first=p;           //生成頭結點

    first->next=NULL//頭結點的next指標域置空

    first->prior=NULL;

}


//解構函式

template<class DataType>

LinkList<DataType>::~LinkList()

{

    while (first!=NULL) {

        DulNode<DataType> *p;

        std::cout<<"我已經被銷燬";

        p=first;           //暫存被釋放結點

        first=first->next;  //指向下一個結點

        delete p;   //刪除結點

    }

}

int main(int argc, const char * argv[]) {

    

    int n=0;

    std::cout<<"你要錄入的學生數量為";

    std::cin>>n;

    int a[]={50,60,70,80};

    LinkList<int> Student(a,n);

    std::cout<<"-----------";

    Student.PrintList();

    std::cout<<"在第三個位置插入一個成績為20的學生";

    Student.Insert(3, 20);

    std::cout<<"-----------";

    Student.PrintList();

    std::cout<<"-----------";

    std::cout<<"第三位學生的成績"<<Student.Get(3);

    std::cout<<"現在總學生數量為"<<Student.Length();

    

    return 0;

}


上圖的“我已經被銷燬”,說明呼叫了四次解構函式刪除了四個學生物件。


實驗總結:

這次雙鏈表實驗與單鏈表大部分相似,通過next指標來尋找資料然後進行操作,不同的是插入與刪除,要修改幾個指標的指向,還算可以,加強了對指標的認識。