数据结构(1)顺序表及其实现

顺序表

众所周知,顺序表是线性表的一种。
所谓线性表,就是数据按照线性结构被组织起来,而没有分叉,每个元素都有唯一的其唯一前驱和后继(除收尾外);
顺序表,就是采用顺序存储方式的线性表;
所谓顺序存储方式,就是逻辑上相邻的数据,在计算机内的存储位置也相邻

代码如下
第一版本代码(未使用面向对象编程,且transplantablity较差)

#include <iostream>
using namespace std;


const int Maxsize = 100;


//implement the stationary list
    typedef struct{
        int data[Maxsize];
        int length;
    }StationaryList1;

    //declare a Dynamical List (by operater *)

    typedef struct{
        int *element;
        int length;
    }DynamicalList1;

    // improve the transplantablily of programm

    typedef int ElementType;
    typedef struct{
        ElementType *element;
        //当前element[]长度,一开始定义的时候啥都没有,长度为0
        //随着输入数据的一个个输入,element[]越来越长,
        //相应length也一个一个加
        int length;
    }DynamicalList2;




// prototype of the funtions of operations
bool Initialize_List(DynamicalList1 &List1);
bool Create_List(DynamicalList1 &List);
bool Get_Element_Of_List(DynamicalList1 List, int target_suffix, int &target_element);
int Locate_Element_Of_List(DynamicalList1 List,int Target_Element);
bool Insert_Element_In_List(DynamicalList1 &List, int Inserter, int Position);
bool Delete_Element_Of_List(DynamicalList1 &List, int Position, int &buffer);


// Sequential list and its implementation
int main()
{


    //declare a stationary list
    StationaryList1 List1;

    List1.length = 1;

    cout<<List1.length<<endl;


    return 0;
}

//Now we have some basic operations to perform on the List(whether it's dynamical or stationary)
//1. initialization

// use the operator '&' before the variable List1
//means that we pass the real pamameter(实参)/address to
//the funciton,so if the funtion change some arrtibutes of
//the variable/List1,the List1 will keep the changes
//after the termination of the execution of the funtion
bool Initialize_List(DynamicalList1 &List1){
    //initialze the List.element
    //so that it becomes a integer array with
    //elements which are all random numbers
    //that's why we use the keyword "new"
    List1.element = new int[Maxsize];

    if(!List1.element)
    //fail to allocate space to the array
        return false;

    // In the step of initialization
    // the squential list does not have any element
    // so we set the length of the list be zero
    List1.length = 0;
    return true;


}

//2. Creation: input the data to the Sequential List
//输入数据的类型必须和定义的类型相一致

//算法步骤
//1) 初始化 下标变量i= 0,判断顺序表是否已满;如果是,结束;否则执行2)
//2) 输入一个数据元素x
//3) 将数据x存入顺序表的第i个位置(有点缓冲的感觉),也就是List.element[i] = x,然后i++
//4) 顺序表长度加一(顺序表的一个attribute),即List.length++
//5) 重复上述步骤,直到输入数据全部进入顺序表

bool Create_List(DynamicalList1 &List){
    int input_data;
    int suffix = 0;

    //If we input -1,the process of creation will terminate
    while(input_data!=-1){

        if(List.length == Maxsize){
            cout<<"The sequential list has been full!"<<endl;
            return false;

        }
        cin>>input_data;
        List.element[suffix] = input_data;
        suffix ++;
        List.length++;
    }
    return true;
}

//3. Getting value
//查找顺序表中的值
// 查找表函数就不必穿实参了,传入形参即可
//因为我们并不想在查找表的过程中改变这个表
bool Get_Element_Of_List(DynamicalList1 List, int target_suffix, int &target_element){
    //这边用下标,下标和数组某个元素的位置差1
    //数据位置从0开始算,下标从1开始算
    if(target_suffix <1 || target_suffix > List.length)
        return false;
    target_element = List.element[target_suffix -1];

    return true;

}


