王道其他链表

一、双链表
1.要访问某个结点的前驱结点(插入、删除操作时),只能从头遍历,访问后续结点的时间复杂度O(1),访问前驱结点的时间复杂度O(n)
2.引入双链表,双链表结点中有两个指针prior 和next
3.双链表中的按值查找和按位查找的操作和单链表相同,但双链表在插入和删除操作的实现上,与单链表有较大不同
4.双链表的建立以及初始化

typedef struct DNode{
   ElemType data;
   struct DNode *prior,*next;
}DNode,*DLinkList;
// 初始化双链表
bool InitDLinkList(InitDList){
    L=(DNode *)malloc(sizeof(DNode));
    if(L==NULL)
        return false;
    L->prior = NULL;
    L->next=NUll;
    return true;

}
//判断双链表是否为空
bool Empty(DLinkList L){
   if (L->next == NULL)
      return true;
   else 
    return false;
}
int main()
{
    DLinkList L;
    InitDLinkList(L);
    return 0;
}

5.双链表的插入操作
(1)//给结点,前插:在p结点之后插入s结点

bool InserNextDNode(DNode *p,DNode *s){
     if(p==NULL|| s== NULL)
        return false;
     s->next=p->next;     ---------if(p->next!=NULL)
        p->next->prior=s;  ----------②             如果p结点之后没有后继,则没有
     s->prior = p;    -------- ③                   判断的话就会出错
     p->next=s;  ---------return true;
}

注意:1 2步骤必须在4前面
(2)给值,后插

//插入操作-指定结点后插2-给元素值
bool InsertNextDNode2(DNode* p, ElemType e) {
	if (p == NULL)		//非法参数
		return false;
	DNode* q = p->next;		//q为p原先的后继结点
	DNode* s = (DNode*)malloc(sizeof(DNode));	//s为p新的后继结点
	if (s == NULL)
		return false;		//内存不足,分配失败
	s->data = e;	//为新结点赋值
	s->next = q;
	if(q!=NULL)			//判断q是不是最后一个结点
		q->prior = s;		//如果是,则跳过此句,因为q为NULL,没有前驱
	s->prior = p;
	p->next = s;
	return true;
}

(3)给定结点前插操作

bool InsertPriorDNode(DNode* p, DNode* s) {
	DNode* q = p->prior;	//先找到p的前驱结点q
	return InsertNextDNode1(q, s);	//对q进行后插操作
}

(4)按位前插

bool InsertDLinkList(DLinkList& L, int i, ElemType e) {
	DNode* p = GetElem(L, i-1);		//按位查找i-1个结点p
	return InsertNextDNode2(p, e);	//对p结点进行后插操作
}

6.双链表的删除操作

//删除p结点的后继结点
bool DeleteNextDNode(DNode *p){
     if(p==NULL)  return false;
     DNode *q=p->next;
     if(q==NULL) return false;
     p->next=q->next;
     if(q->next!=NULL)
        q->next->prior=p;
     free(q);
     return true;
}

7.链表销毁

//链表销毁
void DestoryList(DLinkList &L){
   //循环释放各个数据结点
   while(L->next!= NUll){
    DeleteNextDNode(L);
    free(L);
    L=NULL;
   }

8.链表遍历

//双链表的遍历
//后向遍历
while(p!=NULL){
    p=p->next;
}
//前向遍历
while(p!=NULL){
    p=p->prior;
}
//前向遍历(跳过头结点)
while (p->prior!=NULL){
    p=p->prior;
}

9.求表长

int Length(DLinkList L) {
	int len = 0;
	DNode* p = L->next;
	while (p != NULL) {
		p = p->next;
		len++;
	}
	return len;
}

二、循环链表

1.初始化循环链表以及判断为空

typedef struct DNode{
   ElemType data;
   struct DNode *next;
}LNode,*LinkList;
// 初始化循环链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));
    if(L==NULL)
        return false;
    L->next=L;
    return true;
}
//判断是否为空
bool Empty(LinkList L){
   if (L->next ==L)
      return true;
   else 
    return false;
}
//判断结点p是否为循环单链表的表尾结点
bool isTail(LinkList L,LNode *p){
   if(p->next==L)
    return true;
   else 
    return false;}

2.循环双链表

//初始化空的循环双链表
bool InitDLinkList(DLinkList &L){
   L=(DNode *)malloc(sizeof(DNode));
   if (L==NULL)
    return false;
   L->prior=L;
   L->next=L;
   return true;
}
//判断循环双链表是否为空
bool Empty(DLinkList L){
   if (L->next == L)
        return true;
   else 
    return false;
}
//判断结点p是否为循环双链表的表尾结点
bool isTail(DLinkList L,DNode *p){
   if(p->next==L)
    return true;
   else
    return false;
}

1.循环单链表与单链表的区别在于,表中最后一个结点的指针不是NULL,而是改为指向头结点,形成一个环
2.循环单链表的判空条件不是头结点的指针是否为空,而是它是否等于头结点
3.循环单链表的插入、删除、与单链表几乎一致,不同的是表尾操作
4.单链表只能从头结点开始遍历后续结点,但是循环单链表可以从表中任意一个结点开始遍历整个链表。因此有时候对于循环单链表不设头指针而设尾指针,有时候会更加高效。
5.如果设的是头指针,那么对表尾操作需要O(n),设的是尾指针r,r->next表示的是表头,对表头表尾操作只需要O(1)
6.循环双链表,当结点为尾结点,->next= L,当循环双链表为空表,其头结点的prior next都等于L

三、静态链表
1.静态链表借助数组来描述线性表的链式存储结构。
2.需要事先分配一块连续的内存空间
3.每个数据元素4B,每个游标4B(每个结点共8B)设起始地址为addr,e1的存放地址为addr +8*2
4.描述

struct Node{
   Elemtype data;
   int next;
};
Typedef struct Node SlinkList[MaxSize];

5.课本上的

typedef struct{
   Elemtype data;
   int next;
}SLinkList[MaxSize];

int main()
{
   SLinkList a;
    return 0;
}

6.初始化静态链表:把a[0]的next设为-1
7.查找:从头结点出发挨个往后遍历结点O(n)
8.插入位序为i的结点:
①找到一个空结点,存放数据元素
②从头结点出发找到位序为i-1的结点
③修改新结点的next
④修改i-1号结点的next
9.初始化时就把每一个的next设为-2等特定数据
10.优点:增删操作不需要大量移动元素
11.缺点:不能随机存储,只能从头结点开始一次往后查找:容量固定不可变
12.适用场景:
①不支持指针的低级语言
②数据元素数量固定不变的场景(操作系统的文件分配表FAT)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值