目录
一、前言
二、什么是顺序表
三、顺序表的实现
1. 顺序表的存储结构
2. 顺序表的基本操作
(1)创建顺序表
(2)插入元素
(3)删除元素
(4)查找元素
四、顺序表的优缺点
1. 优点
2. 缺点
C++实现
Java实现
Python实现
Cobol实现
在计算机科学中,数据结构是一种组织和存储数据的方式,以便于访问和修改。数据结构是计算机科学中的基础,它是算法的基础。数据结构可以分为两种类型:线性结构和非线性结构。顺序表是线性结构中最基本的一种数据结构,它是一种连续的存储结构,可以用数组来实现。本篇博客将详细介绍顺序表的定义、实现、优缺点以及应用场景。
顺序表是一种线性结构,它是一种连续的存储结构,可以用数组来实现。顺序表中的元素在内存中是连续存储的,每个元素都有一个唯一的下标,可以通过下标来访问元素。顺序表中的元素可以是任意类型的数据,如整数、浮点数、字符、字符串等。
顺序表是一种静态的数据结构,它的大小在创建时就已经确定,无法动态地改变大小。如果需要添加或删除元素,需要重新创建一个新的顺序表,并将原来的元素复制到新的顺序表中。
顺序表的存储结构可以用数组来实现。数组是一种连续的存储结构,可以通过下标来访问元素。顺序表中的元素在数组中是按照顺序存储的,每个元素都有一个唯一的下标,可以通过下标来访问元素。
下面是一个简单的顺序表的定义:
#define MAXSIZE 100 // 定义顺序表的最大长度
typedef struct {
int data[MAXSIZE]; // 存储顺序表中的元素
int length; // 顺序表的长度
} SeqList;
顺序表的基本操作包括创建、插入、删除、查找和遍历等。
创建顺序表需要先定义一个结构体,然后初始化顺序表的长度为0。下面是创建顺序表的代码:
SeqList* createSeqList() {
SeqList* L = (SeqList*)malloc(sizeof(SeqList)); // 分配内存空间
L->length = 0; // 初始化顺序表的长度为0
return L;
}
在顺序表中插入元素需要先判断顺序表是否已满,如果已满则无法插入元素。如果顺序表未满,则需要将插入位置后面的元素依次向后移动一位,然后将新元素插入到指定位置。下面是插入元素的代码:
bool insert(SeqList* L, int index, int value) {
if (L->length >= MAXSIZE) { // 判断顺序表是否已满
return false;
}
if (index < 1 || index > L->length + 1) { // 判断插入位置是否合法
return false;
}
for (int i = L->length; i >= index; i--) { // 将插入位置后面的元素依次向后移动一位
L->data[i] = L->data[i - 1];
}
L->data[index - 1] = value; // 将新元素插入到指定位置
L->length++; // 顺序表长度加1
return true;
}
在顺序表中删除元素需要先判断顺序表是否为空,如果为空则无法删除元素。如果顺序表不为空,则需要将删除位置后面的元素依次向前移动一位,然后将顺序表的长度减1。下面是删除元素的代码:
bool remove(SeqList* L, int index) {
if (L->length == 0) { // 判断顺序表是否为空
return false;
}
if (index < 1 || index > L->length) { // 判断删除位置是否合法
return false;
}
for (int i = index; i < L->length; i++) { // 将删除位置后面的元素依次向前移动一位
L->data[i - 1] = L->data[i];
}
L->length--; // 顺序表长度减1
return true;
}
在顺序表中查找元素需要遍历整个顺序表,逐个比较元素的值,直到找到目标元素或者遍历完整个顺序表。下面是查找元素的代码:
int LocateElem(SqList L, int e) {
int i;
for (i = 0; i < L.length; i++) {
if (L.data[i] == e) {
return i; // 返回元素在顺序表中的位置
}
}
return -1; // 如果未找到,返回-1
}
1. 随机访问效率高:顺序表中的元素在内存中是连续存储的,因此可以通过下标直接访问任意位置的元素,访问效率非常高。
2. 存储密度高:顺序表中的元素存储在一段连续的存储空间中,因此存储密度非常高,不会出现像链表那样的指针占用额外的存储空间。
3. 空间利用率高:顺序表中的元素存储在一段连续的存储空间中,因此不会出现像链表那样的内存碎片,空间利用率非常高。
4. 适合于大量随机访问的场景:由于顺序表的随机访问效率非常高,因此适合于需要大量随机访问的场景,比如数组、矩阵等。
1. 插入和删除效率低:由于顺序表中的元素存储在一段连续的存储空间中,因此在插入和删除元素时需要移动其他元素,效率比较低。
2. 存储空间需要预先分配:顺序表的存储空间需要预先分配,因此在存储空间不足时需要重新分配更大的空间,并将原有的元素复制到新的空间中,这样会造成一定的时间和空间浪费。
3. 不适合频繁的插入和删除操作:由于顺序表的插入和删除操作效率比较低,因此不适合频繁的插入和删除操作,比如链表等数据结构更适合这种场景。
4. 内存浪费:由于顺序表的存储空间需要预先分配,因此当存储空间没有被充分利用时,会造成一定的内存浪费。
以下是使用C++实现顺序表的完整代码:
#include
using namespace std;
const int MAXSIZE = 100; // 定义顺序表的最大长度
class SeqList {
private:
int data[MAXSIZE]; // 存储数据的数组
int length; // 当前顺序表的长度
public:
SeqList() { // 构造函数,初始化顺序表
length = 0;
}
~SeqList() {} // 析构函数,不需要进行任何操作
bool isEmpty() { // 判断顺序表是否为空
return length == 0;
}
bool isFull() { // 判断顺序表是否已满
return length == MAXSIZE;
}
int getLength() { // 获取顺序表的长度
return length;
}
int getElem(int i) { // 获取顺序表中第i个元素的值
if (i < 1 || i > length) { // 判断i是否越界
cout << "Error: index out of range!" << endl;
return -1;
}
return data[i-1];
}
int locateElem(int e) { // 查找元素e在顺序表中的位置
for (int i = 0; i < length; i++) {
if (data[i] == e) {
return i+1;
}
}
return 0;
}
bool insert(int i, int e) { // 在顺序表的第i个位置插入元素e
if (i < 1 || i > length+1) { // 判断i是否越界
cout << "Error: index out of range!" << endl;
return false;
}
if (isFull()) { // 判断顺序表是否已满
cout << "Error: the list is full!" << endl;
return false;
}
for (int j = length; j >= i; j--) { // 将第i个位置及之后的元素后移
data[j] = data[j-1];
}
data[i-1] = e; // 将元素e插入到第i个位置
length++; // 长度加1
return true;
}
bool remove(int i) { // 删除顺序表中第i个位置的元素
if (i < 1 || i > length) { // 判断i是否越界
cout << "Error: index out of range!" << endl;
return false;
}
for (int j = i; j < length; j++) { // 将第i个位置及之后的元素前移
data[j-1] = data[j];
}
length--; // 长度减1
return true;
}
void printList() { // 输出顺序表中所有元素
if (isEmpty()) { // 判断顺序表是否为空
cout << "The list is empty." << endl;
return;
}
cout << "The list is: ";
for (int i = 0; i < length; i++) {
cout << data[i] << " ";
}
cout << endl;
}
};
int main() {
SeqList list;
list.insert(1, 10);
list.insert(2, 20);
list.insert(3, 30);
list.printList(); // 输出:The list is: 10 20 30
list.remove(2);
list.printList(); // 输出:The list is: 10 30
cout << "The length of the list is: " << list.getLength() << endl; // 输出:The length of the list is: 2
cout << "The element at position 2 is: " << list.getElem(2) << endl; // 输出:The element at position 2 is: 30
cout << "The position of element 10 is: " << list.locateElem(10) << endl; // 输出:The position of element 10 is: 1
return 0;
}
在上面的代码中,我们定义了一个SeqList类,其中包含了顺序表的基本操作,如插入、删除、查找等。在主函数中,我们创建了一个SeqList对象list,并对其进行了一些操作,最后输出了一些结果。
public class SeqList {
private Object[] elementData; // 存储元素的数组
private int size; // 元素个数
// 默认容量为10
public SeqList() {
this(10);
}
// 指定初始容量
public SeqList(int initialCapacity) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("容量不能为负数:" + initialCapacity);
}
this.elementData = new Object[initialCapacity];
this.size = 0;
}
// 获取元素个数
public int size() {
return this.size;
}
// 判断是否为空
public boolean isEmpty() {
return this.size == 0;
}
// 获取指定位置的元素
public T get(int index) {
checkIndex(index);
return (T) this.elementData[index];
}
// 修改指定位置的元素
public void set(int index, T element) {
checkIndex(index);
this.elementData[index] = element;
}
// 在指定位置插入元素
public void add(int index, T element) {
if (index < 0 || index > this.size) {
throw new IndexOutOfBoundsException("索引越界:" + index);
}
ensureCapacity(this.size + 1);
System.arraycopy(this.elementData, index, this.elementData, index + 1, this.size - index);
this.elementData[index] = element;
this.size++;
}
// 在末尾添加元素
public void add(T element) {
add(this.size, element);
}
// 删除指定位置的元素
public T remove(int index) {
checkIndex(index);
T oldValue = (T) this.elementData[index];
int numMoved = this.size - index - 1;
if (numMoved > 0) {
System.arraycopy(this.elementData, index + 1, this.elementData, index, numMoved);
}
this.elementData[--this.size] = null;
return oldValue;
}
// 清空顺序表
public void clear() {
for (int i = 0; i < this.size; i++) {
this.elementData[i] = null;
}
this.size = 0;
}
// 检查索引是否越界
private void checkIndex(int index) {
if (index < 0 || index >= this.size) {
throw new IndexOutOfBoundsException("索引越界:" + index);
}
}
// 扩容
private void ensureCapacity(int minCapacity) {
if (minCapacity > this.elementData.length) {
int newCapacity = this.elementData.length * 2;
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
this.elementData = Arrays.copyOf(this.elementData, newCapacity);
}
}
}
```
使用示例:
```java
SeqList list = new SeqList<>();
list.add("A");
list.add("B");
list.add("C");
System.out.println(list.get(1)); // 输出 B
list.set(1, "D");
System.out.println(list.get(1)); // 输出 D
list.add(1, "E");
System.out.println(list.get(1)); // 输出 E
System.out.println(list.remove(2)); // 输出 D
list.clear();
System.out.println(list.isEmpty()); // 输出 true
class SeqList:
def __init__(self, maxsize=None):
self.maxsize = maxsize
self._items = [None] * maxsize
self.length = 0
def __getitem__(self, index):
if index < self.length:
return self._items[index]
else:
raise IndexError('Index out of range')
def __setitem__(self, index, value):
if index < self.length:
self._items[index] = value
else:
raise IndexError('Index out of range')
def __len__(self):
return self.length
def __repr__(self):
return str(self._items[:self.length])
def insert(self, index, value):
if self.length >= self.maxsize:
raise Exception('SeqList is full')
if index < 0 or index > self.length:
raise IndexError('Index out of range')
for i in range(self.length, index, -1):
self._items[i] = self._items[i-1]
self._items[index] = value
self.length += 1
def delete(self, index):
if index < 0 or index >= self.length:
raise IndexError('Index out of range')
for i in range(index, self.length-1):
self._items[i] = self._items[i+1]
self._items[self.length-1] = None
self.length -= 1
```
使用方法:
```python
# 创建一个长度为5的顺序表
lst = SeqList(5)
# 插入元素
lst.insert(0, 1)
lst.insert(1, 2)
lst.insert(2, 3)
# 输出顺序表
print(lst) # [1, 2, 3]
# 删除元素
lst.delete(1)
# 输出顺序表
print(lst) # [1, 3]
以下是使用COBOL语言实现顺序表的示例代码:
IDENTIFICATION DIVISION.
PROGRAM-ID. SEQUENTIAL-LIST.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 LIST-SIZE PIC 9(4) VALUE 100.
01 LIST OCCURS 0 TO 99 TIMES DEPENDING ON LIST-SIZE.
05 LIST-ITEM PIC X(20).
01 LIST-COUNT PIC 9(4) VALUE 0.
PROCEDURE DIVISION.
MAIN-LOGIC.
DISPLAY "SEQUENTIAL LIST PROGRAM".
PERFORM DISPLAY-MENU UNTIL LIST-COUNT = 100.
STOP RUN.
DISPLAY-MENU.
DISPLAY "1. ADD ITEM TO LIST".
DISPLAY "2. DELETE ITEM FROM LIST".
DISPLAY "3. DISPLAY LIST".
DISPLAY "4. EXIT".
DISPLAY "ENTER YOUR CHOICE: ".
ACCEPT CHOICE.
EVALUATE CHOICE
WHEN 1
PERFORM ADD-ITEM
WHEN 2
PERFORM DELETE-ITEM
WHEN 3
PERFORM DISPLAY-LIST
WHEN 4
EXIT PROGRAM
WHEN OTHER
DISPLAY "INVALID CHOICE".
END-EVALUATE.
ADD-ITEM.
IF LIST-COUNT = 100
DISPLAY "LIST IS FULL"
GO TO MAIN-LOGIC
END-IF
DISPLAY "ENTER ITEM TO ADD: ".
ACCEPT LIST-ITEM(LIST-COUNT)
ADD 1 TO LIST-COUNT.
DELETE-ITEM.
IF LIST-COUNT = 0
DISPLAY "LIST IS EMPTY"
GO TO MAIN-LOGIC
END-IF
DISPLAY "ENTER ITEM TO DELETE: ".
ACCEPT DELETE-ITEM
SEARCH LIST
AT END
DISPLAY "ITEM NOT FOUND"
WHEN LIST-ITEM(LIST-COUNT) = DELETE-ITEM
SUBTRACT 1 FROM LIST-COUNT
DISPLAY "ITEM DELETED"
WHEN OTHER
CONTINUE
END-SEARCH.
DISPLAY-LIST.
IF LIST-COUNT = 0
DISPLAY "LIST IS EMPTY"
GO TO MAIN-LOGIC
END-IF
DISPLAY "LIST CONTENTS: "
PERFORM VARYING I FROM 1 BY 1 UNTIL I > LIST-COUNT
DISPLAY LIST-ITEM(I)
END-PERFORM.
这个程序定义了一个大小为100的顺序表,使用LIST-COUNT变量来跟踪列表中的元素数量。主逻辑部分包括一个菜单,允许用户添加、删除和显示列表中的元素。ADD-ITEM和DELETE-ITEM子程序分别用于添加和删除元素,DISPLAY-LIST子程序用于显示列表中的元素。