静态顺序表的基本操作

顺序表
  顾名思义,就是用一段连续的存储单元依次存储数据元素的线性结构 。
  静态顺序表即顺序表的最大容量是确定的。
这里写图片描述
接下来我们要完成的基本操作是:
初始化
打印
尾部插入
尾部删除
头部插入
头部删除
查找指定元素
指定位置插入
删除指定位置元素
删除指定元素
删除所有的指定元素
返回顺序表的大小
判断顺序表是否为空
冒泡排序
选择排序
选择排序的优化
二分查找
二分查找递归写法
首先我们定义一个结构体
结构体成员是:数组和链表有效元素的个数

#define MAX 10                    //链表的最大容量
typedef int DataType;             //将int重命名为DataType
typedef struct SeqList
{
    DataType data[MAX];           //MAX=10
    int sz;                       //容量(存入有效元素的个数)
}SeqList,*qSeqList;

  由于顺序表里存放的元素的类型是未知的,所以将int重命名为DataType,若想在顺序表中存储其他类型的数据,只需将int修改为对应的类型即可。
初始化函数
   数组初始化(全部初始化为0)+ 容量初始化(刚开始容量为0)

//初始化函数
void SeqListInit(qSeqList seq)
{
    assert(seq);
    //初始化整个数组
    memset(seq->data,0, MAX*sizeof(DataType));
    //初始化sz
    seq->sz = 0;
}

打印
  循环依次打印

//打印
void PrintSeqList(qSeqList seq)
{
    int i = 0;
    assert(seq);
    for (i = 0; i < seq->sz; i++)
    {
        printf("%d ", seq->data[i]);
    }
    printf("\n");
}

尾部插入
  注意判断是否可以插入

//尾插法
void PushBack(qSeqList seq, DataType data)
{
    assert(seq);
    //判断是否可以插入即判断容量是否小于MAX
    if (seq->sz >= MAX)
    {
        printf("容量已满,无法插入!\n");
        return;
    }
    //将数据插入到第seq->sz的位置上
    seq->data[seq->sz] = data;
    //容量++
    seq->sz++;
}

尾部删除

//尾部删除
void PopBack(qSeqList seq)
{
    assert(seq);
   //判断是否可以删除
    if (seq->sz == 0)
    {
        printf("数组为空,不能删除!");
        return;
    }
    //容量--
    seq->sz--;
}

头部插入

