[Data Structure]数据结构学习之链表小结[上]---实现

[Data Structure]数据结构学习之链表小结[]:

                                                    by EmilMatthew

线性表中的链表是数据结构学习的基础和起点, 虽说看上去比较简单.不过里面所涉及的一些操作及算法还是有相当的深入和实践价值的,把它们搞熟了,是进一步学习的基石.

首先当然是看一下链表的两种基本实现,一种是基于数据的,还有一种是基于指针的:

(这里的数据结构的定义部分的代码风格基于北大的张乃孝的<算法与数据结构>一书)

1基于数组的链表实现:

/*

All these code -------think ,code , test by EmilMatthew,You can modify and use them as you wish, but I do not promise these code can fit all your needs.

                                                                                                         05/09/12

*/

/*SeqList*/

       struct SeqList;

       typedef struct SeqList* PSeqList;

      

       struct SeqList

              {

                     Type element[MAXLENGTH];

                     int    n;

              };

线性表相关的操作:

//创建空表:

PSeqList createNullList_Seq(void)

{

       PSeqList palist;

       palist=(PSeqList)malloc(sizeof(PSeqList));

       assertF(palist!=NULL,"in createNullList_Seq,pallist is null/n");

       palist->n=-1;

       return palist;

}

 

//在指定位置插入:

void insert_Seq(PSeqList inSeqList,int pos,Type data)

{

       int i;

      

       assertF(inSeqList!=NULL,"in insert_Seq,PSeqList is null/n");

       assertF(inSeqList->n<MAXLENGTH-1,"in insert_Seq,no more space/n");

       assertF(pos>=0&&pos<=inSeqList->n+1,"in insert_Seq ,pos out of range/n");

      

       inSeqList->n++;

      

       for(i=inSeqList->n;i>=pos+1;i--)

              inSeqList->element[i+1]=inSeqList->element[i];

       assertF(i==pos,"in insert_Seq,i!=pos/n");

      

       inSeqList->element[i]=data;

}

 

//在指定位置删除节点

void del_ElementP(PSeqList inSeqList,int pos)

{

       int i;

        

      

       assertF(inSeqList!=NULL,"in del_ElementP,PSeqList is null/n");

       assertF(pos>=0&&pos<=inSeqList->n,"in del_ElementP ,pos out of range/n");

       assertF(inSeqList->n!=-1,"in del_ElementP,PSeqList is null/n");

 

       for(i=pos;i<inSeqList->n;i++)

              inSeqList->element[i]=inSeqList->element[i+1];

      

       inSeqList->n--;

       inSeqList=NULL;

}

 

//将链表逆转

void reverseSeqList(PSeqList inSeqList)

{

       int l, u;

       assertF(inSeqList!=NULL,"in reverseSeqList,pallist is null/n");

       /*init data*/

       l=0;

       u=(inSeqList->n)-1;

       while(l<=u)

       {

              swapArrData(inSeqList->element,l,u);

              l++;

              u--;

       }

}

 

//遍历链表

void traversalSeqList(PSeqList inSeqList)

{

       PSeqList node;

       int i;

       assertF(inSeqList!=NULL,"in traversalSeqList,pallist is null/n");

      

       node=inSeqList;

       /*init*/

       i=0;

       printf("===starting of traversalYouBiaoNode===/n");

       while(i<inSeqList->n)

       {

              printf("%d->",inSeqList->element[i]);

              i++;

       }

       printf("%d",inSeqList->element[i]);

       printf("/n===end of traversalYouBiaoNode===/n");

}

 

//在某个位置插入元素

int locateData(PSeqList inSeqList,Type searchData)

{

       int i=0;

       int returnPos=-1;

       for(i=0;i<=inSeqList->n;i++)

              if(inSeqList->element[i]==searchData)

              {

                     returnPos=i;

                     break;

              }

             

       return returnPos;

}

 

//得到某个位置的元素值

Type retriveData(PSeqList inSeqList,int pos)

{

       assertF(inSeqList!=NULL,"in retriveData,PSeqList is null/n");

       assertF(pos>=0&&pos<=inSeqList->n,"in retriveData ,pos out of range/n");

       return inSeqList->element[pos];

}

 

//检测当前链表是否为空

int isNullSeqList(PSeqList inSeqList)

{

       return inSeqList==NULL||inSeqList->n==-1;

}

 

以上操作相对都比较的简单,所以就不做过多的介绍了,重点是下面基于指针来实现的链表上:

 

 

2基于指针实现的链表:

 

