定义一个结点
typedef struct ElemType{char name[20];int sex;int age;char number[11];
};//定义一个结点
typedef struct Lnode{ ElemType data;struct Lnode* next;
}LNode,*LinkList;
链表的初始化
一般包含两步:给结点分配空间,头指针指针域为空
相当于建立一个空表
/*链表初始化,头结点指针域为空 */
Status InitList_L(LinkList &L){ //L为指向头结点的指针 L=(LinkList)malloc(sizeof(LNode)); //L中存放着头结点的地址L->next=NULL; return OK;
}
单链表的简单操作
单链表的销毁
/*销毁单链表(头结点,头指针都不存在)*/
Status DestoryList_L(LinkList &L){ //L为指向头结点的指针 Lnode * p; //或者LinkList p;while(L){ p=L; //p和L指向同一个结点 L=L->next; //L向后移动一个 free(p); //释放p } return OK;
}
清空单链表
/*清空单链表*/
Status ClearList(LinkList &L){Lnode *p,*q;p=L->next; //p指向首元结点 while(p){q=p->next; //q指向p后面的结点 free(p); //释放p p=q; //p,q指向同一结点 }L->next=NULL;return OK;
}
清空链表与销毁链表的不同在于:清空会保留单链表的头结点和头指针,相当于一个空表,而小胡链表,整个表都不存在。
求单链表的表长
/*求单链表的表长*/
int ListLength_L(LinkList &L){LinkList p;p=L->next; //p指向首元结点 int i=0;while(p){ //遍历单链表 i++;p=p->next;} return i;
}
单链表的基本操作
查找
取出链表中第i个元素的内容
/*取出链表中第i个元素的内容*/
//<1>从第一个结点顺着链表扫描,p=L->next;
//<2>j做计数器,初始值为1,记录已扫描的结点的个数
//<3>p向后移动,j++
//<4>当j==i时找到该结点
Status GetElem_L(LinkList &L,int i,ElemType &e){ /*通过变量e返回*/ LinkList p;p=L->next;j=1;while(p&&j<i){p=p->next;++j;}if(!p||j>i){ //第i个元素不存在 return ERROR;}e=p->data;return OK;
}
根据指定数据元素获取该数据所在的位置
/*根据指定数据元素获取该数据所在的位置*/
Lnode * LocateElem_L(LinkList &L,ElemType e){ //查找值为e的元素 p=L->next;while(p&&p->data!=e){p=p->next;}return p; //若找到,则返回该值的地址,查找失败就返回NULL
}
根据指定数据元素获取该数据的序号
跟上面根据指定数据元素获取该数据所在的位置有点类似,只是多了一个计数器
/*根据指定数据元素获取该数据的序号*/
Lnode * LocateElem_L(LinkList &L,ElemType e){ //查找值为e的元素 p=L->next;j=1;while(p&&p->data!=e){p=p->next;j++;}if(p){return j;}else{return 0;}
}
插入
在单链表的第i个结点前插入值为e的结点
/*在单链表的第i个结点前插入值为e的结点*/
//<1>找到a(i-1)的位置p
//<2>生成一个数据域为e的新结点
//<3>插入新结点 //新结点的指针域指向a(i);//结点a(i-1)的指针域指向新结点
Status ListInsert_L(LinkList &L,int i,ElemType e){p=L;j=0;while(p&&j<i-1){ //找到第i-1个结点 p=p->next;++j;}if(!p||j>i-1){ //第i-1个元素不存在 return ERROR;}s=(LinkList)malloc(sizeof(LNode));s->next=p->next; //新结点的指针域指向a(i);p->next=s; //结点a(i-1)的指针域指向新结点return OK;
}
删除
删除第i个结点
/*删除第i个结点*/
//<1>找到a(i-1)的位置p,(如需必要保存结点i的值)
//<2>令p->next指向a(i+1)
//<3>释放a(i)的空间
Status ListDelete_L(LinkList &L,int i,ElemType &e){p=L;j=0;while(p&&j<i-1){ //找到第i-1个结点 p=p->next;++j;}if(!p||j>i-1){ //第i-1个元素不存在 return ERROR;}q=(LinkList)malloc(sizeof(LNode));q=p->next; //结点i p->next=q->next; //令p->next指向a(i+1)e=q->data; //保存结点i的值free q;return OK;
}
//查找:因为线性链表只能顺序存取,所以要从头查找,时间复杂度为O(n)
//插入,删除:因为线性链表不用移动元素,只用修改指针,一般情况下时间复杂度为O(1),但是要在单链表中进行,要从头找到相应的前驱结点,时间复杂度为O(n)
单链表的建立
头插法建立单链表
/*头插法建立单链表*/
//<1>从一个空表开始,重复读入数据
//<2>生成新的节点,将读入的数据放在结点的数据域中
//<3>从最后一个结点开始依次将各结点插入到链表前端
void CreateList_H(LinkList &L,int i){ //i为结点个数 L=(LinkList)malloc(sizeof(LNode));L->next=NULL; //建立一个空表for(int i=0;i<n;i++){p=(LinkList)malloc(sizeof(LNode));p->data=读取数据元素;p->next=L->next; //链表的插入 L->next=p;}
尾插法建立单链表
/*尾插法建立单链表*/
//<1>从一个空表开始,将新的结点依次插入到链表尾部,尾指针r指向尾节点
//<2>开始时L与r均指向头结点,每个数据元素申请一个新结点,r指向新结点
void CreateList_R(LinkList &L,int i){L=(LinkList)malloc(sizeof(LNode));L->next=NULL;LinkList r;r=L;for(int i=0;i<n;i++){p=(LinkList)malloc(sizeof(LNode));p->data=读取数据元素;p->next=NULL;r->next=p; //插到表尾 r=p; //指向新结点 }
}