//头部插入
void PushFront(qSeqList seq, DataType data)
{
    int i;
    assert(seq);
    //判断是否可以插入
    if (seq->sz >= MAX)
    {
        printf("数组已满,不能插入!\n");
        return;
    }
    //元素全部后移
    for (i = seq->sz - 1 ; i >= 0; i--)
    {
        seq->data[i + 1] = seq->data[i];
    }
    //插入
    seq->data[0] = data;
    //容量++
    seq->sz++;


头部删除

//头部删除
void PopFront(qSeqList seq)
{
    int i = 0;
    assert(seq);
    //判断是否可以删除
    if (seq->sz == 0)
    {
        printf("数组为空,不能删除!\n");
        return;
    }
    //前移
    for (i = 1; i < seq->sz; i++)
    {
        seq->data[i - 1] = seq->data[i];
    }
    //容量--
    seq->sz--;
}

查找指定元素

int  Front(qSeqList seq, DataType data)
{
    int i = 0;
    assert(seq);
    for (i = 0; i < seq->sz; i++)
    {
        if (seq->data[i] == data)
            return i;
    }
    return -1;
}

指定位置插入

void Insert(qSeqList seq, int pos, DataType data)
{
    int i = 0;
    assert(seq);
    //判断是否可以插入
    if (seq->sz >= MAX)
    {
        printf("数组已满,不能插入!\n");
        return;
    }
    //指定位置以及之后的元素后移
    for (i = seq->sz - 1; i >= pos; i--)
    {
        seq->data[i + 1] = seq->data[i];
    }
    //指定位置插入
    seq->data[pos] = data;
    //容量++
    seq->sz++;
}

删除指定位置元素

void Erase(qSeqList seq, int pos)
{
    int i = 0;
    assert(seq);
    //判断是否可以删除
    if (seq->sz == 0)
    {
        printf("数组为空,不能被删除!\n");
        return;
    }
    //指定位置之后的所有元素前移
    for (i = pos + 1; i < seq->sz; i++)
    {
        seq->data[i - 1] = seq->data[i];
    }
    //容量--
    seq->sz--;
}

  由于指定位置插入和指定位置删除都是在查找指定元素成立的条件下测试的,即是在pos合法的情况下插入和删除,所以不需要判断位置(pos)的合法性,如果不是在查找指定元素成立的条件下进行指定位置插入和删除就需要判断pos的合法性。
删除指定元素

void Remove(qSeqList seq, DataType data)
{

    int i = 0;
    assert(seq);
    for (i = 0; i < seq->sz; i++)
    {
        if (seq->data[i] == data)
        {
            break;     //跳出循环,i即为指定元素的位置
        }
    }
    if (i < seq->sz)   //若i有效
    {
        int j = 0;
        {
            seq->data[j - 1] = seq->data[j];          
             //指定元素之后的所有元素前移
        }
        //容量--
        seq->sz--;
    }
}

删除所有的指定元素

void Removeall(qSeqList seq, DataType data)
{
    int i = 0;
    assert(seq);
    for (i = 0; i < seq->sz; i++)

    {
        if (seq->data[i] == data) // i即为删除对象的位置 
        {
            int j = 0;
            for (j = i + 1; j < seq->sz; j++)   
            {
                 //指定元素之后的所有元素前移 
                seq->data[j - 1] = seq->data[j];          
            }
            //容量--
            seq->sz--;
        }
    }
}

返回顺序表的大小

int size(qSeqList seq)
{
    assert(seq);
    return seq->sz;
}

判断顺序表是否为空

int Empty(qSeqList seq)
{
    assert(seq);
    return seq->sz == 0;//等式成立返回真(1)
}

冒泡排序

void Bubble(qSeqList seq)
{
    int i = 0;
    int j = 0;
    int flag = 0;
    assert(seq);
    for (i = 0; i < seq->sz - 1; i++)
    {
        flag = 0;
        for (j = 0; j < seq->sz - 1- i; j++)
        {
            if (seq->data[j] < seq->data[j + 1])
            {
                swap(seq->data + j, seq->data + j + 1); //交换
                flag = 1;     //用于节约时间,如果flag不改变,证明该次有序,不用进行下次
            }
        }
        if (flag == 0)   //循环一次后判断flag是否为0,如果为0,即有序,直接返回
            return;
    }
}
static swap(DataType * px, DataType * py)
{
    DataType tmp = 0;
    tmp = *px;
    *px = *py;
    *py = tmp;
}

选择排序

  选择排序:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的最后位置,直到全部待排序的数据元素排完。

void Selectsort(qSeqList seq)
{
    int maxpos = 0;//最大值的下标
    int i = 0;
    int j = 0;
    assert(seq);
    for (i = 0; i < seq->sz-1; i++)
    {
        maxpos = 0;
        //寻找最大值
        for (j = 1; j < seq->sz-i ; j++)
        {
            if (seq->data[j] > seq->data[maxpos])
                maxpos = j ;             
        }
      //若最大值不是最后一个元素,则将最大值和最后一个元素交换
        if (maxpos != j-1)
        {
            swap(seq->data + maxpos, seq->data +j-1);
        }   
    }
}

选择排序的优化

  选择排序的优化:每一次从待排序的数据元素中选出最小和最大的两个元素,存放在序列的起始位置最后位置,直到全部待排序的数据元素排完。

void SelectsortOp(qSeqList seq)
{
    int left = 0;
    int right = seq->sz - 1;
    int i = 0;
    int maxpos = 0;  //最大值下标
    int minpos = 0;  //最小值下标
    assert(seq);
    while (left <= right)
    {
        maxpos = left;
        minpos = left;
        //找出最大值和最小值
        for (i = left+1; i <= right; i++) 
        {
            if (seq->data[i]>seq->data[maxpos])
                maxpos = i;
            if (seq->data[i] < seq->data[minpos])
                minpos = i;
        }
        if (maxpos != right)
        {
            swap(seq->data + maxpos, seq->data + right);   
            //最大值放在最右边
        }
        //如果最小值在right指向的位置
        //由于right指向的位置已经变成了最大值
        //所以应该修改最小值的下标,使得其到原来最大值的地方
        if (minpos == right)
        {
            minpos = maxpos;   
        }
        if (minpos != left)
        {
            swap(seq->data + minpos, seq->data + left);   
             //最小值放在最左边
        }
        left++;
        right--;
    }
}

二分查找

//二分查找
int BinarySearch(qSeqList seq, DataType data)
{
    int left = 0;
    int right = seq->sz - 1;
    int mid = 0;
    assert(seq);
    while (left <= right)
    {
        mid = left + (right - left) / 2;
        if (seq->data[mid] > data) //要找的数据在mid左边
        {
            right = mid - 1;
        }
        else if (seq->data[mid] < data)//要找的数据在mid左边
        {
            left = mid + 1;
        }
        else 
        {
            return mid;
        }
    }
    return -1;  //没找到
}

二分查找递归写法

int BinarySearch_R(qSeqList seq, int left, int right, DataType data)
{
    int mid = left + (right - left) / 2;
    assert(seq);
    if (left <= right)
    {
        if (seq->data[mid] > data)
        {
           return BinarySearch_R(seq, left, mid - 1, data);
        }
        else if (seq->data[mid] < data)
        {
           return BinarySearch_R(seq, mid + 1, right, data);
        }
        else
        {
            return mid;
        }
    }
    return -1;
}

.h文件(头文件)
  存放函数的声明以及全局变量

#ifndef __SEQLIST_H__
#define __SEQLIST_H__

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

#define MAX 10                    //链表的最大容量
typedef int DataType;             //将int重命名为DataType
typedef struct SeqList
{
    DataType data[MAX];           //MAX=10;
    int sz;                       //容量(已经存入多少个有效元素)
}SeqList,*qSeqList;

void SeqListInit(qSeqList seq);                    //初始化函数
void PushBack(qSeqList seq, DataType data);        //尾插法
void PopBack(qSeqList seq);                        //尾部删除    
void PushFront(qSeqList seq, DataType data);       //头插法
void PopFront(qSeqList seq);                       //头部删除
int  Front(qSeqList seq, DataType data);           //查找指定元素
void Insert(qSeqList seq, int pos, DataType data); //指定位置插入
void Erase(qSeqList seq, int pos);                 //删除指定位置元素
void Removeall(qSeqList seq, DataType data);       //删除全部指定元素
void Remove(qSeqList seq, DataType data);          //删除指定元素
int size(qSeqList seq);                            //返回顺序表的大小
int Empty(qSeqList seq);                           //判断结构体是否为空
void Bubble(qSeqList seq);                         //冒泡排序
void Selectsort(qSeqList seq);                     //选择排序
void SelectsortOp(qSeqList seq);                   //选择排序的优化
int BinarySearch(qSeqList seq, DataType data);    // 二分查找
int BinarySearch_R(qSeqList seq, int left, int right, DataType data); //二分查找递归
void PrintSeqList(qSeqList seq);                   //打印  

#endif  //__SEQLIST_H__

测试文件(test.c)

#include"SeqList.h"


//尾部测试
testBack()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //尾插法
    PushBack(&seq, 1);
    PushBack(&seq, 2);
    PushBack(&seq, 3);
    //打印
    PrintSeqList(&seq);
    //尾部删除
    PopBack(&seq);
    //打印
    PrintSeqList(&seq);
}

