顺序表:用一段地址连续的存储单元依次存储数据元素的线性结构
地址连续的空间,一般情况下采用数组,但数组有静态数组和动态数组,所以顺序表分为静态顺序表和动态顺序表。
静态顺序表的有关实现
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define MAX_SIZE 100
typedef int DataType;
typedef struct SeqList{
DataType array[MAX_SIZE];
int size; //1.保存数据表里已经有了的数据个数
//2.当前可用下标
}SeqList;
//初始化(函数设计)
void SeqListInit(SeqList *pSeq)
{
//1.初始化size
//2.可能需要把容器空间清空下(但是最后确定不需要)
assert(pSeq != NULL);
pSeq->size = 0;
}
//销毁
void SeqListDestroy(SeqList *pSeq)
{
assert(pSeq != NULL);
pSeq->size = 0;
}
//增
//1.尾插
void SeqListPushBack(SeqList *pSeq, DataType data)
{
assert(pSeq);
//特殊情况(满了)
if(pSeq->size >= MAX_SIZE){
assert(0);
printf("满了\n");
return ;
}
//通常情况
pSeq->array[pSeq->size] = data;
pSeq->size++;
}
//2.头插
void SeqListPushFront(SeqList *pSeq, DataType data)
{
int i = 0;
assert(pSeq);
//特殊情况(满了)
if(pSeq->size >= MAX_SIZE){
assert(0);
printf("满了\n");
return ;
}
//通用情况
for(i=pSeq->size; i>0; i--)
{
pSeq->array[i] = pSeq->array[i-1];
}
pSeq->array[0] = data;
pSeq->size++;
}
//3.插入
void SeqListInsert(SeqList *pSeq, int pos, DataType data)
{
int i = 0;
assert(pSeq);
//特殊情况(满了)
if(pSeq->size >= MAX_SIZE){
assert(0);
printf("满了\n");
return ;
}
//通常情况
for(i=pSeq->size; i>pos; i--)
{
pSeq->array[i] = pSeq->array[i-1];
}
pSeq->array[pos] = data;
pSeq->size++;
}
//删
//1.尾删
void SeqListPushPop(SeqList *pSeq)
{
assert(pSeq);
//特殊情况(空了)
if(pSeq->size <= 0){
printf("空了\n");
assert(0);
return ;
}
//通常情况
pSeq->size --;
}
//2.头删
void SeqListPopFront(SeqList *pSeq)
{
int i = 0;
assert(pSeq);
//特殊情况(空了)
if(pSeq->size <= 0){
printf("空了\n");
assert(0);
return ;
}
//通常情况
for(i=0; i<pSeq->size-1; i++)
{
pSeq->array[i] = pSeq->array[i+1];
}
pSeq->size--;
}
//3.删除
void SeqListErase(SeqList *pSeq, int pos)
{
int i = 0;
assert(pSeq);
assert(pos>=0 && pos<pSeq->size);
//特殊情况(空了)
if(pSeq->size <= 0){
printf("空了\n");
assert(0);
return ;
}
//通常情况
for(i=pos; i<pSeq->size-1; i++)
{
pSeq->array[i] = pSeq->array[i+1];
}
pSeq->size--;
}
//查询
//找到第一个遇到的数的下标,没找到返回-1(更理想的返回类型ssize_t)
int SeqListFind(SeqList *pSeq, DataType data)
{
int i = 0;
for(i=0; i<pSeq->size; i++)
{
if(data == pSeq->array[i]){
return i;
}
}
return -1;
}
//删除的第二种形态(根据数据删除)
//1.遇到的第一个数据
void SeqListRemove(SeqList *pSeq, DataType data)
{
int pos = SeqListFind(pSeq,data);
if(pos == -1)
{
return ;
SeqListErase(pSeq,pos);
}
}
//2.遇到的所有数据
void SeqListRemoveAll(SeqList *pSeq,DataType data)
{
int i,j;
for(i=0,j=0; i<pSeq->size; i++)
{
if(data != pSeq->array[i]){
pSeq->array[j] = pSeq->array[i];
j++;
}
}
pSeq->size = j;
}
//打印
void SeqListPrint(const SeqList *pSeq)
{
int i = 0;
assert(pSeq != NULL);
for(i = 0; i < pSeq->size; i++)
{
printf("%d ",pSeq->array[i]);
}
printf("\n");
}
void Test()
{
SeqList seqlist;
SeqListInit(&seqlist);//1.指针空间小2.改变值
SeqListPushBack(&seqlist,1);
SeqListPushBack(&seqlist,2);
SeqListPushBack(&seqlist,3);
SeqListPushBack(&seqlist,4);
SeqListPrint(&seqlist);
SeqListPushPop(&seqlist);
SeqListPrint(&seqlist);
SeqListPushFront(&seqlist,10);
SeqListPrint(&seqlist);
SeqListPopFront(&seqlist);
SeqListPrint(&seqlist);
SeqListInsert(&seqlist, 1, 100);
SeqListPrint(&seqlist);
SeqListErase(&seqlist, 2);
SeqListPrint(&seqlist);
}
static void Swap(DataType *a, DataType *b)
{
DataType t = *a;
*a = *b;
*b = t;
}
//冒泡排序
void SeqListBubble(SeqList *pSeq)
{
int isSort;//标记是否交换
int i, j;
for(i=1; i<pSeq->size; i++)
{
isSort = 1;
for(j=0; j<pSeq->size-1-i; j++)
{
if(pSeq->array[j] > pSeq->array[j+1]){
Swap(pSeq->array+j, pSeq->array+(j+1));
isSort = 0;
}
if(isSort == 0)
break;
}
}
}
//选择排序
void SeqListSort(SeqList *pSeq)
{
int min = 0;
int max = pSeq->size-1;
int minPos,maxPos;
while(min<max)
{
int i = 0;
minPos = min;
maxPos = min;
for(i=min+1; i<=max; i++)
{
if(pSeq->array[i]<pSeq->array[minPos])
{
minPos = i;
}
if(pSeq->array[i]>pSeq->array[maxPos])
{
maxPos = i;
}
}
Swap(pSeq->array+min,pSeq->array+minPos);
if(min == maxPos){
maxPos = minPos;
}
Swap(pSeq->array+max,pSeq->array+maxPos);
min++;
max--;
}
}
void Test2()
{
SeqList seqlist;
SeqListInit(&seqlist);//1.指针空间小2.改变值
SeqListPushBack(&seqlist,4);
SeqListPushBack(&seqlist,5);
SeqListPushBack(&seqlist,3);
SeqListPushBack(&seqlist,8);
SeqListPushBack(&seqlist,6);
SeqListPushBack(&seqlist,9);
SeqListPushBack(&seqlist,2);
SeqListPushBack(&seqlist,10);
SeqListPrint(&seqlist);
SeqListSort(&seqlist);
SeqListPrint(&seqlist);
SeqListBubble(&seqlist);
SeqListPrint(&seqlist);
}
动态顺序表的有关实现:
#pragma once
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
#define INIT_CAPACITY (3)
typedef struct SeqListD {
DataType * parray;
int capacity; // 当前容量 等于 静态顺序表 MAX_SIZE
int size; // 同静态顺序表
} SeqListD;
// 初始化/销毁/所有插入(尾插)
// 其他和静态顺序表完全一样
void SeqListDInit(SeqListD *pSeq)
{
// 为了获得容器空间
pSeq->capacity = INIT_CAPACITY;
pSeq->parray = (DataType *)malloc(sizeof(DataType)* pSeq->capacity);
assert(pSeq->parray);
// 这个和静态顺序表一样
pSeq->size = 0;
}
void SeqListDDestroy(SeqListD *pSeq)
{
free(pSeq->parray);
pSeq->capacity = 0;
pSeq->parray = NULL;
pSeq->size = 0;
}
static void ExpandIfRequired(SeqListD *pSeq)
{
DataType *newArray = (DataType *)malloc(sizeof(DataType)* pSeq->capacity);
int i = 0;
// 扩容条件
if (pSeq->size < pSeq->capacity) {
// 没满
return;
}
// 扩容
pSeq->capacity *= 2;
// 1. 申请新空间
assert(newArray);
// 2. 数据搬移
for (i = 0; i < pSeq->size; i++) {
newArray[i] = pSeq->parray[i];
}
// 3. 释放老空间,关联新空间
free(pSeq->parray);
pSeq->parray = newArray;
}
void SeqListDPushBack(SeqListD *pSeq, DataType data)
{
// 静态:如果满了,不处理/报错
// 动态:加入扩容机制
ExpandIfRequired(pSeq);
pSeq->parray[pSeq->size] = data;
pSeq->size++;
}
// 同理,所有插入都需要加入扩容机制
void Test3()
{
SeqListD sld;
SeqListDInit(&sld);
SeqListDPushBack(&sld, 1);
SeqListDPushBack(&sld, 2);
SeqListDPushBack(&sld, 3);
// 这下面会扩容
SeqListDPushBack(&sld, 4);
SeqListDPushBack(&sld, 5);
}
动态顺序表的实现大部分和静态顺序表都很相似,只不过动态顺序表要加上扩容机制。
主函数:
#include "seqlist.h"
#include "seqListd.h"
int main()
{
//Test();
//Test2();
Test3();
return 0;
}