1.关于线性表
线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)。
线性表的逻辑结构简单,便于实现和操作。有以下特点:
1.集合中必存在唯一的一个“第一元素”。
2.集合中必存在唯一的一个 “最后元素” 。
3.除最后一个元素之外,均有唯一的后继(后件)。
4.除第一个元素之外,均有唯一的前驱(前件)。
2.线性表操作及函数实现
函数实现:
typedef struct SeqList;//创建线性表
void outputList(SeqListPtr paraList);//打印线性表
void outputMemory(SeqListPtr paraListPtr);//打印数据地址
SeqListPtr seqListInit(int paraData[], int paraLength);//初始化线性表
void seqListInsert(SeqListPtr paraListPtr, int paraPosition, int paraValue);//插入数据
void seqInsertTest();//测试插入操作
int seqListDelete(SeqListPtr paraListPtr, int paraPosition);//删除数据
void seqDeleteTest();//测试删除操作
int locateElement(SeqListPtr paraListPtr, int paraValue);//返回指定元素位置
int getElement(SeqListPtr paraListPtr, int paraPosition);//返回目的位置元素
void clearList(SeqListPtr paraListPtr);//清空线性表
初始化操作:
运用数组,对一个空白线性表按顺序赋值,有很高复用性。
插入操作:
将需要插入元素的位置及其之后的元素顺序向后移动一个位置(注意:如果插入元素后线性表长度超出限制或选定插入位置错误,无法插入),然后在选定位置插入元素。
删除操作:
将需要删除元素之后的每个元素顺序向前移动一个位置,注意选定错误的位置将无法删除。
三个相关函数实现:
//返回指定元素位置
int locateElement(SeqListPtr paraListPtr, int paraValue){
for (int i = 0; i < paraListPtr->actualLength; i ++)
{
if (paraListPtr->data[i] == paraValue)
{
return i;
}
}
return -1;
}
//返回目的位置元素
int getElement(SeqListPtr paraListPtr, int paraPosition)
{
// 检查位置
if (paraPosition<0)
{
printf("错误的位置: %d\r\n", paraPosition);
return -1;
}
if (paraPosition >= paraListPtr->actualLength)
{
printf("不能插入:位置 %d 超出线性表长度 %d\r\n", paraPosition, paraListPtr->actualLength);
return -1;
}
return paraListPtr->data[paraPosition];
}
//清空线性表
void clearList(SeqListPtr paraListPtr)
{
paraListPtr->actualLength = 0;
}
3.总结
线性表,顾名思义其内部元素的相对位置是线性的,元素位置只取决于序号,通过线性表这一特性,我们可以很快地查找表中任意位置的元素。但是我在编写程序时发现,进行插入删除操作时,需要移动大量的元素,这是我认为线性表存在的问题。
代码及运行结果
#include <stdio.h>
#include <malloc.h>
#define LIST_MAX_LENGTH 10
//创建线性表
typedef struct SeqList {
int actualLength;
int data[LIST_MAX_LENGTH];
} *SeqListPtr;
//打印线性表
void outputList(SeqListPtr paraList) {
for(int i = 0; i < paraList->actualLength; i ++) {
printf("%d ", paraList->data[i]);
}
printf("\r\n");
}
//打印数据地址
void outputMemory(SeqListPtr paraListPtr) {
printf("The address of the structure: %ld\r\n", paraListPtr);
printf("The address of actualLength: %ld\r\n", ¶ListPtr->actualLength);
printf("The address of data: %ld\r\n", ¶ListPtr->data);
printf("The address of actual data: %ld\r\n", ¶ListPtr->data[0]);
printf("The address of second data: %ld\r\n", ¶ListPtr->data[1]);
}
//初始化线性表
SeqListPtr seqListInit(int paraData[], int paraLength) {
SeqListPtr resultPtr = (SeqListPtr)malloc(sizeof(struct SeqList));
for (int i = 0; i < paraLength; i ++) {
resultPtr->data[i] = paraData[i];
}
resultPtr->actualLength = paraLength;
return resultPtr;
}
//插入数据
void seqListInsert(SeqListPtr paraListPtr, int paraPosition, int paraValue) {
// 1.检查空间
if (paraListPtr->actualLength >= LIST_MAX_LENGTH) {
printf("空间不够,不能插入数据\r\n");
return;
}
// 2.检查位置
if (paraPosition < 0) {
printf("数据插入位置错误\n");
return;
}
if (paraPosition > paraListPtr->actualLength) {
printf("不能插入:位置 %d 大于线性表长度 %d\r\n", paraPosition, paraListPtr->actualLength);
return;
}
// 3.移动数据
for (int i = paraListPtr->actualLength; i > paraPosition; i --) {
paraListPtr->data[i] = paraListPtr->data[i - 1];
}
// 4.插入数据
paraListPtr->data[paraPosition] = paraValue;
// 5.更新长度
paraListPtr->actualLength ++;
}
//测试插入操作
void seqInsertTest() {
int i;
int tempArray[5] = {3, 5, 2, 7, 4};
printf("---- 进行顺序插入测试 ----\r\n");
//初始化的线性表
SeqListPtr tempList = seqListInit(tempArray, 5);
printf("初始化的线性表为: ");
outputList(tempList);
// 首位插入
printf("在首位插入后: ");
seqListInsert(tempList, 0, 8);
outputList(tempList);
// 尾部插入
printf("在尾部插入后: ");
seqListInsert(tempList, 6, 9);
outputList(tempList);
// 尾部之外插入
printf("在尾部之外插入 \r\n");
seqListInsert(tempList, 8, 9);
printf("线性表为:");
outputList(tempList);
// 连续插入
for (i = 0; i < 5; i ++) {
printf("插入 %d.\r\n", (i + 10));
seqListInsert(tempList, 0, (i + 10));
outputList(tempList);
}
printf("---- 顺序插入测试结束 ----\r\n\n");
}
//删除数据
int seqListDelete(SeqListPtr paraListPtr, int paraPosition) {
// 检查位置
if (paraPosition < 0) {
printf("错误的位置: %d.\r\n", paraPosition);
return -1;
}
if (paraPosition >= paraListPtr->actualLength) {
printf("不能删除:位置 %d 超出线性表长度 %d\r\n", paraPosition, paraListPtr->actualLength);
return -1;
}
// 2.移动数据
int resultValue = paraListPtr->data[paraPosition];
for (int i = paraPosition; i < paraListPtr->actualLength; i ++) {
paraListPtr->data[i] = paraListPtr->data[i + 1];
}//
// 3.更新长度
paraListPtr->actualLength --;
// 4.返回值
return resultValue;
}
//测试删除操作
void seqDeleteTest() {
int tempArray[5] = {3, 5, 2, 7, 4};
printf("---- 进行数据删除测试 ----\r\n");
// 初始化的线性表
SeqListPtr tempList = seqListInit(tempArray, 5);
printf("初始化的线性表为: ");
outputList(tempList);
// 删除首位数据
printf("删除首位数据: ");
seqListDelete(tempList, 0);
outputList(tempList);
// 删除尾部数据
printf("删除尾部数据: ");
seqListDelete(tempList, 3);
outputList(tempList);
// 删除第二个数据
printf("删除第二位数据: ");
seqListDelete(tempList, 1);
outputList(tempList);
// 删除第五位数据
printf("删除第五位数据 : ");
seqListDelete(tempList, 5);
outputList(tempList);
// 删除第-6位数据
printf("删除第-6位数据: ");
seqListDelete(tempList, -6);
outputList(tempList);
printf("---- 删除数据测试结束 ----\r\n");
outputMemory(tempList);
}
void main()
{
seqInsertTest();
seqDeleteTest();
}
---- 进行顺序插入测试 ----
初始化的线性表为: 3 5 2 7 4
在首位插入后: 8 3 5 2 7 4
在尾部插入后: 8 3 5 2 7 4 9
在尾部之外插入
不能插入:位置 8 大于线性表长度 7.
线性表为:8 3 5 2 7 4 9
插入 10.
10 8 3 5 2 7 4 9
插入 11.
11 10 8 3 5 2 7 4 9
插入 12.
12 11 10 8 3 5 2 7 4 9
插入 13.
空间不够,不能插入数据
12 11 10 8 3 5 2 7 4 9
插入 14.
空间不够,不能插入数据
12 11 10 8 3 5 2 7 4 9
---- 顺序插入测试结束 ----
---- 进行数据删除测试 ----
初始化的线性表为: 3 5 2 7 4
删除首位数据: 5 2 7 4
删除尾部数据: 5 2 7
删除第二位数据: 5 7
删除第五位数据 : 不能删除:位置 5 超出线性表长度 2.
5 7
删除第-6位数据: 错误的位置: -6.
5 7
---- 删除数据测试结束 ----
The address of the structure: 8263248
The address of actualLength: 8263248
The address of data: 8263252
The address of actual data: 8263252
The address of second data: 8263256