/*link_List*/

       struct Node;

       typedef struct Node* PNode;

       typedef struct Node* LinkList;

       struct Node

              {

                     Type  info;

                     PNode link;

              };

//创建一个空链表

LinkList createNullList_LinkList(void)

{

       PNode tmpNode;

       tmpNode=(PNode)malloc(sizeof(struct Node));

       assertF(tmpNode!=NULL,"in createNullList_Seq,tmpNode is null/n");

       tmpNode->info=Undefined;

       tmpNode->link=NULL;

       return tmpNode;

}

//在指定的位置插入数据

void insert_LinkList(LinkList* inLinkList,int pos,Type data)

{

       int i=0;

       LinkList* tmpListNode;

       LinkList newListNode,head;

      

       assertF(*inLinkList!=NULL,"in insert_LinkList,tmpNode is null/n");

       tmpListNode=(LinkList*)malloc(sizeof(struct Node*));

       head=(LinkList)malloc(sizeof(struct Node));

      

       head=*inLinkList;

       tmpListNode=inLinkList;

 

       //head and rear is insert operation's difficult.

              i=0;

              while(i<pos-1&&(*tmpListNode)->link)//stop at the insert node's pre node.

              {

                     *tmpListNode=(*tmpListNode)->link;

                     i++;

              }

              assertF(i==pos-1||pos==0,"in insert_LinkList,out of iterator error/n");

             

              if(pos==0&&(*inLinkList)->info==Undefined)

              {

                     (*tmpListNode)->info=data;

              }

              else if(pos==0)

              {

                     newListNode=(LinkList)malloc(sizeof(struct Node));

                     newListNode->link=*tmpListNode;

                     newListNode->info=data;

                     *tmpListNode=newListNode;

              }

              else

              {

                     newListNode=(LinkList)malloc(sizeof(struct Node));

                     newListNode->link=(*tmpListNode)->link;

                     newListNode->info=data;

                     (*tmpListNode)->link=newListNode;

                     *tmpListNode=head;//repoint to its head.

              }

 

}

 

 

//在指定位置删除元素:

void del_ElementLinkList(LinkList* inLinkList,int pos)

{

       int i=0;

       LinkList tmpListNode,delNode;

      

       assertF(*inLinkList!=NULL,"in del_ElementLinkList,inLinkList is null/n");

 

       tmpListNode=(LinkList)malloc(sizeof(struct Node));

       delNode=(LinkList)malloc(sizeof(struct Node));

 

       tmpListNode=*inLinkList;

      

       i=0;

       while(i<pos-1&&tmpListNode->link->link)//stop at the del node's position.

       {

              tmpListNode=tmpListNode->link;

              i++;

       }

       assertF(i==pos-1||pos==0,"in insert_LinkList,out of iterator error/n");

      

       if(pos==0&&(*inLinkList)->info==Undefined)

       {

              *inLinkList=NULL;//because this action have to use 2d pointer.

       }

       else if(pos==0)

       {

              delNode=*inLinkList;

              *inLinkList=(*inLinkList)->link;

              free(delNode);

       }

       else

       {

              delNode=tmpListNode->link;

              tmpListNode->link=tmpListNode->link->link;

              free(delNode);

       }

}

 

//遍历链表

void traversalLinkList(LinkList inLinkList)

{

       LinkList tmpListNode;

      

       assertF(inLinkList!=NULL,"in traversalLinkList,tmpNode is null/n");

      

       tmpListNode=(LinkList)malloc(sizeof(struct Node));

             

       tmpListNode=inLinkList;

       printf("===starting of traversalLinkList===/n");

       while(tmpListNode->link)

       {

              printf("%d->",tmpListNode->info);

              tmpListNode=tmpListNode->link;

       }

       printf("%d/n",tmpListNode->info);

       printf("====end of traversalLinkList====/n");

      

       tmpListNode=NULL;

}

 

//返回某个值在链表中第一次出现的位置 .

int locateDataInLinkList(LinkList inLinkList,Type searchData)

{

       LinkList tmpListNode;

       int pos,i;

      

       assertF(inLinkList!=NULL,"in traversalLinkList,tmpNode is null/n");

      

       tmpListNode=(LinkList)malloc(sizeof(struct Node));

             

       tmpListNode=inLinkList;

      

       pos=-1;

       i=0;

       while(tmpListNode)

       {

              if(tmpListNode->info==searchData)

              {

                     pos=i;

                     break;

              }

              tmpListNode=tmpListNode->link;//move forward.

              i++;

       }

      

       tmpListNode=NULL;

       return pos;

}

 

