数据结构_链表

103 阅读4分钟

链表

一.单链表

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;
}
  1. 尾插法

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.优缺点

  • 优点:增、删操作不需要移动大量元素
  • 缺点:不能随机存取,只能从头结点开始依次往后查找:容量固定不可变。