//4. SearchVlaue 查找某个值是否在List里面
//一般来讲,从第一个逐个查找的话,目标值如果和List的第一个元素一样的话,等于只需要
//执行一次比较(运算)
// 因此,平均而言,找到一个元素是否在List里,平均需要执行的比较运算数为
//1+2+···+n = (n+1)/2
//所以这种方法时间复杂度为O(n)
//当然,我们可以用二分法让时间复杂度缩减到O(log n)
//日后再谈

//这也仅仅需要传入形参即可,返回的是位置(suffix)
//若找不到,返回-1
int Locate_Element_Of_List(DynamicalList1 List,int Target_Element){

    for(int i = 0;i<List.length;i++){

        if(List.element[i] == Target_Element)
            //目标元素在List里,且为List的第i+1个元素(起始位置为1)
            //准确地讲,是第一次出现的
            //该元素在List里至少存在一个
            return i+1;
    }
    //if traversing all the elements
    //we still cannot find the element in the List
    return -1;
}

// 5. Insertion 插入
// 在顺序表的第i个位置插入一个1个元素
//原理就是:从最后一个元素开始,最后一个元素后移一个位置
//然后倒数第二个也后移
//依次后移,直到第i个元素也后移
//然后在那个腾出来的地方插入给定的元素

//steps
//1) 先判断插入位置i是否valid(1≤ i ≤List.length),即判断能否插入
//,可以在第一个元素之前插入,也可以在最后一个(第List.length)元素之后插入
//  相当于append
//2) 判断(此时未被插入的)顺序表是否已经满了
//3) 若满了,返回-1,显示插入失败;若未满,则将第List.length个元素至第i个元素
//依次向后移动一位,让第i个位置空出来
//4) 将给定元素放到第i个元素
//5) List.length++,同时返回插入成功


//算法复杂度分析
// 我们可以第一个元素之前插入(插到第一个位置),也可以在第二个···
//以至于在第n(n == length)个元素之前插入
//更可以在第n+1个元素之前(第n个元素之后)插入)——相当于append
//因此,一共有n+1种情况
//易知,若要插到第i个元素的位置,相应地,我们需要移动(n+1-i)个元素————等价执行(n+1-i)次移动操作
//则平均每次插入,需要执行的“移动”操作次数为(∑(n+1-i))/(n+1) i从1到n+1
//求得为 ———— 2/n次,又因为最终插入的操作,时间复杂度为O(1)
//故总的时间复杂度为O(n)




//因为这种operaton要改变原有的LIst
//因此要pass实参进去
bool Insert_Element_In_List(DynamicalList1 &List, int Inserter, int Position){
    //o△xxxxxx△o
    //xxxxxx表示待插入的List
    //三角形是可以插入的
    //圆圈是不能插入的位置,也就是说,List的末尾可以插入!
    //我们可以顺带实现append功能
        if(Position<1 || Position>List.length+1)
        return false;
    // full or not
    if(List.length == Maxsize){
//        cout<<"The list has been full!"<<endl;
        return false;
    }
     else{
            //理解这个-1 这是第List.length个元素储存的位置
            //在List.length-1个格子里
         for(int i = List.length-1; i >= Position-1 ;i-- ){
            // 全体依次后移
            List.element[i+1] = List.element[i];
         }
        List.element[Position-1] = Inserter;
        List.length++;
        return true;
    }

}

//6. Deletion 删除
//从顺序表中删除一个元素,就是把那个位置清空,然后后面的元素依次前移,最后List.length--
//具体操作可以是,执行把第i个元素(第i-1位置)删除,先将该元素暂存到某一variable中
//then, 第i+1个元素直到最后一个元素依次前移
//易知复杂度亦为O(n)

//步骤
//1) 判断删除的元素下标是否合法(0 ≤position-1 ≤List.length-1)
//2) 若不合法,返回false;若合法,将该元素暂存于某个temporary变量中
//3) 第i+1 个元素至最后一个元素(第length个元素)依次前移
//4) List.length--;返回True

bool Delete_Element_Of_List(DynamicalList1 &List, int Position, int &buffer){


    if((Position-1)<0 || Position>List.length )
        return false;


    buffer = List.element[Position-1];

    for(int i = Position-1;i<List.length;i++){
        List.element[i] = List.element[i+1];
    }

    List.length--;
    return true;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值