#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <malloc.h>
//帶頭節點雙向循環
//帶頭節點優點容易寫刪除操作 雙向優點可以找到節點前一個,循環優點容易找到尾節點
typedef int LTDateType;
typedef struct ListNode//節點的屬性有單和雙向之分但是無法區別帶頭還是不帶頭
{
LTDateType _data;
struct ListNode *_next;
struct ListNode *_prev;
}ListNode;
typedef struct List
{
ListNode *_head;
}List;
//函數的聲明
void ListInit(List *list);//建立
void ListDestory(List *plist);//銷燬
void ListPrint(List *plist);//顯示,可以傳List型參數但效率低,因爲要構造新的List變量
ListNode *BuyListNode();
void ListPushBack(List *plist,LTDateType x);
void ListPopBack(List *plist);
void ListPushFront(List *plist,LTDateType x);
void ListPopFront(List *plist);
ListNode* ListFind(List* plist,LTDateType x);
void ListInsert(ListNode* pos,LTDateType x);//在pos節點前鏈接值爲x的節點
void ListErase(ListNode* pos);
void ListRemove(List* plist,LTDateType x);//找到x的節點刪除
int ListSize(List* plist);
int ListEmpty(List* plist);
//函數的實現
ListNode *BuyListNode(LTDateType x)
{
ListNode *node= (ListNode*)malloc(sizeof(ListNode));
node->_data = x;
node->_next = NULL;//初始化要有頭尾節點
node->_prev = NULL;
return node;
}
void ListInit(List *plist)
{
assert(plist);
plist->_head = BuyListNode(-1);
plist->_head->_next = plist->_head;
plist->_head->_prev = plist->_head;
}
void ListDestory(List *plist)
{
assert(plist);
ListNode* cur = plist->_head->_next;
ListNode* next ;
while(cur!=plist->_head)
{
next = cur->_next;
free(cur);
cur = next;
}
free(plist->_head);
plist->_head = NULL;
}
void ListPushBack(List *plist,LTDateType x)
{
assert(plist);
ListNode* head = plist->_head;
ListNode* tail = head->_prev;
ListNode* newnode = BuyListNode(x);
tail->_next = newnode;
newnode->_prev = tail;
head->_prev = newnode;
newnode->_next = head;
}
void ListPopBack(List *plist)
{
ListNode *cur = plist->_head;
while(cur->_next!=plist->_head)
{
cur = cur->_next;
}
if(cur!=plist->_head)
{
cur->_prev->_next = cur->_next;
cur->_next->_prev = cur->_prev;
free(cur);
cur = NULL;
}
}
void ListPushFront(List *plist,LTDateType x)
{
assert(plist);
ListNode* newnode = BuyListNode(x);
ListNode* next = plist->_head->_next;
plist->_head->_next = newnode;
newnode->_prev = plist->_head;
next->_prev = newnode;
newnode->_next = next;
}
void ListPopFront(List *plist)
{
assert(plist&& plist->_head->_next!=plist->_head);
ListNode *cur = plist->_head->_next;
plist->_head->_next = cur->_next;
cur->_next->_prev = plist->_head;
free(cur);
}
void ListPrint(List *plist)
{
assert(plist&&plist->_head);
ListNode *cur = plist->_head->_next;
if(cur!=plist->_head)
{
printf("%d->",cur->_data);
cur = cur->_next;
}
while(cur!=plist->_head)
{
printf("<-%d->",cur->_data);
cur = cur->_next;
}
printf("\n");
}
ListNode* ListFind(List* plist,LTDateType x)
{
ListNode *cur = plist->_head;
while(cur->_next!=plist->_head)
{
if(cur->_data == x)
return cur;
cur = cur->_next;
}
return NULL;
}
void ListInsert(ListNode* pos,LTDateType x)
{
ListNode* prev = pos->_prev;
ListNode* cur =BuyListNode(x);
prev->_next = cur;
cur->_prev = prev;
cur->_next = pos;
pos->_prev = cur;
}
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* next = pos->_next;
ListNode* prev = pos->_prev;
next->_prev = pos->_prev;
prev->_next = pos->_next;
free(pos);
}
void ListRemove(List* plist,LTDateType x)
{
ListNode *cur = ListFind(plist,x);
if(cur!=NULL)
{
ListErase(cur);
}
}
int ListSize(List* plist)
{
assert(plist);
ListNode *cur = plist->_head;
int size = 0;
while(cur->_next!=plist->_head)
{
size++;
cur = cur->_next;
}
return size;
}
int ListEmpty(List* plist)
{
assert(plist);
ListNode *cur = plist->_head;
if(cur->_next!=cur)
{
return 1;
}
else
{
return 0;
}
}
//測試函數
void test()
{
List plist;
ListInit(&plist);
ListPushBack(&plist,1);
ListPushBack(&plist,2);
ListPushBack(&plist,3);
ListPushBack(&plist,4);
ListPushBack(&plist,5);
ListPrint(&plist);
ListRemove(&plist,4);
ListPrint(&plist);
printf("%d ",ListSize( &plist));
ListDestory(&plist);
ListInit(&plist);
printf("%d ",ListEmpty(&plist));
}
//主函數
int main()
{
test();
}
另有一份模板設定的雙鏈表代碼,對模板還不是很熟悉,先放在這,日後再看
- 頭文件
//header.h
#include<iostream>
#include <cstdlib>
using namespace std;
/*
* 雙向循環鏈表頭文件,
* 其聲明中封裝有指向鏈表附加頭節點的頭x指針first
*/
template<class T>
struct DbNode
{
T data;
DbNode<T> *pred, *next;
DbNode(T value, DbNode<T> *a = NULL, DbNode<T> *b = NULL):\
data(value), pred(a), next(b) {}
DbNode(DbNode<T> *a = NULL, DbNode<T> *b = NULL):pred(a), next(b) {}
};
template<class T>
class Dblist
{
private:
DbNode<T> *first;
public:
Dblist(T value);
~Dblist()
{
makeEmpty();
}
void makeEmpty();
int Length()const;
bool IsEmpty()
{
return (this->first->pred == this->pred);
}
DbNode<T> *getHead()const
{
return this->first;
}
DbNode<T> *Locate(int i, int d);
DbNode<T> *Search(const T& x);
bool Insert(int i, const T& x, int d);
bool Remove(int i, T& x, int d);
void Print(int d);
};
template<class T>
int Dblist<T>::Length()const
{
DbNode<T> *tmp = this->first;
int i = 1;
while(tmp->next!=this->first)
{
++i;
tmp = tmp->next;
}
return i;
}
template<class T>
bool Dblist<T>::Remove(int i, T& x, int d)
{
DbNode<T> *p = this->Locate(i, d);
if(!p)
return false;
x = p->data;
if(p==this->first && this->Length()>1)
this->first = p->next;
else
cout<<"僅有頭節點的雙向循環鏈表已被刪除!請勿在沒添加新元素前對其調用。"<<endl;
p->pred->next = p->next;
p->next->pred = p->pred;
delete p;
return true;
}
template<class T>
DbNode<T>* Dblist<T>::Search(const T& x)
{
DbNode<T> *tmp = this->first;
do
{
if(tmp->data==x)
{
cout<<"address of x is "<<tmp<<" x = "<<tmp->data<<endl;
return tmp;
}
tmp = tmp->pred;
}
while(tmp!=this->first);
return NULL;
}
template<class T>//定位元素,d=0時從頭節點向前(pred)查第i個元素,d!=0時,從頭節點向後(next)找第i個元素
DbNode<T>* Dblist<T>::Locate(int i, int d)
{
if(this->first->next==this->first || i==0)
return this->first;
int t = 1;
DbNode<T>* tmp = this->first;
if(d) //向後找
{
while(tmp->next!=this->first && t!=i)//查找到的條件爲,在沒把雙向循環鏈表遍歷一遍前,t=i
{
tmp = tmp->next;
++t;
}
if(tmp->next==this->first&&t!=i)
return NULL;
else
return tmp;
}
else //向前找
{
while(tmp->pred!=this->first && t!=i)
{
tmp = tmp->pred;
++t;
}
if(tmp->pred==this->first&&t!=i)
return NULL;
else
return tmp;
}
}
template<class T>
bool Dblist<T>::Insert(int i, const T& x, int d)
{
DbNode<T> *p = this->Locate(i, d);
if(!p)
return false;
DbNode<T> *newnode = new DbNode<T>;
if(newnode==NULL)
{
cout<<"申請內存錯誤!"<<endl;
exit(1);
}
newnode->data = x;
if(d) //p節點後插入
{
p->next->pred = newnode;
newnode->pred = p;
newnode->next = p->next;
p->next = newnode;
}
else //p節點前插入
{
p->pred->next = newnode;
newnode->next = p;
newnode->pred = p->pred;
p->pred = newnode;
}
return true;
}
template<class T>
void Dblist<T>::makeEmpty()
{
DbNode<T> *p, *q = this->first->pred;
while(q != this->first)
{
p = q;
q = q->pred;
delete p;
}
}
template<class T>
void Dblist<T>::Print(int d)
{
if(d) //正序打印
{
cout<<"Positive order: ";
DbNode<T> *tmp = this->first;
while(tmp->next != this->first)
{
cout<<tmp->data<<"->";
tmp = tmp->next;
}
cout<<tmp->data<<"->over."<<endl;
}
else //逆序打印
{
DbNode<T> *tmp = this->first;
cout<<"Reverse sequence: ";
while(tmp->pred != this->first)
{
cout<<tmp->data<<"->";
tmp = tmp->pred;
}
cout<<tmp->data<<"->over."<<endl;
}
}
template<class T>
Dblist<T>::Dblist(T value)
{
this->first = new DbNode<T>(value);
if(this->first == NULL)
{
cerr<<"內存分配錯誤!"<<endl;
exit(1);
}
this->first->next = this->first->pred = this->first;
}
- main文件
//main.cpp
#include"dlinklist.h"
int main()
{
Dblist<int> dl(888);
dl.Print(0);
for(int i=1; i<=4; ++i)
{
dl.Insert(1, i, 0);
}
dl.Print(1);
int l = 999, k = 0;
dl.Insert(0, l, 0);
//int k = 0;
dl.Print(1);
dl.Remove(0, k, 0);
dl.Print(1);
k = 5;
dl.Search(k);
dl.Print(0);
return 0;
}
至此,鏈表的學習就告一段落。