【数据结构】线性表的知识点全面总结

目录

1.线性表的顺序表示

    1.1顺序表的基本概念 

    1.2顺序表的基本操作 

         1.2.1插入

         1.2.2删除

         1.2.3查找 

2.线性表的链式表示

    2.1单链表

         单链表的基本概念

         2.1.1基本操作

               2.1.1.1单链表的建立

               2.1.1.2插入

               2.1.1.3删除

               2.1.1.4查找 

    2.2双链表

         2.2.1基本操作

               2.2.1.1插入

               2.2.1.2删除

               2.2.1.3遍历

    2.3循环链表

         2.3.1循环单链表

         2.3.2循环双链表 

               2.3.2.1循环双链表的插入

               2.3.2.2循环双链表的删除 

3.静态链表

4.顺序表和链表的比较 


1.线性表的顺序表示

1.1顺序表的基本概念 

存储结构:逻辑上相邻的数据元素物理上也相邻。

实现方式分为:静态分配和动态分配

静态分配:使用静态数组实现,大小一旦确定无法改变。

动态分配:使用动态数组实现,顺序表存满时可以用malloc动态扩展顺序表的最大容量,需要将数据元素复制到新的存储区域,并用free函数释放原区域。

1.2顺序表的基本操作 

1.2.1插入

最好时间复杂度:O(1)

最坏时间复杂度:O(n)

平均时间复杂度:O(n)

//插入
bool ListInsert(SqList &L,int i,int e)
{
	if (i < 1 || i > L.length + 1)         //判断i是否合法
		return false;
	if (L.length >= MaxSize)             //判断是否存满
		return false;
	for (int j = L.length;j >= i;j--)//插入结点的位置之后的元素依次后移
		L.data[j] = L.data[j - 1];
	L.data[i - 1] = e;                     //插入e
	L.length++;               //顺序表长度加一
	return true;
}

1.2.2删除

最好时间复杂度:O(1)

最坏时间复杂度:O(n)

平均时间复杂度:O(n)

//删除
bool ListDelete(SqList& L, int i, int e)
{
	if (i < 1 || i > L.length + 1)//判断i是否合法
		return false;
	e = L.data[i - 1];        //将删除结点位置的元素值赋给e
	for (int j = i;j < L.length;j++)//删除结点后面的元素依次前移
		L.data[j - i] = L.data[j];
	L.length--;              //顺序表长度减一
	return true;
}

1.2.3查找 

查找方式有按位查找和按值查找。

按位查找
//按位查找
int GetElem(SqList L, int i)
{
	return L.data[i - 1];
}

按值查找

最好时间复杂度:O(1)

最坏时间复杂度:O(n)

平均时间复杂度:O(n)

//按值查找
int LocateElem(SqList L.int e)
{
	for (int i = 0;i<L>length;i++)
		if (L.data[i] == e)
			return i + 1;
	return 0;
}

注意:C语言中,结构体的比较不能直接用“==” 

2.线性表的链式表示

2.1单链表

单链表的基本概念 

定义:线性表的链式存储。

两种实现方式:带头结点和不带头结点

带头结点的空表判断:L->next==NULL

不带头结点的空表判断:L==NULL

头结点和头指针的区分:不管带不带头结点,头指针都始终指向链表的第一个结点,而头结点时带头结点的链表中的第一个结点,结点内通常不存储信息。

2.1.1基本操作

2.1.1.1单链表的建立
头插法

应用:链表的逆置(带头结点的单链表的就地逆置:http://t.csdn.cn/J6bph) 

// 头插法建立单链表
LinkList List_HeadInsert(LinkList &L)
{
	LNode* s;
	int x;
	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;          //将新结点插入表中,L为头指针
		scanf("%d", &x);
	}
	return L;
}

尾插法
//尾插法
LinkList List_TailInsert(LinkList& L)
{
	int x;
	L = (LinkList)malloc(sizeof(LNode));//创建头结点
	LNode* s, * r = L;      //r为表尾指针
	scanf("%d", &x);
	while (x != 9999)
	{
		s = (LNode*)malloc(sizeof(LNode));  //创建新的结点
		s->data = x;
		r->next = s;                 
		r = s;                      //r指向新的表尾结点
		scanf("%d", &x);
	}
	r->next = NULL;
	return L;
}

