顺序表的理解与使用


一、前言



顺序表是线性表(链式表和顺序表)的一种,线性表是线性排列的一组具有相同数据类型的元素的有限集合,除第一个元素外,所有的元素都有且只有一个直接后驱。除最后一个元素外,所有的元素都有且只有一个直接前驱。它是数据结构中最常用也是最基本最简单的数据结构,它的基本操作有检索元素,插入元素,删除元素.......接下来会解析顺序表的概念和使用(含c,c++,java三种语言实现)。



二、顺序表


(1)概念:



顺序表即按顺序存储的一组有限的含有相同元素的数据集合。顺序存储指的是,集合里面的元素都是按照次序排列在一块连续的存储空间中。比如有这样的一个数据集合(a1,a2,a3.....ai,ai+1......an),表示该集合中的元素是按照a1,a2这样的顺序存储的。如果是在c语言中,知道了a1的地址,那么就可以推算出第i个元素的地址,公式如下:

addr(ai)=addr(a1)+(i-1)*d。

其中d表示一个元素占据的存储空间大小。在很多高级程序设计语言中,顺序表的最直接的表现形式就是一维数组了。大家都知道数组的元素是有一个上限的,既是容量,因此,在使用顺序表的来处理数组的时候,数组的容量要足够大,这样才不至于导致数组空间不足。接下来了解一下,顺序表可以有哪些基本操作(其实很多操作都是可以在自己理解的基础上总结出来的,这里通过基本操作来了解顺序表的使用,目的是发散思维)。



(2)基本操作:


①、顺序表的初始化


顺序表的初始化即构造一个空表,这里我们命名为init(接下里的操作都将遵循这个名字)。


②、添加元素到指定的位置


将指定元素添加到线性表指定的位置,这里命名为insert。


③、删除指定位置的元素


将指定位置的元素删除,这里命名为delete。


④、查找指定元素在表中的位置


查找指定元素的位置,这里命名为get。


三、顺序表在C语言中的实现


代码如下:

/*
c语言实现顺序表的基本操作
*/
#include<stdio.h>
#include<stdlib.h>

//最多存储100个元素
#define MAXSIZE 100//注意预定义的语法没有分号也没有=号

//定义一个线性表结构,注意strcut里面的元素是不可以初始化的
struct OrderTable
{
	int element[MAXSIZE];//元素表
	int last;//指示当前元素中最后一个元素的位置
};

//声明基本操作

struct OrderTable* init();//初始化
int insert(struct OrderTable *L, int x, int i);//添加一个元素到指定位置
int delete(struct OrderTable *L, int i);//将指定位置的元素删除
int get(struct OrderTable *L, int i);//获取指定位置的值

int main(void)
{
	struct OrderTable *L = init();

	for (int i = 1; i <=50; i++)
	{
		insert(L, i*2,i);
	}

	printf("输出列表元素:\n");
	for (int i = 1; i <= 50; i++)
	{
		printf("%d ",get(L, i));
		if (i % 10 == 0)
			printf("\n");
	}

	delete(L, 1);
	printf("输出列表元素:\n");
	for (int i = 1; i <= 50; i++)
	{
		printf("%d ", get(L, i));
		if (i % 10 == 0)
			printf("\n");
	}
	return 0;
}

/*
初始化顺序表并返回指针对象
*/
struct OrderTable* init()
{
	struct OrderTable *L;
	//申请一个足以存放100个元素的存储空间并返回,malloc返回值是void *,所以需要强制转换对象
	L = (struct OrderTable*)malloc(MAXSIZE*sizeof(struct OrderTable));
	L->last = -1;
	return L;
}

/*
将指定元素插入到表中的指定位置
*/
int insert(struct OrderTable *L, int x, int i)
{
	//搞清楚的一个概念就是数组是从0开始算的,100的元素其实是a[0]-a[99]。所以第i个位置实际上是a[i-1];
	if (L->last == MAXSIZE - 1)
	{
		printf("表中元素已满,不允许插入");
		return -1;
	}
	if (i<0 || i>L->last + 2)
	{
		printf("插入的位置不允许");
		return -1;
	}
	else
	{
		for (int j = L->last; j >= i - 1; j--)
		{
			L->element[j + 1] = L->element[j];
		}
		L->element[i - 1] = x;
		L->last++;
		return 1;
	}
}


/*
删除指定位置的元素
*/
int delete(struct OrderTable *L, int i)
{
	if (i<0 || i>L->last + 1)
	{
		printf("指定的位置不存在");
		return 0;
	}
	else
	{
		for (int j = i; j <= L->last - 1; j++)
		{
			L->element[j - 1] = L->element[j];
		}
		L->last--;
		return 1;
	}
}

/*
获取指定位置的元素
*/
int get(struct OrderTable *L, int i)
{
	if (i >= 1 && i <= L->last + 1)
	{
		return L->element[i - 1];
	}
	printf("该位置没有值");
	return -1;
}

