链表
一.单链表
1.单链表的定义
typedef int ElemType;
typedef struct LNode
{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList;
2.初始化单链表(不带头节点)
LinkList L:强调他是一个单链表时使用
LNode *L:强调是一个节点时使用
bool InitList(LinkList &L){
L=NULL;
return true;
}
3.判断单链表是否为空
bool Empty(LinkList L){
return (L==NULL);
}
4.初始化单链表(带头节点)
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头节点
if(L=NULL) return false;//内存不足,分配失败
L->next=NULL;//头节点之后暂时没有节点
return true;
}
5.按位序插入(带头结点)
在第i个位置插入元素e
bool ListInsert(LinkList &L,int i,ElemType e){
if (i<1) return false;
LNode *p; //指针P指向当前扫描的结点
int j=0 ;//当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点
while (p!=NULL&&j<i-1)
{
p=p->next;
j++;
}
if (p==NULL) return false;
LNode *S = (LNode *)malloc(sizeof(ElemType));
S->data=e;
S->next=p->next;
p->next=S;
return true;
}
6.按位序插入(不带头结点)
bool ListInsert(LinkList &L,int i,ElemType e){
if (i<1) return false;
if (i==1)
{
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true;
}
LNode *p;
int j=1;
p=L;
while (p!=NULL&&j<i-1)
{
p=p->next;
j++;
}
if (p==NULL) return false;
LNode *S = (LNode *)malloc(sizeof(ElemType));
S->data=e;
S->next=p->next;
p->next=S;
return true;
}
7.前插操作
bool InsertPriorNode(LNode *p ,ElemType e){
if (p=NULL) return false;
LNode *S = (LNode *)malloc(sizeof(ElemType));
if (S==NULL) return false; //内存分配失败
S->next=p->next;
p->next=S;
S->data=p->data;
p->data=e;
return true;
}
8.按位序删除
bool ListDelete(LinkList &L ,int i,ElemType &e){
if (i<1) return false;
LNode *p; //指针P指向当前扫描的结点
int j=0 ;//当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点
while (p!=NULL&&j<i-1)
{
p=p->next;
j++;
}
if (p==NULL) return false;
if (p->next==NULL) return false;
LNode *q = p->next; //令Q指向被删除结点
e=q->data; //返回元素的值
p->next = q->next;
free(q);
return true;
}
9.删除指定结点p
bool DeleteNode(LNode *p){
if (p==NULL) return false;
LNode *q=p->next;
p->data=p->next->data; //和后继结点交换数据 //如果在表尾则不可行
p->next=q->next;
free(q);
}
10.单链表的查找
LNode * GetElem(LinkList L ,int i){
if (i<0) return NULL;
LNode *p; //指针P指向当前扫描的结点
int j=0 ;//当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点
while (p!=NULL&&j<i)
{
p=p->next;
j++;
}
return p;
}
11.按值查找
LNode * LocateElem(LinkList L ,ElemType e){
LNode *p = L->next;
while (p!=NULL&&p->data!=e) p=p->next;
return p;
}
-
尾插法
LinkList list_TailInsert(LinkList &L){
int x ;
L=(LinkList)malloc(sizeof(LNode)); //建立头结点
LNode *s, *r=L;
scanf("%d",&x);
while (x!=9999)
{
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
13.头插法
LinkList list_HeaderInsert(LinkList &L){
int x ;
LNode *s;
L=(LinkList)malloc(sizeof(LNode)); //建立头结点
L->next=NULL;
scanf("%d",&x);
while (x!=9999)
{
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
二.双链表
1.定义
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data; //数据域
struct LNode *prior , *next; //指针域
}DNode,*DLinkList;
2.初始化双链表
bool InitDLinkList(DLinkList &L){
L=(DNode *)malloc(sizeof(DNode));
if(L==NULL) return false;
L->prior=NULL;
L->next=NULL;
return true;
}
3.双链表的插入 p结点插入s结点
bool InsertNextDNote(DNode *p,DNode *s){
if (p==NULL||s==NULL) return false; //非法参数
s->next=p->next;
if(p->next!=NULL) p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
4.删除p结点的后继结点q
bool DeleteNextDNode(DNode *p){
if (p==NULL) return false;
DNode *q= p->next; //找到p结点的后继结点
if(q==NULL) return false; //p没有后继
p->next=q->next;
if(q->next!=NULL) q->next->prior=q;
free(q);
return true;
}
5.销毁双链表
void DestoryList(DLinkList &L){
// 循环释放数据结点
while (L->next!=NULL)
DeleteNextDNode(L);
free(L);
L=NULL;
}
6.双链表的遍历
// 后向遍历
while (p!=NULL)
{
p=p->next;
}
// 前向遍历
while (p!=NULL)
{
p=p->prior;
}
// 前向遍历(跳过头结点)
while (p->prior!=NULL)
{
p=p->prior;
}
三.循环单链表
1.初始化循环单链表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode));//分配一个头节点
if(L=NULL) return false;//内存不足,分配失败
L->next=L;//头结点next指向头结点
return true;
}
2.判断循环单链表是否为空
bool Empty(LinkList L){
if(L->next==L) return true;
else return false;
}
3.判断结点p是否为末尾结点
bool isTail(LinkList L,LNode *p){
if (p->next==L) return true;
else return false;
}
四.循环双链表
1.初始化循环双链表
bool InitDLinkList(DLinkList &L){
L=(DNode *)malloc(sizeof(DNode));
if(L==NULL) return false;
L->prior=L;
L->next=L;
return true;
}
2.循环双链表 p结点插入s结点
bool InsertNextDNote(DNode *p,DNode *s){
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
五.静态链表
静态链表:数组的方式实现链表
1.静态链表的定义
typedef struct
{
ElemType data; //存储数据元素
int next; //下一个元素的数组下标
}SLinkList[MaxSize];
2.优缺点
- 优点:增、删操作不需要移动大量元素
- 缺点:不能随机存取,只能从头结点开始依次往后查找:容量固定不可变。