雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個數據結點中都有兩個指針,分別指向直接後繼和直接前驅。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點,時間複雜度爲O(1)。
雙鏈表具有以下優點:
1、刪除單鏈表中的某個結點時,一定要得到待刪除結點的前驅,得到該前驅有兩種方法,第一種方法是在定位待刪除結點的同時一路保存當前結點的前驅。第二種方法是在定位到待刪除結點之後,重新從單鏈表表頭開始來定位前驅。儘管通常會採用方法一。但其實這兩種方法的效率是一樣的,指針的總的移動操作都會有2*i次。而如果用雙向鏈表,則不需要定位前驅結點。因此指針總的移動操作爲i次。
2、查找時也一樣,我們可以借用二分法的思路,從head(首節點)向後查找操作和last(尾節點)向前查找操作同步進行,這樣雙鏈表的效率可以提高一倍。
可是爲什麼市場上單鏈表的使用多於雙鏈表呢?
從存儲結構來看,每個雙鏈表的節點要比單鏈表的節點多一個指針,而長度爲n就需要 n*length(這個指針的length在32位系統中是4字節,在64位系統中是8個字節) 的空間,這在一些追求時間效率不高應用下並不適應,因爲它佔用空間大於單鏈表所佔用的空間;這時設計者就會採用以時間換空間的做法,這時一種工程總體上的衡量。
代碼實現:
#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
using namespace std;
typedef struct Person //數據
{
int number;
char name[32];
}DATATYPE;
typedef struct Node //結點
{
DATATYPE data;
Node *pri;
Node *next;
}linkNode;
typedef struct List //鏈表
{
linkNode *head;
int clen;
}linkLIst;
//鏈表初始化
linkLIst * initList()
{
linkLIst *tmp = new linkLIst;
if (NULL == tmp)
{
perror("list_init Linklist");
exit(1);
}
tmp->clen = 0;
tmp->head = NULL;
return tmp;
}
//頭插
int insertHead(linkLIst *mlist,DATATYPE *data)
{
linkNode *newnode = new linkNode; //創建要添加的結點
newnode->next = NULL;
newnode->pri = NULL;
if (NULL == newnode)
{
perror("insertHead newnode");
return 1;
}
newnode->data = *data;
newnode->next = mlist->head;
mlist->head = newnode;
mlist->clen++;
return 0;
}
//尾插
int insertTail(linkLIst *mlist, DATATYPE *data)
{
linkNode *newnode = new linkNode; //創建要添加的結點
if (NULL == newnode)
{
perror("insrtTail newnode");
return 1;
}
newnode->data = *data;
newnode->next = NULL;
newnode->pri = NULL;
if (NULL == mlist->head)
{
mlist->head = newnode;
}
else
{
linkNode* tmp = mlist->head;
while (tmp->next)
{
tmp = tmp->next;
}
tmp->next = newnode;
newnode->pri = tmp;
}
mlist->clen++;
return 0;
}
//查找
linkNode* findList(linkLIst *mlist,char *pname)
{
linkNode *tmp = mlist->head;
while (tmp)
{
if (0 == strcmp(tmp->data.name,pname))
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
//刪除元素
int delList(linkLIst *mlist, char *pname)
{
if (NULL == mlist->head) //判斷鏈表是否爲空
{
cout << "鏈表已爲空" << endl;
return 1;
}
if (NULL == mlist->head->next) //判斷是否只有表頭
{
if (0 == strcmp(mlist->head->data.name,pname))
{
delete mlist->head;
mlist->head = NULL;
}
else
{
cout << "未查到。。。" << endl;
return 1;
}
}
else
{
linkNode *p = mlist->head;
linkNode *q = mlist->head;
while (p)
{
if (0 == strcmp(p->data.name,pname))
{
if (p == q) //判斷是否爲表頭
{
mlist->head = p->next;
p->next->pri = NULL;
}
else
{
q->next = p->next;
p->next->pri = q;
}
delete p;
p = NULL;
mlist->clen--;
return 0;
}
else
{
q = p;
p = p->next;
}
}
}
cout << "未找到要刪除的元素。。。" << endl;
return 1;
}
//鏈表逆序
int reverseList(linkLIst *mlist)
{
linkNode *p = mlist->head->next;
linkNode *q = mlist->head;
while (p)
{
q->next = p->next;
if (p->next)
{
p->next->pri = q;
}
p->next = mlist->head;
p->pri = NULL;
mlist->head = p;
p = q->next;
}
return 0;
}
//鏈表排序
int sortList(linkLIst *mlist)
{
if (NULL == mlist->head)
{
cout << "鏈表爲空" << endl;
return 1;
}
if (NULL == mlist->head->next)
{
cout << "鏈表只有一個表頭" << endl;
return 0;
}
else
{
linkNode *p, *q, temp;
q = mlist->head;
while (q->next != NULL)
{
p = q->next;
while (p != NULL)
{
if (p->data.number < q->data.number)
{
temp.data = p->data;
p->data = q->data;
q->data = temp.data;
}
p = p->next;
}
q = q->next;
}
}
cout << "排序完成" << endl;
return 0;
}
//修改鏈表元素
int updataList(linkLIst *mlist,char *oldname,char *newname)
{
linkNode *temp;
temp = findList(mlist,oldname);
strcpy(temp->data.name, newname);
return 0;
}
//銷燬鏈表
int destoryList(linkLIst *mlist)
{
linkNode *tmp = mlist->head;
while (mlist->head) //逐個刪除每個結點
{
tmp = mlist->head;
mlist->head = tmp->next;
delete tmp;
}
tmp = NULL;
delete mlist;
mlist = NULL;
cout << "釋放完成" << endl;
return 0;
}
//打印鏈表
int showList(linkLIst *mlist)
{
linkNode *tmp = mlist->head;
while (tmp)
{
cout << "ID:" << tmp->data.number << " " << "名字:" << tmp->data.name << endl;
tmp = tmp->next;
}
return 0;
}
int main()
{
linkLIst *m_list = initList();
DATATYPE data1 = { 1,"劉德華" };
DATATYPE data2 = { 0,"周潤發" };
cout << "頭插:" << endl;
insertHead(m_list, &data1);
insertHead(m_list, &data2);
cout << "當前鏈表長度:" << m_list->clen << endl;
showList(m_list);
DATATYPE data3[3] = {
{2,"張學友"},
{3,"郭富城"},
{4,"黎明"}
};
DATATYPE data4 = { 1,"周星馳" };
cout << "尾插:" << endl;
insertTail(m_list, &data3[0]);
insertTail(m_list, &data3[1]);
insertTail(m_list, &data3[2]);
insertTail(m_list, &data4);
sortList(m_list);
cout << "當前鏈表長度:" << m_list->clen << endl;
showList(m_list);
cout << "---------------------------------------------------" << endl;
cout << "鏈表逆序:" << endl;
reverseList(m_list);
cout << "鏈表長度:" << m_list->clen << endl;
showList(m_list);
cout << "---------------------------------------------------" << endl;
cout << "查找元素:" << endl;
linkNode* res = findList(m_list, "劉德華");
if (NULL != res)
{
cout << "ID:" << res->data.number << " " << "姓名:" << res->data.name << endl;
}
else
{
cout << "未找到。。。" << endl;
}
cout << "---------------------------------------------------" << endl;
cout << "刪除元素:" << endl;
delList(m_list, "劉德華");
cout << "鏈表長度:" << m_list->clen << endl;
showList(m_list);
cout << "---------------------------------------------------" << endl;
cout << "修改鏈表元素:" << endl;
updataList(m_list, "張學友", "成龍");
showList(m_list);
cout << "---------------------------------------------------" << endl;
cout << "銷燬鏈表:" << endl;
destoryList(m_list);
system("pause");
return 0;
}