上述实现过程,最重要的是注意列表的下标是从0开始的,而我们所说的位置则是从1开始的。接下来我们分析一下个方法的时间渐进复杂度(此概念这里不普及了,因为数学表达式不好输入,读者自行补充相关知识)。


首先是
int insert(struct OrderTable *L, int x, int i)

因为i可能是任意位置,假设每个位置被插入的概率是pi,当前的数组长度是n,则pi=1/(n+1),
其次,此方法中执行次数最多的是
L->element[j + 1] = L->element[j];
总共执行了(n-i+1)+(n-i)+......+1+0次。(这里其实是一个等差级数)
所以时间渐进复杂度位((n-i+1)+....+0)*pi=n/2;即为n。

剩余的方法的时间渐进复杂度有读者自行推断。

运行结果:




四、顺序表在C++中的实现



首先定义头文件:


#include <iostream>


class OrderTable
{
public:
	OrderTable();
	~OrderTable();
	/*
	讲指定元素添加到顺序表里面
	*/
	int insertElement( int x, int i)
	{
		if (this->last == 100 - 1)
		{
			std::cout << "数组已满" << std::endl;
			return -1;
		}
		if (i <= 0 || i > this->last + 2)
		{
			std::cout << "插入位置错误" << std::endl;
			return -1;
		}
		else
		{
			int j;
			for (j = this->last; j >= i - 1; j--)
			{
				this->element[j + 1] = this->element[j];
			}
			this->element[j + 1] = x;
			this->last++;
			return 1;
		}
	}

	/*
	删除指定位置的元素
	*/
	int deleteELement( int i)
	{
		if (i <= 0 || i >this->last + 1)
		{
			std::cout << "删除的位置不正确" << std::endl;
			return -1;
		}
		else
		{
			for (int j = i; j < this->last; j++)
			{
				this->element[j - 1] = this->element[j];
			}
			this->last--;
			return 1;

		}
	}
	/*
	获取指定位置的元素
	*/
	int getElement(int i)
	{
		if (i <= 0 || i > this->last + 1)
		{
			std::cout << "位置不正确" << std::endl;
			return -1;
		}
		else
			return this->element[i - 1];
	}

private:
	int element[100];
	int last = -1;
};

OrderTable::OrderTable()
{
}

OrderTable::~OrderTable()
{
}


然后是主函数文件:

// OrderCPP.cpp : 定义控制台应用程序的入口点。
//

#include <iostream>
#include "Order.h"

using std::cout;
using std::endl;

int main()
{
	OrderTable orderTable;

	for (int i = 1; i <= 50; i++)
	{
		orderTable.insertElement(i * 2, i);
	}

	for (int i = 1; i <= 50; i++)
	{
		cout << orderTable.getElement(i) << " ";
		if (i % 10 == 0)
			cout << endl;
	}

	orderTable.deleteELement(1);

	for (int i = 1; i <= 50; i++)
	{
		cout << orderTable.getElement(i) << " ";
		if (i % 10 == 0)
			cout << endl;
	}
	system("pause");
	return 0;
}



其中this是每个class都隐含的指针对象,它是一个指向自己的对象。

运行结果:





五、顺序表在java中的实现



public class OrderTable {

	private int element[];
	private int last;

	OrderTable() {
		element=new int[100];
		last = -1;
	}

	/**
	 * 添加元素
	 * 
	 * @param x
	 * @param i
	 * @return
	 */
	public int insert(int x, int i) {
		if (last == 100 - 1) {
			return -1;
		}
		if (i <= 0 || i > last + 2) {
			return -1;
		} else {
			int j;
			for (j = last; j >= i - 1; j--) {
				element[j + 1] = element[j];
			}
			element[j + 1] = x;
			last++;
			return 1;
		}
	}

	/**
	 * 删除元素
	 * 
	 * @param i
	 * @return
	 */
	public int delete(int i) {
		if (i <= 0 || i > last + 1) {
			return -1;
		} else {
			for (int j = i; j < last; j++) {
				element[j - 1] = element[j];
			}
			last--;
			return 1;

		}
	}

	/**
	 * 获取元素
	 * 
	 * @param i
	 * @return
	 */
	public int get(int i) {
		if (i <= 0 || i > last + 1) {
			return -1;
		} else
			return element[i - 1];
	}

}


主函数:


public class Order {

	public static void main (String args[])
	{
		OrderTable orderTable=new OrderTable();

		for (int i = 1; i <= 50; i++)
		{
			orderTable.insert(i * 2, i);
		}

		for (int i = 1; i <= 50; i++)
		{
			System.out.print(orderTable.get(i)+ " ");
			if (i % 10 == 0)
				System.out.println();
		}

		orderTable.delete(1);

		for (int i = 1; i <= 50; i++)
		{
			System.out.print(orderTable.get(i)+ " ");
			if (i % 10 == 0)
				System.out.println();
		}
		
		
	}
}


运行结果:



以上用了三种语言实现了顺序表的基本运算。





---------文章写自:HyHarden---------

--------博客地址:http://blog.csdn.net/qq_25722767-----------


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值