C语言数据结构之顺序表

158 阅读3分钟

以下内容是本人在学习王道C语言训练营的相关代码,代码主要适用于考研的同学,但数据结构的思想是大致一样。

一、顺序表插入操作

声明:项目的结构是C++,且以数组的形式表示顺序表。

  • 逻辑思想

插入操作核心步骤:

  1. 检查插入的元素是否在合理范围内(1 <= i <= length+1) i指元素实际位置
  2. 顺序表内存还有空间
  3. 如果前面两个问题满足,则将待插入元素及后面的元素位置依次后移一位,否则不能插入
  4. 将待插入元素赋值到空位置中
  5. 顺序表的长度加一
  • 顺序表初始化和插入

注意点:

1.bool ListInsert(SqList *L,int pos,ElemType ele)中的第一个参数要使用指针,因为要改变该结构体的内容(地址传递)

2.符号.和->的作用和区别

  • A.a则A为对象或者结构体; 点号(.):左边必须为实体。

  • A->a则A为指针,->是成员提取,A->a是提取A中的成员a,A只能是指向类、结构、联合的指针; 箭头(->):左边必须为指针;

3.if (pos < 1 || pos > L->length+1)中的之所以要length+1 是为了说明可以在最后插入元素

#include <stdio.h>

#define MaxSize 50
typedef int ElemType;//elemtype表示任意类型
//定义顺序表
typedef struct {
    ElemType data[MaxSize];//以数组的形式,ElemType让
    int length;//顺序表的长度
} SqList;

//插入方法,参数分别为顺序表指针,插入的位置,插入的元素值
bool ListInsert(SqList &L,int pos,ElemType ele){
    //判断插入的位置是否在合理范围内
    if (pos < 1 || pos > L.length+1){//length+1 是为了在说明可以在最后插入
        return false;
    }
    //数组是否内存已满
    if (L.length == MaxSize){
        return false;
    }
    //把后面的元素依次往后移
    for (int i = L.length; i >= pos ; i--) {
        L.data[i] = L.data[i-1];
    }
    L.data[pos - 1] = ele;
    L.length++;//将数组长度加加
    return true;
}

//打印顺序表
void PrintList(SqList L){
    for (int i = 0; i < L.length; i++) {
        printf("%3d",L.data[i]);
    }
    printf("\n");
}
int main() {
    //初始化
    SqList L;
    bool ret;
    //手动添加顺序
    L.data[0] = 1;
    L.data[1] = 2;
    L.data[2] = 3;
    L.length = 3;//设置长度,很重要,刚刚没有写句话,就打印了failed
    ret = ListInsert(L,2,60);
    if (ret){
        printf("insert sqList success\n");
        PrintList(L);
    } else{
        printf("insert sqList failed\n");
    }
}

二、顺序表删除操作

//删除顺序表的元素
bool ListDelete(SqList &L,int i,ElemType &ele){
    //删除的元素是否在合理范围内
    if (i < 1 || i > L.length){
        return false;//一旦走到return函数就结束了
    }
    ele = L.data[i-1];
    for (int j = i - 1; j < L.length - 1; j++) {
        //将待删除元素后面的元素依次向前移
        L.data[j] = L.data[j+1];
    }
    L.length--;
    return true;
}
int main() {
    //初始化
    SqList L;//结构体
    bool ret;
    //手动添加顺序
    L.data[0] = 1;
    L.data[1] = 2;
    L.data[2] = 3;
    L.length = 3;//设置长度,很重要,刚刚没有写句话,就打印的defeat
    ret = ListInsert(L,2,60);
//    if (ret){
//        printf("insert sqList success\n");
//        PrintList(L);
//    } else{
//        printf("insert sqList defeat\n");
//   }
//    printf("----------------\n");
    //删除的元素放到del
    ElemType del;
    ret = ListDelete(L,1,del);
    if (ret){
        printf("delete sqList success\n");
        PrintList(L);
    } else{
        printf("delete sqList failed\n");
    }
}

三、顺序表的查询

//查询顺序表位置
int LocalElem(SqList L, int i){//不改变结构体,因此不用引用
    for (int j = 0; j < L.length; j++) {
        if (L.data[j] == i){
            return j+1;//因为j是数组的下标,所以加一
        }
    }
    return 0;
}
int main(){
int pos;//存储元素的位置
pos = LocalElem(L, 60);
if (pos){
    printf("chaXun sqList success\n");
    printf("%d\n",pos);
  } else{
    printf("chaXun sqList failed\n");
  }
}

四、三种传递区别

1.【值传递】如果形参为非引用的传值方式,则生成局部临时变量接收实参的值
void Swap (int left, int right) //值传递的方式无法实现交换,因为传参时对于参数left和right拷贝一临时副本,交换的是副本值,因为其是临时变量函数退出,变量销 {                                //毁,并不会影响外部left和right的值。
     int temp = left;
     left = right ;
     right = temp ;
}
 
2.【引用传递】如果形参为引用类型,则形参是实参的别名。
void Swap (int& left, int& right)//使用引用的话,不做临时拷贝,&的使用说明此处只是原参数的另一个名字而已,所以修改时直接在原参数的基础上修改变量值。
{
     int temp = left;
     right = left ;
     left = temp ;
}
 
3.【指针传递】
void Swap (int* pLeft, int* pRight)//传入的是地址,因为地址是唯一的,所以指针通过地址的访问进而可修改其内容。
{
     int temp = *pLeft;
     *pLeft = *pRight;
     *pRight = temp;