大话数据结构(一)链表的基本操作

来源:互联网 发布:医药零售软件 编辑:程序博客网 时间:2024/05/29 18:17


本人收藏的链表的基本操作,已经经过上机测试,效果不错!


#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;
}
0 0