C、C++线性表基本操作的详细介绍

 更新时间:2020年11月05日 11:40:35   作者:zhen-yu  
这篇文章主要给大家介绍了关于C、C++线性表基本操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

线性表包括两部分顺序表和链表,是数据结构的基础,在此主要就算法进行分析和总结,作为记忆了解,未做具体实现。

提示:以下是本篇文章正文内容,下面案例可供参考

一、顺序表

#define LISST_INIT_SIZE 100
#define LISTINCREMENT 10
#define OK 0
#define OVERFLOW 1
typedef int ElemType;
typedef int Status;

1、定义

typedef struct{
			int* elem; //定义存储基地址
			int length; //当前顺序表长度
			int listsize; //当前分配的大小
			}SqList;

2、初始化构建

Status InitList_Sq(SqList &l){
	L.elem =(ElemType *)malloc(LISST_INIT_SIZE*sizeof(ElemType));
	if(!L.elem)
	exit(OVERFLOW);
	L.length=0;
	L.listsize=LISST_INIT_SIZE;
	return OK;

3、插入操作

在第i的位置插入元素e

1、算法解释

  1. 检查i的合法性
  2. 检查储存空间
  3. 标记插入位置
  4. 将插入位置后面的元素依次向下移动一位(注意从后往前依次移动,以移动位置小于插入位置结束循环)

2、算法实现

Status LIstInsert_Sq(Sqlist &L,int i, ElemType e){
SqList *newbase,*p,*q;
	//在第i个位子插入元素e
	if(i<1||i>L.length+1)
	return ERROR;
	//分配存储空间
	if(L.length>L.listsize){
		newbase=(ElemType *)realloc(l.elem,		(Listsize+LISTINCREMENT)*sizeof(ELemType);
	if(!newbase)
	exit(OVERFLOW);
	L.elem=newbase;
	L.listsize+=LISTINCREMENT;
	}
//记录插入位置
	q=&L.elem[i-1];
	for(p=L.elem[length-1];q<=p;p--)
	{
		*(p+1)=*p
	}
	*p=e;
	L.length++;//更新表长
	return OK;
}

4、删除操作

在第i的位置插入元素e

1、算法解释

  1. 检查i的合法性
  2. 记录删除的位子
  3. 找到删除元素并赋值给e
  4. 被删除元素后面的元素都想上移动一位(找到表尾元素,以移动位子地址大于表尾地址结束循环)

2、算法实现

Status LIstDelete_Sq(Sqlist &L,int i, ElemType &e){
SqList *p,*q;
	//在第i个位子删除元素
	if(i<1||i>L.length+1)
	return ERROR;
//记录删除位置
	p=&L.elem[i-1];
	e=*p;
	//表尾元素
	q=&L.elem[L.length-1];
	for(++p;p<=q;p++)
	{
		*(p-1)=*p;
	}
	L.length--;//更新表长
	return OK;
}

5、合并操作

已知La和Lb的元素按照非递减的顺序排列归并为Lc也为按值非递减排列

1、算法解释

  1. 记录La、Lb的操作地址
  2. 计算Lc的长度并为其分配空间
  3. 记录La、Lb的表尾位置
  4. 合并-比较两个表的元素,值较小的存入Lc(注意:以任意一表完全存入Lc结束循环)
  5. 检查La、Lb是否还有剩余元素,如果有剩余依次存入Lc

2、算法实现

void MergeList_Sq(SqList La,SqList Lb,SqList &Lc){
//分别记录La、Lb的当前操作地址
SqList *pa,*pb,*pc,*pa_last,*pb_last;
pa=La.elem;
pb=Lb.elem;
Lc.listsize=La.length+Lb.length;
pc=Lc.elem=(ElemType *)mallod(Lc.listsize*sizeof(ElemType);
if(!pc){
		exit(OVERFLOW);//分配失败
		}
		//记录顺序表尾的地址
pa_last=La.elem+La.length-1;
pb_last=Lb.elem+Lb.length-1;
while(pa<pa_last&&pb<pb_last){
	if(*pa<*pb)
	{
	 //*pc++=*pa++;
		*pc=*pa
		pc++;
		pa++;
	}
	else
	{
	//*pc++=*pb++;
		*pc=*pb;
		pc++;
		pb++;
	}
	while(pa<pa_last)
	{
		*pc++=*pa++;
	}
	while(pb<pb_last)
	{
		*pc++=*pb++;
	}
}

二、链表

#define OK 0
#define OVERFLOW 1
typedef int ElemType;
typedef int Status;

1.单链表

1、定义

typedef int ElemType;
typedef struct LNode{
	ElemType date;
	struct LNode *next;
	}LNode,*LinkList;

2、插入

在带头结点L中的第i个位置之前插入e

1、算法解释

  1. 找到第i-1个结点记录为P
  2. 判断是否找到该结点
  3. 生成新结点S赋值进行插入L中

2、算法实现

status ListInsert(LinkList &l,int i;ElemType e){
	LinkList p=L,S;
	int j=0;
	while(p&&j<i-1){
	p=p->next;
	j++;
	}
	if(!p||j>i-1)
	return ERROR;
	//生成新节点
	S=(LinkList)malloc(sizeof(LNode));
	S->date=e;
	S->next=p->next;
	p->next=S;
	return OK;
	}

3、删除

在带头结点的单链表L中删除第i个元素,并返回e

1、算法解释

  1. 记录头结点的位置
  2. 寻找第i个结点,并用p记录其前驱
  3. 检查删除位置的合理性
  4. 记录第i个结点,取其值赋值给e
  5. 将第i-1个结点指向i+1
  6. 释放第i个结点

2、算法实现

status ListDelete_L(LinkList &L,int i,ElemType &e){
LinkList p=L,q;
int j=0;
while(p->next&&j<i-1){
	p=p->next;
	j++;
}
if(!(p-next)||j>i-1)
return ERROR;
	q=p->next;
	p->next=q->next;
	e=q->date;
	free(q);
return OK;

4、查找

代码如下(示例):找到第i个位置的元素,并赋值给e

1、算法解释

  • 将p指向第一个结点
  • 寻找第i个结点(以p为空或者j>i结束循环)
  • 判断是否找到结点i
  • 取结点i的元素值

2、算法实现

status GetElem_L(LinkList L,int i,ElemType &e){
	LinkList p;
	int j=1;
	p=L->next;
	
	while(p&&j<i){
		p=p->next;
		j++;
		}
	if(!p||j>i)
		return ERROR;
	e=p->data;
	return OK;
	}

5、合并有序链表

已知La、Lb按值非递减 Lc也是按值非递减(带头结点)

1、算法解释

  1. 更新Pa、Pb、Pc的初始化位置都指向第一个结点
  2. 以Pa、Pb都非空为条件,比较其存储数据,较小的连接在Lc上,更新Pc和Pa(Pb)
  3. 插入剩余结点
  4. 释放未使用的空头结点

2、算法实现

void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
//记录结点
LinkList Pa,Pb,Pc;
Pa=La->next;
Pb=Lb->next;
Pc=Lc=La;
while(Pa&&Pb){

if(Pa->data<=Pb->data){
	Pc->next=Pa;
	Pc++;
	Pa++;
	}
else{
	Pc->next=Pb;
	Pc++;
	Pb++;
	}
}
Pc->next=pa? Pa:Pb;
free(Lb);
}

6、创建链表

输入n个元素的值,建立带头结点的单链表L

1、逆位序(头插法)

算法思路

  1. 创建头结点
  2. 循环插入结点
  3. 将新结点插入表头的后面
  4. 更新表头的next ##### 算法实现

算法实现

void GreateList_L(LinkList &L,int n){
//建立头结点
LinkList L,P;
L=(LinkList)malloc(sizeof(LNode);
L->next=NULL;
for(i=0;i<n;i++){
	P=(LinkList)malloc(sizeof(LNode);
	scanf("%d",&P->data);//以整型为例
	P->next=L->next;
	L->next=P;
	}
}

2、顺位序(尾插法)

算法思路

  1. 创建头结点
  2. 循环插入结点
  3. 将新结点插入表尾
  4. 记录表尾位置并更新

算法实现

void GreateList_L(LinkList &L,int n){
//建立头结点
LinkList L,P;
L=(LinkList)malloc(sizeof(LNode);
L->next=NULL;
Q=L;
for(i=0;i<n;i++){
	P=(LinkList)malloc(sizeof(LNode);
	scanf("%d",&P->data);//以整型为例
	Q->next=P
	Q=P;
	}
	q->next=NULL;
}

2.循环链表

与单链表类似,只是表尾结点的next指向了头结点,循环条件为是否等于表头元素,不再具体叙述!

3.双向链表

1、定义

//定义一个双向链表
typedef struct DuLNode{
	ELemType data;//数据元素
	struct DuLNode *prior;//前驱指针
	struct DuLNode *next;//后继指针
}DuLNode,*DuLinkList;

2、插入

在带头结点的双向循环链表L中的第i个结点(P)之前插入结点S的元素e

算法思路

  1. 检查i的合法性(1<=i<=表长+1)
  2. 插入

算法实现

S->data=e;//赋值
S-prior=p->prior;
P->prior->next=S;
S->next=P;
P->prior=S;

3、删除

在带头结点的双向循环链表L中删除第i个结点(P)并将其数据复制给元素e

算法思路

  1. 检查i的合法性(1<=i<=表长)
  2. 删除

算法实现

e=P->data;
q=P;
P->prior->next=P->next;
P->next->prior=P->prior;
free(q);//释放结点P

总结

到此顺序表和链表的基本操作算法基本介绍完成,希望能对初学者有所帮助,后续会对数据结构后面的内容进行更新。更多相关C、C++线性表基本操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现的顺序表功能完整实例

    C语言实现的顺序表功能完整实例

    这篇文章主要介绍了C语言实现的顺序表功能,结合完整实例形式分析了C语言顺序表的创建、添加、删除、排序、合并等相关操作技巧,需要的朋友可以参考下
    2018-04-04
  • 关于C++中的友元函数的一些总结

    关于C++中的友元函数的一些总结

    以下是对C++中的友元函数进行了详细的总结介绍,需要的朋友可以过来参考下
    2013-09-09
  • C++中临时对象的常见产生情况及其解决的方案

    C++中临时对象的常见产生情况及其解决的方案

    这篇文章主要是探讨常见的临时对象产生的情况,及其如何避免和解决这种临时对象产生的方式。具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • QT调用vs2019生成的c++动态库的方法实现

    QT调用vs2019生成的c++动态库的方法实现

    本文主要介绍了QT调用vs2019生成的c++动态库的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • 详解C语言之预处理(上)

    详解C语言之预处理(上)

    这篇文章主要介绍了C语言程序的预处理,小编觉得这篇文章写的还不错,需要的朋友可以参考下,希望能够给你带来帮助
    2021-11-11
  • C语言实现2048游戏

    C语言实现2048游戏

    这篇文章主要为大家详细介绍了C语言实现2048小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 深入理解C语言指针及占据内存空间

    深入理解C语言指针及占据内存空间

    这篇文章主要介绍了C语言指针及占据内存空间的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • Qt利用DOM类实现读取xml文件

    Qt利用DOM类实现读取xml文件

    Dom(Document Object Model,即文档对象模型)能把XML文档转换成应用程序可遍历的树形结构,这样便可以随机访问其中的节点。本文将详细讲讲实现的方法,需要的可以参考一下
    2022-06-06
  • Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect实例分析

    Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect实例分析

    这篇文章主要介绍了Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect实例分析,有助于更加直观的理解Object-C常用的结构体,需要的朋友可以参考下
    2014-07-07
  • C语言实现扫雷游戏(含注释详解)

    C语言实现扫雷游戏(含注释详解)

    这篇文章主要为大家详细介绍了C语言实现扫雷游戏,含注释,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06

最新评论