本人收藏的链表的基本操作,已经经过上机测试,效果不错!
#include <iostream>
#include <cassert>using namespace std;
typedef int DataType; //链表元素类型
typedef struct node //链表结点
{
DataType data;
node *next;
}LNode,*PLNode;
//创建带有头结点的链表
//输入ctrl+z结束
//有无头结点将会影响到对链表的所有操作,包括显示链表元素、插入、删除、销毁等
PLNode CreatLink()
{
PLNode pHead = new LNode; //注意delete
PLNode pPre = pHead;
PLNode pCur = NULL;
pHead->data = 0; //空头
pHead->next = pCur;
DataType dataTmp = 0;
cout<<"Please enter the elements of the link ,separate with space,and end with ctrl+z :"<<endl;
while (cin>>dataTmp)
{
pCur = new LNode;
pCur->data = dataTmp;
pCur->next = NULL;
pPre->next = pCur;
pPre = pCur;
}
return pHead;
}
//创建不带头结点的链表
//输入ctrl+z结束
PLNode CreatLinkWithNonNullHead()
{
PLNode pHead = NULL; //delete
PLNode pPre = NULL;
PLNode pCur = NULL;
DataType dataTmp = 0;
cout<<"Please enter the elements of the link ,separate with space,and end with ctrl+z :"<<endl;
while (cin>>dataTmp)
{
pCur = new LNode;
pCur->data = dataTmp;
pCur->next = NULL;
if (NULL == pHead) //对头的特别处理
{
pHead = pCur;
pPre = pCur;
}
else
{
pPre->next = pCur;
}
pPre = pCur;
}
return pHead;
}
//对头结点为pHead的链表,在位置posToInsert处插入元素dataToInsert
//posToInsert定义为size_t类型,排除了位置为负数的异常输入
//注意对输入位置超过链表长度的处理
PLNode InsertLink(PLNode &pHead,size_t posToInsert,const DataType dataToInsert)
{
assert(pHead != NULL);
PLNode pCur = pHead;
PLNode pNew = new LNode;
pNew->data = dataToInsert;
pNew->next = NULL;
while (posToInsert--)
{
//assert(pCur != NULL); //保证不超过链表长度
pCur = pCur->next;
assert(pCur != NULL); //保证不超过链表长度,放在前面当posToInsert减到0时会出错
}
pNew->next = pCur->next;
pCur->next = pNew;
return pHead;
}
//删除结点指针指向的元素,未测试
PLNode InsertLinkAtNode(PLNode &pHead,const PLNode pPosToInsert,const DataType dataToInsert)
{
assert(pHead != NULL);
PLNode pCur = pHead;
PLNode pNew = new LNode;
pNew->data = dataToInsert;
pNew->next = NULL;
while (pCur != pPosToInsert)
{
assert(pCur != NULL); //保证不超过链表长度
pCur = pCur->next;
}
pNew->next = pCur->next;
pCur->next = pNew;
return pHead;
}
//对头结点为pHead的链表,在位置posToInsert处插入元素dataToInsert
//posToInsert定义为size_t类型,排除了位置为负数的异常输入
//注意对输入位置超过链表长度的处理
PLNode DeleteLink(PLNode &pHead,size_t posToDelete)
{
assert(pHead != NULL);
if (0 == posToDelete)
{
return pHead;
}
PLNode pCur = pHead;
PLNode pNodeToDelete = NULL;
size_t posPriorToDelete = posToDelete - 1;
while (posPriorToDelete--)
{
pCur = pCur->next;
assert(pCur != NULL); //保证不超过链表长度,放在前面当posToInsert减到0时会出错
}
pNodeToDelete = pCur->next;
assert(pNodeToDelete != NULL); 保证不超过链表长度
pCur->next = pNodeToDelete->next;
delete pNodeToDelete;
return pHead;
}
//获取链表长度
size_t GetLengthOfLink(PLNode pHead)
{
assert(NULL != pHead);
size_t lengthOfLink = 0;
PLNode pCur = pHead;
while (NULL != pCur->next)
{
++lengthOfLink;
pCur = pCur->next;
}
return lengthOfLink;
}
//冒泡法最链表元素排序
PLNode BubbleSortLink(PLNode &pHead)
{
assert(NULL != pHead);
PLNode pCur = pHead->next;
size_t lengthOfLink = GetLengthOfLink(pHead);
size_t tmp = 0;
int i = (int)lengthOfLink; //定义为int型,在lengthOfLink为0时,lengthOfLink--为-1
int j = 0;
while (i-- > 1)
{
pCur = pHead->next; //每次都指向第一个结点
j = i;
/*while (j--)*/
while (j-- > 0)
{
if (pCur->data > pCur->next->data)
{
tmp = pCur->data;
pCur->data = pCur->next->data;
pCur->next->data = tmp;
}
pCur = pCur->next;
}
}
return pHead;
}
//链表元素翻转
PLNode ReverseLink(PLNode &pHead)
{
assert(NULL != pHead);
if (NULL == pHead->next || NULL == pHead->next->next) //短路求值的特性保证pHead->next->next不会因为pHead->next == NULL而非法操作
{
return pHead;
}
PLNode pPre = pHead->next; //上面的if保证此处的访问都是合法的
PLNode pCur = pPre->next;
PLNode pNxt = NULL;
pPre->next = NULL; //此时pPre为翻转后链表的最后一个结点,将next置为NULL
while (pCur != NULL)
{
pNxt = pCur->next;
pCur->next = pPre; //指正方向翻转
pPre = pCur;
pCur = pNxt;
}
//pHead = pPre;
pHead->next = pPre;
return pHead;
}
//显示有头结点的链表的元素
void Displaylink(const PLNode &pHead)
{
assert(pHead != NULL);
PLNode pCur = pHead->next;
while (pCur != NULL)
{
cout<<pCur->data<<"\t";
pCur = pCur->next;
}
cout<<endl;
}
//显示没有头结点的链表的元素
void DisplaylinkWithNonNullHead(const PLNode &pHead)
{
PLNode pCur = pHead;
while (pCur != NULL)
{
cout<<pCur->data<<"\t";
pCur = pCur->next;
}
cout<<endl;
}
//带有头结点的链表的销毁
void Destorylink(PLNode &pHead)
{
assert(pHead != NULL);
PLNode pCur = pHead->next;
while (pCur != NULL)
{
delete pHead; //删除头结点
pHead = pCur;
pCur = pCur->next;
}
}
//测试链表操作
//除了作为比较的建立链表操作,链表的所有操作都基于带有头结点的链表
//因为带有头结点的链表在各种操作上都会比较方便
void Testlink()
{
PLNode pHead = NULL;
//Test CreatLinkWithNullHead...
cout<<"Test CreatLink..."<<endl;
pHead = CreatLink();
cout<<"display the link created by CreatLink : "<<endl;
Displaylink(pHead);
cin.clear(); //清除流状态
cin.sync();
//Test InsertLink...
/*size_t posToInsert = 0;
DataType dataToInsert = 0;
cout<<"Please enter the position and the data to insert,end with ctrl+z :"<<endl;
while (cin>>posToInsert>>dataToInsert)
{
cout<<"The link before insertion : "<<endl;
Displaylink(pHead);
pHead = InsertLink(pHead,posToInsert,dataToInsert);
cout<<"The link after insertion : "<<endl;
Displaylink(pHead);
cout<<"Please enter the position to insert,end with ctrl+z :"<<endl;
}
cin.clear(); //清除流状态
cin.sync();*/
//Test DeleteLink...
//size_t posToDelete = 0;
//
//cout<<"Please enter the position to delete,end with ctrl+z :"<<endl;
//while (cin>>posToDelete)
//{
// cout<<"The link before insertion : "<<endl;
// Displaylink(pHead);
// pHead = DeleteLink(pHead,posToDelete);
// cout<<"The link after delete : "<<endl;
// Displaylink(pHead);
// cout<<"Please enter the position to delete,end with ctrl+z :"<<endl;
//}
//cin.clear(); //清除流状态
//cin.sync();
//Test GetLengthOfLink...
//size_t lengthOfLink = GetLengthOfLink(pHead);
cout<<"Test GetLengthOfLink..."<<endl;
cout<<"the length of link is : "<<GetLengthOfLink(pHead)<<endl;
//Test BubbleSortLink...
cout<<"Test BubbleSortLink..."<<endl;
BubbleSortLink(pHead);
cout<<"The link after sort : "<<endl;
Displaylink(pHead);
//Test BubbleSortLink...
cout<<"Test ReverseLink..."<<endl;
ReverseLink(pHead);
cout<<"The link after reverse : "<<endl;
Displaylink(pHead);
Destorylink(pHead);
/*cout<<"Test CreatLinkWithNonNullHead..."<<endl;
pHead = CreatLinkWithNonNullHead();
cout<<"display the link created by CreatLinkWithNullHead : "<<endl;
DisplaylinkWithNonNullHead(pHead);
Destorylink(pHead);*/
}
//main
int main()
{
Testlink();
return 0;
}