//头部测试
testFront()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //头部插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //打印
    PrintSeqList(&seq);
    //头部删除
    PopFront(&seq);
    //打印
    PrintSeqList(&seq);
}

//查找
void testFind()
{
    //定义一个结构体seq
    SeqList seq;
    int pos = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //查找指定元素
    pos = Front(&seq, 1);
    if (pos == -1)
    {
        printf("找不到!\n");
        return;
    }
    else
    {
        printf("下标为:%d\n", pos);
    }
}


//指定位置插入
void testInsert()
{
    //定义一个结构体seq
    SeqList seq;
    int pos = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //查找指定元素
    pos = Front(&seq, 1);
    if (pos == -1)
    {
        printf("找不到指定位置!\n");
        return;
    }
    else
    {
        //指定位置插入
        Insert(&seq, pos, 5);
        //打印
        PrintSeqList(&seq);
    }
}

//指定位置删除
void testErase()
{
    //定义一个结构体seq
    SeqList seq;
    int pos = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //查找指定元素
    pos = Front(&seq, 3);
    if (pos == -1)
    {
        printf("找不到指定位置!\n");
        return;
    }
    else
    {
        //指定位置删除
        Erase(&seq, pos);
        //打印
        PrintSeqList(&seq);
    }
}

//删除指定元素
void testRemove()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 1);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    Remove(&seq, 1);
    //打印
    PrintSeqList(&seq);
}


