王道视频笔记
链表
一、单链表
1.1 单链表定义及初始化
/1.单链表定义
typedef struct LNode{ //LNode:结点
ElemType data; //数据域
struct LNode*next; //指针域,指向下个结点
}LNode,*LinkList;//LNode强调指结点,LinkList强调指单链表。
//不带头结点的单链表初始化
LinkList L ;
//初始化一个不带头结点的单链表
/*
&L直接引用实参,不会生成形参,因此省略了赋值操作这一步。
函数会直接对实参进行操作,因此会改变实参的值
*/
bool InitList(Linklist &L){
L = NULL; //空表,暂时无结点
return ture;
}
//带头结点的单链表声明
LinkList L ;//建立一个带头结点的空链表。
//初始化一个带头结点的单链表:不存储数据
bool InitList(Linklist &L){
L = (LNode*)malloc(sizeof(LNode));//分配一个头结点
if(L==NULL)//空间分配失败会返回空指针
return false;
L->next = NULL:
return ture;
}
1.2单链表插入
以下皆是带头结点单链表操作。
1.2.1按位序插入
bool ListInsert(Linklist &L,int i ,ElemType e){
if(i<1)//结点从1开始
return false;
LNode *p;//指针p指向当前扫描的结点
int j=0; //当前p指向第几个结点
p = L; //L 指向头结点不含数据,含有第一个结点的首地址,可以看做Node0
while(p!=NULL&&j<i-1){//找到i-1个结点
p = p->next;
j++;
}
if(p==NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));//为新结点分配空间
s->data = e;
s->next = p->next;//s结点 --> i结点
p->next = s; //i-1结点-->s结点
return true;
}
1.2.2指定结点后插入元素e
//在p结点后插入元素e
bool InsertNextNode(ElemType *p,ElemType e){
if(p==NULL)//该结点不存在
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
1.2.3指定结点前插入元素e
//在p结点前插入元素e
//当前p结点的数据后移到新结点 , 再将新结点的数据赋予p结点
bool InsertPreNode(ElemType *p,ElemType e){
if(p==NULL)//该结点不存在
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data = p->data;
p->data = e;
s->next = p->next;
p->next = s;
return true;
}
1.3删除
1.3.1按位序删除
bool ListDelete(Linklist &L,int i,ElemType &e){
if(i<1)
return false;
LNode*p;//指向当前扫描的结点
int j = 0;//扫描第几个结点
p = L; //结点0
while(p->next!=NULL&& j<i-1){//循环扫描到i-1结点
p = p->next;
j++;
}
if(p->next==NULL)//不存在i结点
return false;
LNode*temp = p->next;
e = temp->data;//保存数据
p->next = temp->next;
free(temp);
return false;
}
1.3.2指定结点删除
//如果p不是最后一个结点
bool ListDeleteNode (LNode *p){
if(p==NULL)
return false;
LNode *temp = p->next;//记录p后一结点,数据转移到p结点,删除后一个结点
p->data = p->next->data;
p->next = p->next->next;
free(temp);
return true;
}
//删除最后一个结点p
bool ListDeleteFinNode (Linklist &L,LNode *p){
if(p==NULL)
return false;
LNode *q =L;//由于是p是最后一个结点,只能从头查找。
while(q->next!=p){//找到前一个结点
q = q->next;
}
q->next = p->next;
free(p);
return true;
}
1.4、查找
1.4.1按位序查找
LNode * GetElem(LinkList L,int i){
if(i<0)
return NULL;//若i小于1,返回NULL,
LNode *p=L;
int j =0;
while(p!=NULL&&j<i){//若i大于实际节点数,返回NULL,若为0,返回LL
p = p->next;
j++;
}
return p;
}
1.4.2插入与删除用查找函数封装
//插入
bool ListInsert(Linklist &L,int i ,ElemType e){
if(i<1)//结点从1开始
return false;
//通过查找函数
LNode *p = GetElem(L,i-1);//找到i-1个结点
return InsertNextNode(p,e);
}
//删除
bool ListDelete(Linklist &L,int i,ElemType &e){
if(i<1)
return false;
//查找函数找到i结点
LNode*p = GetElem(L,i-1);
//删除指点结点函数
if(p==NULL&&p->next==NULL)//不存在i结点
return false;
LNode*temp = p->next;
e = temp->data;//保存数据
p->next = temp->next;
free(temp);
return false;
}
1.4.3按值查找
//按值查找
LNode * LocatElem(LinkList L,Elemtype e){
LNode *p = L->next;
//从第一个结点找起
while(p!=NULL&&p->data!=e)
p = p->next;
return p;//返回该结点,否则返回NULL
}
1.5 计算链表长度
int ListLength(LinkList L){
int len = 0;
LNode *p = L;
while(p->next!=NULL){
p = p->next;
len++;
}
return len;
}
1.5 判断链表是否为空
bool Empty(LinkList L){
if(L->next == NULL)
return true;
else
return false;
}
1.6 销毁链表
void DestoryList(LinkList &L){
LNode*temp;
while(L->next!=NULL){//删除头结点直至剩头结点
temp = L->next;
L-next = L->next->next;
free(temp);
}
free(L); //释放头结点
L =NULL; //指向NULL
}
二、链表建立
2.1尾插法建立单链表
LinkList list_TailInsert(LinkList &L){
int x; //ElemType:int
L = (LinkList)malloc(sizeof(LNode));
LNode*s,*r=L;
scnaf("%d",&x); //输入结点的值
while(x!9999){ //链表结束条件
s = (LNode*)malloc(LNode);
s->data = x;
r->next = s;
r =s; //r指向新的表尾结点,
scnaf("%d",&x);
}
r->next = NULL; //尾结点指向NULL;
return L;
}
2.2头插法建立单链表
//逆向插入
LinkList list_headInsert(LinkList &L){
int x; //ElemType:int
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
scnaf("%d",&x); //输入结点的值
while(x!9999){ //链表结束条件
s = (LNode*)malloc(LNode);
s->data = x;
s->next = L->next;
L->next = s;
scnaf("%d",&x);
}
return L;
}
三、双链表
3.1双链表结点类型定义
//***********************双链表结点类型********************
typedef struct DNode{
ElemType data; //数据域
struct DNode *prior,*next;//前驱指针和后继指针
}DNode,*DLinklist;
3.2 双链表初始化(带头结点)
//**********************初始化********************
bool InitDLinkList(DLinklist &L){
L = (DLinklist)malloc(sizeof(DNode));分配头结点
if(L==NULL)
return false;//内存分配失败
L->prior = NULL;
L->next = NULL;
return true;
}
3.3 双链表指定节点插入(带头结点)
//********************指定节点p后插入********************
//DNode p->s
bool InsertNextDNode(DNode*p,DNode*s){
if(p==NULL||s==NULL)
return false;
//后插:后-> 中s-> 前p
if(p->next != NULL)//后:p下个结点
p->next->prior = s;
s-next = p->next;//中:s
s->prior = p;
p->next = s;//前:p
}
//DNode s->p结点前插入
bool InsertNextDNode(DNode*p,DNode*s){
if(p==NULL||s==NULL)
return false;
//前插:前-> 中-> 后
p->prior->next = s;//前:s前一个结点
s->prior = p->prior;//中:s
s->next = p;
p->prior = s;//后:p
}
双链表按位序操作与单链表一样,如上注意前驱与后驱的赋值。
3.4 双链表是否为空(带头结点)
bool Empty(DLinklist L){
if(L->next == NULL)
return true;
else
return false;
}
3.5删除结点与销毁链表与单链表一样,就不写了。
四、循坏链表
最后一个节点指向第一个节点。