码迷,mamicode.com
首页 > 其他好文 > 详细

小猪的数据结构学习笔记(二)

时间:2014-07-27 23:44:10      阅读:429      评论:0      收藏:0      [点我收藏+]

标签:数据结构   算法   基础   入门   笔记   

小猪的数据结构学习笔记(二)

线性表中的顺序表


本节引言:


在上个章节中,我们对数据结构与算法的相关概念进行了了解,知道数据结构的

逻辑结构与物理结构的区别,算法的特性以及设计要求;还学了如何去衡量一个算法

的好坏,以及时间复杂度的计算!在本节中我们将接触第一个数据结构——线性表;

而线性表有两种表现形式,分别是顺序表和链表;学好这一章很重要,是学习后面的基石;

这一节我们会重点学习下顺序表,在这里给大家一个忠告,学编程切忌眼高手低,看懂不代表自己

写得出来,给出的实现代码,自己要理解思路,自己写出来!写多了就有感觉了!多思考!!

另外附上学习数据结构的一个利器,数据结构演示动画,在本文结尾给出!bubuko.com,布布扣


好了,废话就这么多!



本节学习路线图


bubuko.com,布布扣


路线图解析:

①抽象数据类型就那三要素:数据,数据之间的关系,和数据的操作

②线性表就是按一条线排列的数据集合,1对1,除了首元和尾元,其他元素都有直接前驱和直接后继

③顺序表有点像以前学习的数组,要小心注意表中的第i个元素是对应 i - 1那个位置的数据的!!!!

④基本存储结构要牢记,至于12个基本操作,除了插入和删除有点小难度,其他的都很简单,要自己将代码写多几遍哦!

⑤求并集的那个,也不是很难懂,自己拿笔画下图,想一想应该就懂了!去除表中的重复元素占时没想到什么好的方法,有好的欢迎提出!



正文:


一.抽象的数据类型


bubuko.com,布布扣



二.线性表中的顺序表



bubuko.com,布布扣



三.相关操作的代码实现与解析:


1.线性表的存储结构:


<span style="font-family:Microsoft YaHei;">#define MAXSIZE 20
#define INCREMENT  10
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
//定义一个int数据类型的别名
//这里因为演示采用int,实际使用的通常是复合的数据类型 
typedef int ElemType;
typedef int Status;

typedef struct
{
	ElemType *elem;  //存储空间的起始地址           
	int length; 	//表的当前长度 
	int listsize;   //表的总共存储容量(sizeof(ElemType)) 
}SqList;</span>



2.构造空表


<span style="font-family:Microsoft YaHei;">//创建一个空表:
void InitList(Sqlist &L)
{
	L.elem = (ElemType *)malloc(MAXSIZE * sizeof(ElemType));
	if(!L.elem) exit(ERROR);
	L.length = 0;
	L.listsize = MAXSIZE; 
} </span>

代码解析

:步骤:

①申请表的存储空间,将空间的其实地址赋值给elem,然后通过判断elem是否为空,从而知道内存是否分配成功

②将表的当前长度length设置为0,将表的大小listsize设置为MAXSIZE



3.将表置为空表


<span style="font-family:Microsoft YaHei;">//将表置为空表 
void ClearList(SqList &L)
{
	L.length = 0;
} </span>

代码解析:

只需要将表的长度length设置为0就可以了,很简单吧



4.判断是否为空表


<span style="font-family:Microsoft YaHei;">//判断表是否为空表
 Status ListEmpty(SqList L)
 {
 	if(L.length == 0)return TRUE;
 	else return False;
 }</span>

代码分析:

同样只需要判断length的值是否为0就可以了,很简单



5.销毁表


<span style="font-family:Microsoft YaHei;">//销毁表
void DestroyList(SqList &L)
{
	free(L.elem);
	L.elem = NULL;
	L.length = 0;
	L.listsize = 0;
} </span>

代码分析:

步骤:

①调用free函数释放L,elem指向的内存空间的内存

②将L.elem赋值为NULL,即空指针

③将表的当前长度Length和表的最大长度listsize设置为0



6.获得表中的数据元素数目

<span style="font-family:Microsoft YaHei;">//获得当前表中元素的数目
int ListLength(SqList L)
{
	return L.length; 
} </span>

代码分析:

直接返回当前长度length即可


7.获得表中第i个数据元素的值

<span style="font-family:Microsoft YaHei;">//获得表中第i个元素的值,通过e的值反映 
Status GetElem(SqList L,int i,ElemType &e)
{
	if(i < 1|| i > L.length)
	return ERROR;
	e = *(l.elem + i - 1);
	return OK;
} </span>

代码分析:

①先判断第i个位置是否合法

②将对于位置的值赋值给e,另外减一是因为数组是下标是从0开始的!!

而我们看表是从1开始算的,所以需要减一


8.查找表中是否有满足要求的元素

<span style="font-family:Microsoft YaHei;">//返回表中第一个满足要求的元素的下标
//这里我们把要求假设为一个函数compare(int l_s,int e); 
//参数依次为表中元素与需要进行关系比较的参数e
//第三个参数函数指针,旨锤向函数的指针 
int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))
{
	int i = 1;
	ElemType *p = L.elem;
	while(i < L.length && !compare(*p++,e))
	i++;
	if(i <= L.length) return i;
	else return 0;
} </span>


代码分析:

步骤:

①定义变量i和指针p分别执行表中第1个元素和表的首地址

②循环调用compare()函数与表中的元素进行比较

③如果i <= length的话说明找到了,返回对应元素的序号

④否则返回0表示找不到



9.返回某个节点的前驱