//删除全部指定元素
void testRemoveall()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 1);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    Removeall(&seq, 1);
    //打印
    PrintSeqList(&seq);
}

//返回顺序表的大小
void testsize()
{
    //定义一个结构体seq
    SeqList seq;
    int l = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    l = size(&seq);
    printf("size=%d \n", l);
}

//判断顺序表是否为空
void testEmpty()
{
    //定义一个结构体seq
    SeqList seq;
    int s = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    s = Empty(&seq);
    if (s == 1)
    {
        printf("结构体为空!\n");
        return;
    }
    else
        printf("结构体不为空!\n");
}
//冒泡排序
void testBubble()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //打印
    PrintSeqList(&seq);
    Bubble(&seq);
    //打印
    PrintSeqList(&seq);
}
//选择排序
testSelectsort()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 1);
    PushFront(&seq, 2);
    PushFront(&seq, 3);
    PushFront(&seq, 4);
    //打印
    PrintSeqList(&seq);
    Selectsort(&seq);
    //打印
    PrintSeqList(&seq);
}


//选择排序的优化
void testSelectsortOp()
{
    //定义一个结构体seq
    SeqList seq;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 1);
    PushFront(&seq, 2);
    PushFront(&seq, 3);
    PushFront(&seq, 4);
    //打印
    PrintSeqList(&seq);
    SelectsortOp(&seq);
    //打印
    PrintSeqList(&seq);
}

//二分查找
void testBinarySearch()
{
    //定义一个结构体seq
    SeqList seq;
    int pos = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //打印
    PrintSeqList(&seq);
    pos = BinarySearch(&seq,4);
    if (pos == -1)
    {
        printf("找不到该元素!\n");
        return;
    }
    else
    {
        printf("下标为:%d\n", pos);
        return;
    }
}
//二分查找的递归
void testBinarySearch_R()
{
    //定义一个结构体seq
    SeqList seq;
    int pos = 0;
    //初始化结构体
    SeqListInit(&seq);
    //插入
    PushFront(&seq, 4);
    PushFront(&seq, 3);
    PushFront(&seq, 2);
    PushFront(&seq, 1);
    //打印
    PrintSeqList(&seq);
    pos = BinarySearch_R(&seq, 0,seq.sz-1,0);
    if (pos ==-1 )
    {
        printf("找不到该元素!\n");
        return;
    }
    else
    {
        printf("下标为:%d\n", pos);
        return;
    }
}
void test()
{

    //testBack();
    //testFront();
    //查找指定元素
    //testFind();
    //指定位置插入
    //testInsert();
    //指定位置删除
    //testErase();
    //删除指定元素
    //testRemove();
    //删除全部指定元素
    //testRemoveall();
    //返回顺序表的大小
    //testsize();
    //判断顺序表是否为空
    //testEmpty();
    //冒泡排序
    //testBubble();
    //选择排序
    //testSelectsort();
    //选择排序优化
    //testSelectsortOp();
    //二分查找
    //testBinarySearch();
    //二分查找的递归
    testBinarySearch_R();
}
int main()
{
    test();
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值