数据结构算法代码总结

第二章 线性表

循环双链表

以下四句代码任意一个为真,都可以说明循环双链表为空

head->next==head; 
head->prior==head;
head->next==head&&head->prior==head;
head->next==head||head->prior==head;   

4种链表用4种道路来形象的比喻:
四种链表

静态链表

在这里插入图片描述

顺序表插入和删除的时间复杂度计算过程

在这里插入图片描述

代码

#define maxSize 100   //定义一个整型常量
LNode *a=(LNode *)malloc(sizeof(LNode));  //分配内存空间 
注:这里a包含了两个东西:结点和指向这个结点的指针。a既是指针名又是结点名

2.2顺序表操作

初始化顺序表

void init(Sqlist &L){
	L.length=0;
}

结构体定义

typedef struct{
	int data[maxSize];  //存放元素的数组
	int length;  //存放元素个数(顺序表长度)
}Sqlist;  //定义顺序表类型

考试中用的多的
int a[maxSize];  //存放元素的数组
int n;

插入元素:查找位置,插入

查找算法:找第一个等于e的元素的位置
int find(Sqlist L,int e){
	int i;
	for(i=0;i<L.length;i++){
		if(e==L.data[i])
			return i;  //找到
	}
	return -1;  //没找到,失败标记
}
插入数据元素算法:在p的位置(等同于上面找到的i)上插入e;p的位置存在就插入,不存在返回0
int insert(Sqlist &L,int p,int e){ //L会发生变化,所以要用引用型
	int i;
	//p不对或没位置
	if(p<0||p>L.length||L.length==maxSize)  
		return 0;
	for(i=L.length-1;i>=p;--i)
		L.data[i+1]=L.data[i];//从后往前往后移动
	L.data[p]=e;
	++(L.length);  //加表长
return 1;
}

删除元素

int delete(Sqlist &L,int p,int &e){//删除的结点元素也会改变
	int i;
	if(p<0||p>L.length-1)
		return 0;
	e=L.data[p];  //删除的p位置上的元素赋给e
	for(i=p;i<L.length-1;++i)
		L.data[i]=L.data[i+1];
	--(L.length);
   return 1;
}	

2.3单链表操作(带头结点)

typedef struct LNode{
	int data;
	struct LNode *next;  //结构体要定义指针的话上面就得加一个名称,像LNode一样
}LNode;

2.4双链表操作

typedef struct LNode{
	int data;
	struct LNode *prior;
	struct LNode *next;
}LNode;

查找结点

DLNode* find(DLNode *c,int x){
	DLNode *p=c-next;
	while(p!=NULL){
		if(p-data==x)
			break;
		p=p->next;
	}
	return p;  //找到,p中的内容是结点地址
}

插入结点(p后插入s)

s->next=p->next;
s->prior=p;
p-next=s;
s->next->prior=s; //p如果指向最后一个结点,这行可以去掉

在这里插入图片描述

删除结点p的后继结点

q=p->next;
p->next=q->next;
q->next->prior=p;
free(q);

在这里插入图片描述

真题演练

1.一个顺序表数组A[],元素存储在下标0到m+n-1的范围,前m个元素递增有序,后n个元素也递增有序,设计一个算法,使得整个顺序表有序。
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
(3)说明你所设计的算法的时间复杂度和空间复杂度。

(1)算法的基本设计思想
	 1.将数组A[]中的m+n个元素(假设元素为int型)看成两个顺序表:表L(由A[]中前m个元素构成),表R(由A[]中后n 个元素构成)。
	 2.将数组当前状态看作起始状态,将表R中的元素逐个插入表L中的合适位置即可。
	 3.插入过程:取表R中的第一个元素A[m]存入 辅助变量temp 中,让 temp逐个与A[m-1],…,A[0]进行比较,当temp<A[j](0≤j≤m-1)时,
将A[j]后移一位,temp>A[j](0≤j≤m-1)时,将temp存入A[j+1]中。重复上述过程,继续插入A[m+1],A[m+2],·…,A[m+n-1],最终A[]中元素整体有序。
(2)
void insert(int A[],int m,int n){
	int i,j;
	int temp;
	for(i=m;i<m+n;++i){ //R中的元素插入到L中
		temp=A[i];
		for(j=i-1;j>=0&&temp<A[j];--j)
			A[j+1]=A[j];  //L中的元素后移,给temp腾位置
		A[j+1]=temp;
	}
}		
(3)算法的时间和空间复杂度
 	1.本题的规模由m和n共同决定。取最内层循环中A[j+1]=A[j];这一句作为基本操作,其执行次数在最坏的情况下
为R中的每个元素都小于L中的所有元素;又因R中元素递增有序,所以对于每个R中的元素,要将其插入正确位置
都必须进行m次移动,R中共有n个元素,因此有:
f(m,n)=mn
由此可见,本算法的时间复杂度为O(mn)。
	 2.算法所需额外存储空间与数据规模m和n无关,变化属于常量级,因此空间复杂度为0(1)。

2.递增有序的单链表A、B(元素个数分别为m、n,且都带有头结点)分别存储了一个集合,请设计算法,求出A和B的差集A-B(仅由在A中出现而不在B中出现的元素所构成的集合)。将差集保存在单链表A中,并保持元素的递增有序性。
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
(3)说明你所设计的算法的时间复杂度。

(1)只需从A中删去A与B中共有的元素即可。由于两个链表中的元素是递增有序的,因此可以这么做:设置两个指针p、q开始时分别指向A和B的开始结点。
循环进行以下判断和操作:如果p所指结点的值小于q所指结点的值,则p后移一位看下一位元素的大小;如果q所指结点的值小于p所指结点的值(说明A 
中已经有这一位元素了),则q后移一位看下一位元素的大小;如果两者所指结点的值相同,则删除p所指结点。最后,p与q任一指针为NULL时算法结束。
(2)
void difference(LNode *A,LNode *B){
	LNode *p=A->next,*q=B->next;//pq都是指向开始结点的指针
	LNode *pre=A;  //pre为A中p所指结点的前驱结点的指针,pre应该是指向头指针的
	LNode *r;
	while(p!=NULL&&q!=NULL){
		if(p->data<q->data){
			pre=p;
			p=p->next;
		}
		else if(p->data>q->data)
			q=q->next;
		else{   //相等的情况,删除相同的结点
		//删除p
			pre->next=p->next;  //pre->next是头指针的下一个结点是开始结点更新为p->next
			r=p;//要删除的结点放在了r
			p=p->next;//向后移动指针看下一个结点的大小
			free(r);  //释放结点空间
		}
	}
}
(3)算法的时间复杂度分析
由算法描述可知,算法规模由m和n共同确定。算法中有一个单层循环,循环内的所有操作都是常数级的,因此可以用循环执行的次数作为基本操作执行的次数。可见循环执行的次数即为p、q两指针沿着各自链表移动的次数,考虑最坏的情况,即p、q都走完了自己所在的链表,循环执行 m+n次,因此时间复杂度为O(m+n)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值