<span style="font-family:Microsoft YaHei;">//返回某个节点的直接前驱
//第二和第三个参数分别为:指定的数据元素,before用来存储它的前驱的 
Status PriorElem(SqList L,ElemType choose,ElemType &before)
{
	int i = 2;
	ElemType *p = L.elem + 1;
	while(i <= L.length && *p != choose)
	{
		p++;
		i++;
	}
	if(i > L.length)return ERROR;
	else
	{
		before = *--p;
		return OK; 
	}
} </span>


代码分析:

①首元是没有前驱的,所以i从2,p从L.elem +1 开始算

②通过循环查看指定数据元素在表中的位置,如果i > L.length表示找不到,返回ERROR

③找到的话,通过*--p获取该元素前驱的值赋值给before变量




10.返回某个节点的后继

<span style="font-family:Microsoft YaHei;">//返回某个支点直接后继
//第二三个参数依次为:选定的数据元素的值,存储后继的变量 
Status NextElem(SqList L,ElemType choose,ElemType &behind)
{
	int i = ;
	ElemType *p = L.elem;
	while(i < L.length && *p != choose)
	{
		p++;
		i++;
	}
	if(i == L.length)return ERROR;
	else 
	{
		behind = * ++p;
		return OK;
	}
} </span>

代码分析:

①和上面的前驱差不多,要注意的是i == L.length就可以了,因为尾元没有后继,所以直接把尾元排除了!



11.往表中第i个位置插入元素

<span style="font-family:Microsoft YaHei;">//往表的第i个位置插入元素e
Status ListInsert(SqList &L,int i,ElemType e)
{
	ElemType *p,*q,*newbase;
	//插入位置为1-length,其他值不合法 
	if(i<1||i>L.length + 1)return ERROR;
	//如果表满了的话,增加分配的空间 
	if(L.length == L.listsize)
	{
		newbase = (ElemType)realloc(L.elem,(L.listsize + INCREMENT)*sizeof(ElemType));
		if(!newbase)exit(ERROR);
		L.elem = newbase;
		L.listsize += INCREMENT;
	}
	p = L.elem + i - 1;
	//向右移,先移动最后一个 
	for(q = L.elem + L.length - 1;q >= q;--q)
	*(q + 1) = *q;
	//将e插入,表长+1 
	*q = e;	
	++L.length;
	return OK; 
} </span>


代码解析:

bubuko.com,布布扣




12.删除表中第i个位置的元素

<span style="font-family:Microsoft YaHei;">//删除表中第i个位置的元素
Status ListDelete(SqList &L,int n,ElemType &e)
{
	ElemType *p,*q;
	//判断删除的位置是否合法
	if(i < 1 && i > L.length)return ERROR;
	//指向删除的位置,将值付给e 
	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; 
}</span>


代码分析:

bubuko.com,布布扣




13.遍历顺序表所有元素

<span style="font-family:Microsoft YaHei;">//遍历线性表所有元素
void ListTraverse(SqList L,void(*visit)(ElemType&))
{
	int i = 1;
	ElemType *p = L.elem;
	for(i ==1;i <= L.length;i++)
	{
		visit(*p++);
		printf("\n");
	}
} </span>


代码解析:

代码很简单,就是从第一个元素开始,让指针后移,依次调用visit()函数

实现表中元素的遍历





14.应用小示例:

已知A,B两个顺序表中的元素是按从小到大排列的;现在要你求两个的并集C;

而且C中的元素也要按从小到大排序;不改变A和B中的数据!

是并集哦,就是C中不能有重复的元素


<span style="font-family:Microsoft YaHei;">void UnionList(SqList La,SqList Lb,SqList &Lc)
{
	//定义指向La,Lb表头表位的指针,以及指向Lc的指针 
	ElemType *la,*la_end,*lb,*lb_end,*lc;
	la = La.elem;
	lb = La.elem;
	la_end = La.elem + La.length - 1;
	lb_end = Lb.elem + Lb.length - 1;
	//在这里为lc分配内存空间,大小为La.length + Lb.length
	Lc.listsize = Lc.length = La.length + La.length;
	lc = Lc.elem = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));
	if(!Lc.elem)exit(ERROR);
	//将a,b中的元素进行合并
	//如果a,b中都有元素还没有合并
	while(la <= la_end && pb <= lb_end)
	{
		if(*la <= *lb)*lc++ = *la++;
		else *lc++ = *lb++;
	}
	//假如还有剩下的元素,要么是a,要么是b
	while(la <= la_end)*lc++ = *la++;
	while(lb <= lb_end)*lc++ = *lb++;
	
	//接着要将Lc中重复的元素删除掉
	ElemType *p,*q;
	p = Lc.elem;
	q = p;
	//使用两枚指针p,q,如果指针p没有指向末尾 
	while(p != (Lc.length - 1))
	{
		//q指向p的后缀,比较两数的值 
		if(*p != *(++q))
		{
			p++;
			q = p;
		}
		//相等的话,删除q指向的元素
		//再次进行比较,直到不重复为止 
		else
		{
			while(*p == *q)
			ListDelete(Lc,(p - Lc.elem),e);
		}
	} 
}</span>


ps:最后去除Lc中的重复元素的算法似乎有点累赘,如有高效点的算法,欢迎提出,万分感激啊!



本章小结:

①什么是抽象的数据类型ADT

②线性表的定义与线性表的特性

③顺序表:地址连续的存储单元一次存储的线性表

④顺序表的结构,三个基本属性

⑤顺序表的12个相关操作

⑥顺序表的使用小示例



学习资源下载:

本节代码打包:点击下载

数据结构演示工具:点击下载




小猪的数据结构学习笔记(二),布布扣,bubuko.com

小猪的数据结构学习笔记(二)

标签:数据结构   算法   基础   入门   笔记   

原文地址:http://blog.csdn.net/coder_pig/article/details/38151653

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!