C/C++學習(九)迴圈雙鏈表的操作之建立,插入、刪除
阿新 • • 發佈:2019-02-18
雙向連結串列
迴圈單鏈表的出現,雖然能夠實現從任一結點出發沿著鏈能找到其前驅結點,但時間耗費是O(n)。如果希望從表中快速確定某一個結點的前驅,另一個解決方法就是在單鏈表的每個結點裡再增加一個指向其前驅的指標域prior。這樣形成的連結串列中就有兩條方向不同的鏈,我們可稱之為雙(向)連結串列(Double Linked List)。雙鏈表的結構定義如下:
//建立一個線性雙向連結串列的儲存結構
typedef struct DuLnode
{
T data;
struct DuLnode *prior;//建立一個前趨指標域
struct DuLnode *next ;//建立一個後繼指標域
}DuLonde, *Dulist;
雙鏈表的結點結構如圖2.14所示。
與單鏈表類似,雙鏈表一般也是有頭指標唯一確定的,增加頭結點也能使雙鏈表的某些運算變得方便。同時雙向連結串列也可以有迴圈表,稱為雙向迴圈連結串列,其結構如圖2.15所示。
由於在雙向連結串列中既有前向鏈又有後向鏈,尋找任一個結點的直接前驅結點與直接後繼結點變得非常方便。設指標p指向雙鏈表中某一結點,則有下式成立:
P->prior->next=p=p->next->prior |
在雙向連結串列中,那些只涉及後繼指標的演算法,如求表長度、取元素、元素定位等,與單鏈表中相應的演算法相同,但對於前插和刪除操作則涉及到前驅和後繼兩個方向的指標變化,因此與單鏈表中的演算法不同。
1.雙向連結串列的前插操作
演算法描述:欲在雙向連結串列第i個結點之前插入一個新的結點,則指標的變化情況如圖2.16所示。
2.雙向連結串列的刪除操作
演算法描述:欲刪除雙向連結串列中的第i個結點,則指標的變化情況如圖2.17所示。
#include <iostream>
using namespace std;
template <class T>
class DuList
{
public:
DuList()
{
L = new DuLnode;//申請節點空間
p = new DuLnode;
// if(L == NULL)//判斷是否有足夠的空間
// cout << "申請記憶體空間失敗" <<endl;
L->next = L;//將next設定為空,初始化長度
L->prior = L;
flag = 0;//檢視迴圈列表資料終止標誌位
}
//建立一個線性雙向連結串列的儲存結構
typedef struct DuLnode
{
T data;
struct DuLnode *prior;//建立一個前趨指標域
struct DuLnode *next;//建立一個後繼指標域
}DuLonde, *Dulist;
//頭插法建立雙鏈表
Dulist LinkListCreatH()
{
while((cin >> data1) && (data1 != 0))//data1終止迴圈
{
p = new DuLnode;//關鍵一步重新分配一個指標節點
p->data = data1;
p->next = L->next;
L->next = p;
p->prior = L;
//L->prior = p;
flag++;
}
return L;
}
// //尾插法建立雙鏈表
// Dulist LinkListCreatF()
// {
// while((cin >> data1) && (data1 != 0))//data1終止迴圈
// {
// p = new DuLnode;//關鍵一步重新分配一個指標節點
// p->data = data1;
// p->next = L->next;
// L->next = p;
// p->prior = L;
// L->prior = p;
// }
// return L;
// }
//插入演算法
Dulist ListInsert_Dul(const int i, T e)//1<= i <= 表長+1,第i個位置之前插入元素e
{
s = new DuLnode;
// p = new DuLnode;
s->data = e;
q = L->next;
j = 0;
while((q != L) && j<i-1)
{
q = q->next;
++j;//尋找i-1節點
}
if(!p || j>i)
{
cout << "errorinsert!" << endl;
return L;
}
s->prior = q->prior;//插入L
q->prior->next = s;
s->next = q;
q->prior = s;
return L;
}
//刪除演算法
Dulist ListDelete_Dul(int i, T &e)
{
q = L->next;
j = 0;
while((q != L) && j<i-1)
{
q = q->next;
++j;//尋找i-1節點
}
if(!p || j>i)
{
cout << "errorinsert!" << endl;
return L;
}
e = q->data;
q->prior->next = q->next;
q->next->prior = q->prior;
return L;
}
//獲取元素
void GetElem_L(int i, T &e)
{//L帶頭結點的單鏈表指標,第i個元素存在時賦給e並返回OK,否則返回ERROR
p = L->next;//初始化,p指向第一個節點
j = 1;
while(p != L && j<i)
{
p = p->next;
++j;
}
if(!p || j>i)
{
cout << "errorgetelem!" << endl;
}
e = p->data;
}
void showdata()
{
p = new DuLnode;
j = 0;
p = L->next;//指向頭結點的下一個節點
while(p != L )
{
cout << p->data << "";
p = p->next;
j++;
}
}
~DuList()
{
delete p;
delete L;
delete s;
delete q;
}
private:
T data1;
int j;
int flag;
DuLnode *p;
DuLnode *L;
DuLnode *s;
DuLnode *q;
};
int main()
{
// cout << "Hello World!" << endl;
int data1;
DuList<int> *list = new DuList<int>;
//頭插法
cout << "(H)pleaseenternumbersorcharsorstrings:" << endl;
list->LinkListCreatH();
cout << "showlinklistdata:" << endl;
list->showdata();
cout << endl;
//插入某值
cout << "afterinsertnumbersorcharsorstrings" << endl;
list->ListInsert_Dul(3,10);
cout << "showlinklistdata:" << endl;
list->showdata();
cout << endl;
//刪除某值
cout << "deletenumbersorcharsorstrings:" << endl;
list->ListDelete_Dul(3,data1);
cout << "deletedata:" << data1 << endl;
list->showdata();
cout << endl;
return 0;
}
主要參照地址: