在实现顺序表之前先来了解几个概念。
1、线性表
n(n>=0)个数据元素组成的一个有限序列,可以在其任何位置上进行插入和删除操作的线性数据结构。
从数据在物理内存存储形式上线性表可分为:顺序表和链表。
由上图可看出:
线性表中数据与数据之间存在一对一的关系,即除第一个元素和最后一个元素外,每个元素都有唯一的直接前驱和唯一的直接后继,第一个元素没有前驱,最后一个元素没有后继。
2、顺序表
用一段地址连续的存储单元依次存储数据元素的线性结构。
地址连续的空间,一般情况下采用数组,数组有静态数组和动态数组,顺序表也分静态顺序表和动态顺序表。
3、顺序表的实现
以下先实现静态顺序表的增删查改。
seqlist.h
首先,保证编译一次,需要添加下面代码;
#pragma once
创建结构体
#define SeqListMaxSize 1000 //定义宏,方便后续更改顺序表元素大小 typedef char SeqListType; typedef struct seqlist { SeqListType data[SeqListMaxSize]; size_t size; //线性表中的有效元素 }SeqList;
这里需要注意一点,size_t占几个字节?
(1)在32位操作系统中,占4个字节;
(2)在64位操作系统中,占8个字节;
下面开始实现具体的功能函数,需要注意的就是函数的命名,以下使用的函数功能名称,是约定俗成的,以后看到这类函数名,功能也是类似的。
void SeqListInit ( SeqList * seqlist );//初始化 void SeqListPushBack(SeqList * seqlist, SeqListType value);//往顺序表尾部插入value元素 void SeqListPopBack(SeqList *seqlist);//尾删 void SeqListPushFront(SeqList *seqlist,SeqListType value);//头插 void SeqListPopFront(SeqList *seqlist);//头删 void SeqListInsert(SeqList *seqlist, size_t pos, SeqListType value);//在pos位置插入value元素 void SeqListErase(SeqList *seqlist, size_t pos);//删除pos位置的元素 void SeqListRead(SeqList *seqlist, size_t pos);//读取pos位置的元素 void SeqListAlter(SeqList *seqlist, size_t pos, SeqListType value);//更改pos位置处的元素为value size_t SeqListFindIndex(SeqList *seqlist, SeqListType value);//查找元素value的下标 void SeqListRemove(SeqList *seqlist, SeqListType to_remove);//删除顺序表中to_remove的值 void SeqListRemoveAll(SeqList *seqlist, SeqListType to_remove);//删除顺序表中全部得to_remove的值 void SeqListBubbleSort(SeqList *seqlist);//冒泡排序 //函数指针 typedef int(*Cmp)(SeqListType a, SeqListType b); //如果a和b满足比较规则,返回1,否则返回0. //如果是升序排列,a<b就称为满足比较规则 void SeqListBubbleSortEx(SeqList *seqlist, Cmp cmp);
接下来是函数的具有实现,在seqlist.c 中实现:
seqlist.c
//顺序表初始化
void SeqListInit(SeqList * seqlist) { if (seqlist == NULL) {//非法输入 return; } seqlist->size = 0; }
//往顺序表尾部插入元素value
void SeqListPushBack(SeqList * seqlist, SeqListType value) { if (seqlist == NULL) { return; } if (seqlist->size >= SeqListMaxSize) { //顺序表已满 return; } seqlist->data[seqlist->size]= value; seqlist->size++; }
//尾删
void SeqListPopBack(SeqList *seqlist) { if (seqlist == NULL) { return; } if (seqlist->size == 0) {//顺序表是空 return; } --seqlist->size; return; }
//头插
void SeqListPushFront(SeqList *seqlist, SeqListType value) { if (seqlist == NULL) { return; } if (seqlist->size >= SeqListMaxSize) {//满了 return; } ++seqlist->size;//最好实现前置++,原因先不谈 //seqlist->size++; size_t i = seqlist->size - 1; for (; i > 0; --i) { seqlist->data[i] = seqlist->data[i - 1]; } seqlist->data[0] = value; return; }
//头删
void SeqListPopFront(SeqList *seqlist) { if (seqlist == NULL) { return; } if (seqlist->size == 0) {//空 return; } size_t i = 0; for (; i < seqlist->size - 1; ++i) { seqlist->data[i] = seqlist->data[i + 1]; } --seqlist->size; return; }
//在pos位置插入value元素
void SeqListInsert(SeqList *seqlist, size_t pos, SeqListType value) { if (seqlist == NULL) { return; } if (pos >= seqlist->size) {//越界了 return; } if (seqlist->size >= SeqListMaxSize) {//满了 return; } if (pos == 0) {//如果pos=0时,后面的--i为-1时,size_t是无符号长整型,负数为一个超级大的数值 //故转为头插函数 SeqListPushFront(&seqlist, value); } ++seqlist->size; size_t i = seqlist->size - 1; for (; i - 1 >= pos; --i) { seqlist->data[i] = seqlist->data[i - 1]; } seqlist->data[pos] = value; return; }
//删除pos位置的元素
void SeqListErase(SeqList *seqlist, size_t pos) { if (seqlist == NULL) { return; } if (seqlist->size == 0) {//空 return; } if (pos >= seqlist->size) {//pos值越界 return; } size_t i = pos; for (; i < seqlist->size - 1; ++i) { seqlist->data[i] = seqlist->data[i + 1]; } --seqlist->size; return; }
//读取pos位置的元素
void SeqListRead(SeqList *seqlist, size_t pos) { if (seqlist == NULL) { return; } if (seqlist->size == 0) { return; } printf("[%c]\n", seqlist->data[pos]); }
//更改pos位置处的元素为value
void SeqListAlter(SeqList *seqlist, size_t pos, SeqListType value) { if (seqlist == NULL) { return; } if (seqlist->size == 0) { return; } seqlist->data[pos] = value; }
//查找元素value的下标
size_t SeqListFindIndex(SeqList*seqlist, SeqListType value) { if (seqlist == NULL) { return; } if (seqlist->size == 0) { return; } size_t i = 0; for (; i < seqlist->size; ++i) { if (seqlist->data[i] == value) return i; } return -1; }
//删除顺序表中to_remove的值
void SeqListRemove(SeqList *seqlist, SeqListType to_remove) { if (seqlist == NULL) { return; } size_t pos = SeqListFindIndex(seqlist, to_remove); if (pos == (size_t)-1) { return;//没找到 } SeqListErase(seqlist, pos); return; }
//删除顺序表中全部得to_remove的值
void SeqListRemoveAll(SeqList *seqlist, SeqListType to_remove) { if (seqlist == NULL) { return; } while (1) { size_t pos = SeqListFindIndex(seqlist, to_remove); if (pos == (size_t)-1) { break; } SeqListErase(seqlist, pos); } }
//交换函数
void Swap(SeqListType *a, SeqListType *b) { SeqListType tmp = *a; *a = *b; *b = tmp; }
//冒泡排序
void SeqListBubbleSort(SeqList *seqlist) { if (seqlist == NULL) { return; } size_t count = 0;//count 表示冒泡次数 for (; count < seqlist->size; ++count) { size_t cur = 0;//当前位置 for (; cur < seqlist->size - 1 - count; ++cur) { if (seqlist->data[cur]>seqlist->data[cur + 1]) { Swap(&seqlist->data[cur], &seqlist->data[cur + 1]); } } } }
上传冒泡排序代码总乱序。。。保险起见,贴个图。。
贴个图总不至于再给我乱吧
//指定规则的排序
void SeqListBubbleSortEx(SeqList *seqlist, Cmp cmp) { if (seqlist == NULL) { return; } size_t count = 0;//count 表示冒泡次数 for (; count < seqlist->size; ++count) { size_t cur = 0;//当前位置 for (; cur < seqlist->size - 1 - count; ++cur) { if (!cmp(seqlist->data[cur],seqlist->data[cur+1])) { Swap(&seqlist->data[cur], &seqlist->data[cur + 1]); } } } }