2.1.1.2插入
后插 
//插入(后插)
s->next = p->next;
p->next = s;

前插
//插入(前插)
s->next = p->next;
p->next = s;
temp = p->data;    //交换数据域(偷天换日)
p->data = s->data;
s->data = temp;

2.1.1.3删除
按位序删除
p = GetElem(L, i - 1);  //查找删除位置的前驱节点
q = p->next;            //令q指向被删除结点
p->next = q->next;      //将*q结点从链中断开
free(q);                //释放结点的存储空间

指定结点删除

如果指定结点是最后一个结点时,需要特殊处理

q = p->next;            //令q指向*p的后继结点
p->data = p->next->data; //用后继结点的数据域覆盖
p->next = q->next;       //将*q结点从链中断开
free(q);                 //释放结点的存储空间

2.1.1.4查找 

 按位查找,按值查找,求单链表的长度

2.2双链表

2.2.1基本操作

2.2.1.1插入
1.s->next = p->next;
2.if(p->next!=NULL)
	p->next->prior = s;
3.s->next = p;
4.p->next = s;

上述代码的语句顺序不是唯一,但是1和2必须在4之前,否则会出现断链。 

2.2.1.2删除
//删除双链表结点*p的后继结点*q
bool DeleteNextNode(DNode* p)
{
	if (p == NULL)
		return false;
	DNode* q = p->next;//找到p的后继结点q
	if (q == NULL)      //p没有后继
		return false;
	p->next = q->next;
	if(q->next!=NULL)   //q不是最后一个结点
		q->next->prior = p;
	free(q);
	return true;
}
2.2.1.3遍历
后向遍历
//后向遍历
while (p != NULL)
{
	p = p->next;
}
前向遍历 
//前向遍历
while (p != NULL)
{
	p = p->prior;
}
//前向遍历(跳过头结点)
while (p->prior != NULL)
{
	p = p->prior;
}

2.3循环链表

2.3.1循环单链表

表尾结点的next指针指向头结点 

2.3.2循环双链表 

 表尾结点的next指针指向头结点 ;

 表头结点的prior指针指向表尾结点

2.3.2.1循环双链表的插入
//循环双链表的插入
/ bool InsertNextDNode(DNode * p, DNode * s)
{
	s->next = p->next;
	p->next->prior = s;
	s->prior = p;
	p->next = s;
}
2.3.2.2循环双链表的删除 
//循环双链表的删除 
p->next = q->next;
q->next->prior = p;
free(q);

3.静态链表

分配一整片的连续空间,容量固定不变,结束标志:next == -1

优点:增,删操作不需要大量移动元素。

缺点:不能随机存取,只能从头结点开始依次往后查找。 

4.顺序表和链表的比较 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
1. 线性表的定义和基本操作 - 线性表是一种数据结构,由零个或多个数据元素组成,数据元素之间是有序的,且每个数据元素只有一个前驱和一个后继。 - 基本操作包括插入、删除、查找、遍历等。 2. 线性表的顺序存储结构 - 线性表的顺序存储结构是指将线性表的数据元素存储在一段连续的存储单元。 - 顺序存储结构的优点是随机存取,操作简单高效。 - 顺序存储结构的缺点是插入、删除操作需要移动大量元素。 3. 线性表的链式存储结构 - 线性表的链式存储结构是指将线性表的数据元素存储在一些不连续的存储单元,这些存储单元可以是任意的物理位置。 - 链式存储结构的优点是插入、删除操作方便,不需要移动元素。 - 链式存储结构的缺点是不能随机存取,需要遍历整个链表才能访问某个元素。 4. 线性表的单链表和双向链表 - 单链表是指每个节点只有一个指针指向下一个节点。 - 双向链表是指每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。 5. 线性表的循环链表 - 循环链表是指链表的最后一个节点的指针指向链表的第一个节点,形成一个环。 - 循环链表可以解决单链表遍历到最后一个节点时需要特殊处理的问题。 6. 线性表的静态链表 - 静态链表是指使用数组来实现链表的存储结构。 - 静态链表可以解决动态分配内存的问题,但是插入、删除操作仍然需要移动元素。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十三衙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值