数据结构:顺序表

1.线性表

        1.1概念

一对一的数据所组成的关系称为线性表,注意线性表是逻辑结构

线性表中的数据元素可以是各种各样的,但同一线性表中的元素必定 具有相同的特性,即同一数据对象(26个英文字母),相邻的数据之间 是一对一的关系,比如B字母节点(数据节点)前面是A字母节点,后面 是C字母节点,线性表的特性如下:

(1) 存在唯一的一个被称为"第一个"的数据元素

(2) 存在唯一的一个被称为"最后一个"的数据元素

(3) 处了第一个外,集合中每一个数据元素只有一个前驱节点

(4) 除了最后一个外,集合中每个数据元素均只有一个后驱节点

        举例:生活中的线性表例子非常多,比如一个班级中的以学号编排的学生、一座图书馆中的以序号编排的图书、一条正常排队等候的队列、一摞从上到下堆叠的餐盘,这些都是线性表。他们的特点都是:除了首尾两个元素,其余任何一个元素前后都对应相邻的另一个元素。

注意:

1.线性表是一种数据内部的逻辑关系,与存储形式无关

2.线性表既可以采用连续的顺序存储(数组),也可以采用离散的 链式存储(链表)

3.顺序表和链表都称为线性表。

2.顺序表

        2.1概念

顺序表:顺序存储的线性表

顺序存储就是将数据存储到一片连续的内存中,在C语言环境下,可以 是具名的栈数组,或者是匿名的堆数组。

存储方式不仅仅只是提供数据的存储空间,而是必须要能体现数据之间的逻辑关系。当采用顺序存储的方式来存放数据时,唯一能用来表达数据间本身的逻辑关系的就是存储位置。比如队列中的两个人,小明和小花,如果小明在逻辑上排在相邻的小花的前面,那么在存储位置上也必须把小明存放在相邻的小花的前面。

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

typedef struct 
{
    int cap;   // 顺序表容量
    int last;     // 顺序表元素下标
    int *data;     // 指向顺序表的首元素地址
}sequenList;

//初始化顺序表
sequenList *init_seque(int cap)
{
    if(cap <= 0)
        return NULL;
    //给顺序表管理结构体分配空间
    sequenList *head = malloc(sizeof(sequenList));
    if(head == NULL)
        return NULL;

    head->cap = cap;
    head->last = -1;
    head->data = calloc(cap,sizeof(int));
    if(head->data == NULL)
        return NULL;
    return head;
}

//判断表是否已满
bool isFull(sequenList *head)
{
    if(head->cap == head->last+1)
        return true;
    return false;
}

//判断正负
bool absd(int data)
{
    if(data < 0)
        return true;
    return false;
}

//删除绝对值
bool deleted(sequenList *head,int data)
{
    if(head == NULL)
        return false;
    int i = 0;
    while(i <= head->last)
    {
        if(head->data[i] == data)
        {
            for(int j = i; j < head->last; j++)
            {
                head->data[j] = head->data[j+1];
            }
            head->last--;
            
            //因为删除1位之后所有位置前移1,而下一步是i++,所以需要让i=-1,i++重新回归0位进行判断,否则可能漏掉一些相同的数字
            i = -1;
        }  
        i++;
    }
    if(i == head->last)
        return true;
    return true;
}

//冒泡排序
bool order(sequenList *head)
{
    if(head == NULL)
        return false;
    for(int i = 0; i < head->last; i++)
    {
        for (int j = 0;head->data[j] < 0; j++)
        {
            head->data[j] = ~(head->data[j] -1);
            deleted(head ,head->data[j]);
            j--;
        }
        for(int j = 0; j < head->last -i; j++)
        {
            if(head->data[j] > head->data[j+1])
            {
                int temp = head->data[j];
                head->data[j] = head->data[j+1];
                head->data[j+1] = temp;
            }
        }
    }
    return true;
}

// 插入数据
bool insert(sequenList *head, int data)
{
    if(head == NULL)
        return false;
    //判断数据是否已满
    if(isFull(head))
        return false;

    head->data[++head->last] = data;
    return true;
}

//判断如果错误则输出true,这样下面的错误判断才会接受运行,输出false
//也就是如果head正常则输出false,预防的程序不会运行
bool isEmpty(sequenList *head)
{
    if(head->last == -1)
        return true;
    return false;
}
//显示插入的数据
void showList(sequenList *head)
{
    if(isEmpty(head))
        return;
    for(int j = 0; j < (head->last+1); j++)
    {
        printf("%d ",head->data[j]);
    }
    printf("\n");
}

//销毁顺序表释放空间
void destroy(sequenList *head)
{
    if(head == NULL)
        return;

    free(head->data);
    head->data = NULL;
    free(head);
    head = NULL;
}

//主函数
int main(int argc, char const *argv[])
{
    sequenList *head = init_seque(10);
    if(head == NULL)
    {
        printf("init failed\n");
        return -1;
    }
	//一次性输入,有个数限制(和挨个输入取其一)
    for(int i = 0; i < 5; i++)
    {
        int data;
        scanf("%d", &data);
        //将输入插入到表
        insert(head,data);
    }
    
    //挨个输入输出,无个数限制
    while (1)
    {
        int data;
        // 拿不到数据,表示缓冲区输入的是字符
        if(scanf("%d",&data) == 0)
            break;

        if(data > 0)
        {
            bool ret = insert(head,data);
            if(!ret)
            {
                printf("数据已满\n");
                break;
            }
            showList(head);
        }
        else if(data < 0)
        {
            data = ~(data -1);
        	bool ret = deleted(head, data);
		    if(!ret)
		    {
		    	printf("数据为空\n");
		    	break;
		    }
		    showList(head);
        }
            
    }
    
    //删除负数和绝对值的判断(如果是一次性输入需要,但是挨个输入输出就不需要了)
    for(int i = 0; i < head->last; i++)
    {
        //如果使用if,当负数的绝对值在负数前面时,i需要减2,否则会漏掉负数后面紧挨着的负数
        //if(head->data[i] < 0)
        for(;head->data[i] < 0;)
        {
            head->data[i] = ~(head->data[i] -1);
            deleted(head, head->data[i]);
            //i -= 2; 
            i--; //for循环使用或者把删除放在排序后面;
        }
    }
    
    //修改插入数据顺序
    order(head);
    
    //显示顺序表
    showList(head);
    
    //销毁,释放空间,否则在许多程序一起运行的时候此程序不用也会占用空间,可能会造成系统卡顿,需要进行释放,养成好习惯。
    destroy(head);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值