//得到链表中指定位置的值

Type retriveDataInLinkList(LinkList inLinkList,int pos)

{

      

       int i=0;

       LinkList tmpListNode;

              Type reData;

      

       assertF(inLinkList!=NULL,"in retriveDataInLinkList,inLinkList is null/n");

       tmpListNode=(LinkList)malloc(sizeof(struct Node));

       tmpListNode=inLinkList;

      

       i=0;

       //pos just stands for the step the head need to move.

       while(i<pos&&tmpListNode->link)//stop at the  pos node's position .

       {

              tmpListNode=tmpListNode->link;

              i++;

       }

       assertF(i==pos||pos==0,"in inLinkList,out of iterator error/n");//the forging steps

      

       reData=tmpListNode->info;

      

       return reData;

}

 

int isNullLinkList(LinkList inLinkList)

{

       return inLinkList==NULL||inLinkList==0;

}

 

3基于C++模版的链表实现:

#include "Global.h"

#include "MyAssert.h"

#include <stdlib.h>

#include <stdio.h>

#ifndef ELIST_H

       #define ELSIT_H

template<class T>

class eNode

{

       //friend class eList<T>;

       public:

              eNode();

              T data;

              eNode<T>* next;

};

 

template<class T> 

eNode<T>::eNode()

              {

                     next=NULL;

              }

 

template<class T>

class eList

       {

              public:

                     eList()

                     {

                            head=new eNode<T>;

                            assertF(head!=NULL,"in eList,head is NUll/n");

                            head->next=NULL;

                            head_defined=false;

                            length=0;

                     }

                     eList(T initValue);

                     ~eList();

                     bool isEmpty() const

                            {

                                   return !head_defined||head==NULL;

                            }

                     bool full() const;

                     T headData() const;

                    

                     eList<T>& addAtHead(const T inData);

                     eList<T>& addAtRear(const T inData);      

                     eList<T>& addAtPos(const T inData,long posIndex);

                           

                     T deEListAtPos(long posIndex);

                     T deFromHead();

 

                     //ulti operation.

                     void traverseFloat(char* outputFileName);

                     long getLength();

                     T& getDataAtPos(long posIndex);

              private:

                     eNode<T>* head;

                     bool head_defined;

                     long length;

       };

 

template<class T>

       eList<T>::eList(T initValue)

       {

              head=new eNode<T>;

              assertF(head!=NULL,"in eList,head is NUll/n");

              head->next=NULL;

              head->data=initValue;

              head_defined=true;

              length=0;

       }

      

template<class T>

       eList<T>::~eList()

       {

              eNode<T>* tmpNext;

              while(head)

              {

                     tmpNext=head->next;

                     delete head;

                     head=tmpNext;

              }

       }

      

template<class T>

       bool eList<T>::full()const

       {//So funny a function.

              eNode<T>* p=new eNode<T>;

             

              assertF(p!=NULL,"no new mem is omited to be applyed/n");

             

              delete p;

             

              return false;

       }

      

template<class T>

       T eList<T>::headData()const

       {

              assertF(!isEmpty(),"the queue is empty./n");

              return head->data;

       }

      

template<class T>

       eList<T>& eList<T>::addAtHead(const T inData)

       {

              if(!head_defined)

              {

                     head->data=inData;

                     head_defined=true;

              }

              else

              {

                     eNode<T>* tmpNode=new eNode<T>;

                     tmpNode->data=inData;

                     tmpNode->next=head;

                     head=tmpNode;

              }

              return *this;

       }

      

template<class T>

       eList<T>& eList<T>::addAtRear(const T inData)

       {

              eNode<T>* tmpNode=new eNode<T>;

              eNode<T>* p=new eNode<T>;

             

              tmpNode->data=inData;

             

              p=head;

              while(p->next)

              {

                     p=p->next;

              }

             

              assertF(p!=NULL,"in addAtRear p is NULL/n");

             

              p->next=tmpNode;

             

              return *this;

       }

