3.16/17链表

一.单链表

建表:建表的时候要记得给链表L分配一个新的空间,并让头指针指向NULL

L = (LinkList)malloc(sizeof(LinkList));
L->next = NULL;
#include <cstdio>
#include <cstdlib>
typedef struct LNode{
    int data;
    LNode* next;
}LNode,*LinkList; //定义结构体和结构体指针
//①头插法建立单链表
LinkList CreateList1(LinkList &L1)  //这里要加& ?背住吧。
{
    //首先要创建头结点,结合C对malloc的理解,返回的是一个指针,所以不是(LinkList*)
    //又因为要开辟的空间就是一个LNode,而不是多少个字节,所以不是(?*sizeof(int))
    L1=(LinkList)malloc(sizeof(LNode));
    L1->next=NULL;   //很重要指针必须初始化!!!
    
    for(int i=0;i<7;i++)
    {
     LNode *p=(LNode*)malloc(sizeof(LNode));
     p->data=i;
     
     p->next=L1->next;
     L1->next=p;   
    }
    return L1;  //void不行??
}
//②尾插法建立单链表
LinkList CreateList2(LinkList &L)
{
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    LNode *s,*real=L;
    for(int i=0;i<7;i++)
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=i;
        rear->next=s; //将节点s接到尾巴后面,r指向新的尾结点 
        
        rear=s;
    }
    rear->next=NULL; //千万要记得将尾结点的指针域置空啊 
    return L;
}
void PrintList(LinkList &L)  //这里也加& ?
{
    //LNode *p=(LNode*)malloc(sizeof(LNode));
    //p=L;
    LNode *p=L->next;
   // while(p->next!=NULL)
    while(p!=NULL)
    {
        //printf("%d",p.data);
        printf("%d",p->data);
        p=p->next;
    }
}
int main()
{
    //要表示一个单链表时,只需声明一个头指针L,指向单链表的第一个结点。
    //LNode *L  与LinkList L1可读性更强
    LinkList L1,L2;  //指针初始化的工作在具体函数里面做??
    CreateList1(L1);
    PrintList(L1);
    CreateList2(L2);
}

总结:剩下的代码看看书就可以了,都不难,就建表会建就行了。注意一下LinkList L有没有加&,

二.双链表

总结感悟:其实就是比单链表多了一个prior指针,因此增删改要稍微多一点步骤,用画图的方式会更清楚。由于没有顺序表“随机存取”的特点,要找一个东西,必须遍历。

①声明结构体,初始化

typedef struct DNode
{
	int data;
	struct DNode *prior,*next;
 } DNode,*DLinklist;
 void Init(DLinklist &L)
 {
 	L=(DLinklist)malloc(sizeof(DNode));
 	L->next=NULL;
 	L->prior=NULL;
 }

②插入
插入建议掌握尾插法,如此:头插法可以用:找到结点的前一个结点再尾插。按位序插入:遍历到位置后再尾插。
步骤:四条线四个步骤
在这里插入图片描述注意判断插入的位置是否是最后一个(也就是主要判断黄色线,如果不是最后一个结点,该结点的prior应该指回e):
在这里插入图片描述

//头插法建立双链表 
DLinkList Head_List(DLinkList &D){
	D =(DLinkList)malloc(sizeof(DNode));//头节点 
	D->next=NULL;//空链表初始化,首尾指针都置为空 
	D->prior=NULL;
	DNode *s;//用于指向新节点的指针 
	int x;
	printf("请输入数据,输入9999代表结束\n"); 
	scanf("%d",&x); 
	while(x!=9999){
		s=(DNode*)malloc(sizeof(DNode));
		s->data=x;
		s->prior=D->prior;
		D->prior=s;
		s->next=D->next;
		D->next=s; 
		scanf("%d",&x);
	}
	return D;
} 
0

③删除,与插入同理:
注意:如果要销毁表,需要删除所有节点(引用DeleteNextDNode函数),最后释放头结点(free(L);L->next=NULL;//彻底销毁!!!)
在这里插入图片描述看PPT上的代码也可

bool deleNode(LinkDNode *L, int index){
	if (L->length == 0)
		return false;
	if (index < 0||index>L->length-1){
		return false;
	}
	DNode *p = L->head;
	for (int i = 0; i < index - 1;i++){
		p = p->next;
	}
	DNode *dNode = p->next;//要删除的结点
	p->next = dNode->next;
	dNode->next->prior = dNode->prior;
	free(dNode);
	L->length--;
	return true;
}

③遍历:核心是判断结点是否是表尾/头结点。除了向后遍历还可以向前遍历,还可以跳过头结点。

3.17

三、循环链表

循环单链表:设置尾指针r,当大量操作再头尾进行时比较方便,因为尾指针找到头结点的时间复杂度是O(1)
循环双链表:主要注意初始化、判断是否为空,根据定义有点不一样(看图理解)
在这里插入图片描述PPT还是很清楚的,看PPT
循环双链表相比双链表来说:插入和删除不需要在多判断是否是表尾着一个条件

四.静态链表

用数组的方式实现链表,虽然连续内存,但逻辑相邻(游标确定)不一定物理相邻。
代码见PPT

总结:代码方面
①初始化的核心是如何判空。
②遍历的核心是判断结点是否是头/尾。
③表头、表中、表为插入/删除一个结点,考虑特殊情况

比较总结的那个视频没有看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值