分享
 
 
 

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

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

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

好戏在后头…:

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有