template<class T>

       eList<T>& eList<T>::addAtPos(const T inData,long posIndex)

       {//this pos is just the same as in c lang,start from 0;

              long j;

              eNode<T>* tmpNode=new eNode<T>;

              eNode<T>* p=new eNode<T>;

             

              //data init

              tmpNode->data=inData;

              p=head;

              j=0;

 

             

              while(p&&j<posIndex-1)

              {

                     p=p->next;

                     j++;

              }

             

              if(!head_defined)

                     assertF(j==0&&posIndex,"in addAtPos, head is undefined/n");

              else if(posIndex==0)

                     assertF(j==0,"in addAtPos, error happens./n");

              else

                     assertF(j==posIndex-1,"in addAtPos,j!=posIndex-1/n");

             

              if(!head_defined)

              {

                     head->data=inData;

                     head_defined=true;

 

              }

              else if(posIndex==0)

              {

                     tmpNode->next=head;

                     head=tmpNode;

              }

              else

              {

                     tmpNode->next=p->next;

                     p->next=tmpNode;

              }

       //     cout<<posIndex<<" "<<endl;

              return *this;

       }

      

template<class T>

       T eList<T>::deFromHead()

       {

              eNode<T>* p=new eNode<T>;

              T tmpData;

             

              assertF(!isEmpty(),"in deFromHead, the list is empty/n");

             

              p=head;

              tmpData=head->data;

             

              head=head->next;

              delete p;

             

              return tmpData;

       }

      

template<class T>

       T eList<T>::deEListAtPos(long posIndex)

       {

              long j;

              eNode<T>* tmpNode=new eNode<T>;

              eNode<T>* p=new eNode<T>;

              T tmpData;

 

              //data init

              p=head;

              j=0;

              tmpData=head->data;

 

      

              assertF(head_defined,"in deEListAtPos,the head node is null/n");

 

              while(p&&j<posIndex-1)

              {

                     p=p->next;

                     j++;

              }

             

              assertF(p!=NULL,"in deEListAtPos,the posIndex has been out of bounds./n");

             

              if(posIndex==0)

                     assertF(j==0,"in deEListAtPos, head is undefined/n");

              else

                     assertF(j==posIndex-1,"in deEListAtPos,j!=posIndex/n");

             

              if(posIndex==0&&head->next==NULL)

              {

                     tmpNode=p;

                     p=p->next;

                     head=p;

                     head_defined=false;

                     delete tmpNode;

              }

              else if(posIndex==0&&head->next!=NULL)

              {

                     tmpNode=p;

                     p=p->next;

                     head=p;

                     delete tmpNode;

              }

              else

              {

                     tmpNode=p->next;

                     p->next=tmpNode->next;

                     delete tmpNode;

              }

 

              return tmpData;

       }

      

template<class T>

       void eList<T>::traverseFloat(char* outputFileName)

       {

              FILE* outputFile;

              eNode<T>* tmpNode=new eNode<T>;

              long count=0;

             

              assertF(outputFileName!=NULL,"in eList.traverse(),listFileName is null/n");

              assertF((outputFile=fopen(outputFileName,"wb"))!=NULL,"output file open error");

              assertF(!isEmpty(),"Warning,in traverseFloat,the list is null/n");

             

              tmpNode=head;

             

              while(tmpNode)

              {

                     fprintf(outputFile,"/r/n");

                     fprintf(outputFile,"%f ",tmpNode->data);

                     cout<<tmpNode->data<<" ";

                    

                     if((count+1)%50==0)

                            fprintf(outputFile,"/r/n");

                    

                     tmpNode=tmpNode->next;

                     count++;

              }

       }

 

template<class T>

       long eList<T>::getLength()

       {

              eNode<T>* tmpNode=new eNode<T>;

              long count=0;

              tmpNode=head;

             

              while(tmpNode)

              {

                     count++;

                     tmpNode=tmpNode->next;

              }

              assertF(tmpNode==NULL,"in getLength,tmpNode not reach to its end.");

             

              return count;

       }

      

template<class T> 

       T& eList<T>::getDataAtPos(long posIndex)

       {

              long j;

              eNode<T>* p=new eNode<T>;

             

              p=head;

             

              assertF(head_defined,"in getDataAtPos,the head node is null/n");

              /*init data*/

              j=0;

              while(p&&j<posIndex)

              {

                     p=p->next;

                     j++;

              }

             

              assertF(p!=NULL,"in deEListAtPos,the posIndex has been out of bounds./n");

              assertF(j==posIndex,"in deEListAtPos,j!=posIndex/n");

             

              return p->data;      

       }

#endif

 

这些操作的实现也是相对简单的,但是难点在于不要使链表断链以及指针的操作上.

C++版本模版的好处在于面向对象的数据结构表示要比面向过程的来得直接,而且数据的操作上相对简单(少去了参数传递(尤其是指针)的麻烦.)

好戏在后头…:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值