数据结构-语法规则

Posted abnk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构-语法规则相关的知识,希望对你有一定的参考价值。

1. 传值、传引用、传指针

#include<iostream>
using namespace std;
void func1(int a){
    a=2;
}
void func2(int &b){
    b=2;
}
void func3(int *c){
    *c=2;
}
int main()
{
    int a=1,b=1,c=1;
    func1(a);
    func2(b);
    func3(&c);
    cout<<a<<" "<<b<<" "<<c<<" "<<endl;
    return 0;
}

以上非常基础的东西。不必再强调。下面说说常见的这种形式:

char* p = "abc";                 // valid in C, invalid in C++
回顾:
以上如果是全局变量:p 存放在初始化数据段的rw段,"abc" 存放在代码段,p可以被重新赋值。static 修饰的函数内部变量如果未初始化,也在全局变量的bss段
如果是初始化列表{}里面的东西,有可能是放在数据只读RO段,也有可能放在代码段

参考链接

字符常量:2,‘c‘,true。注意不是字符串常量;

临时对象:std::string("shina");    包括函数返回值、表达式结果;

将亡值:将要被移动的对象(C++11新增的)。

拓展:forward

有了以上右值的概念,下面的就好理解了:

void func4(const int &d){
    d=2;
}

int main(){
    int d=1;
    func4(d);
    func4(5);    // 放在func3中,这种用法是编译失败的
}

以上引用方法仍然有缺陷,回顾相关知识点。

C++11扩展了用法,第四种传值方法,右值引用,依旧不能改变内容。

void func4(int &&d){
    d=2;
}

int main(){
    int d=1;
    func4(std::move(d));
}

意义何在?延长右值生命周期,少定义一个变量,节省内存,提高效率。

数据结构掌握以上三种就行了,第四种作为参考。

常用的引用方式是第三种而不是第二种,明白其好处。

2. struct 变量的不同格式与传引用的关系

头指针:

   经常见到数据结构中节点的定义的两种方式,如下所示,两种方式到底有什么区别呢?

typedef struct node{

    int data;

    struct node *next;

}LNode,*LList;

typedef struct node{

    int data;

    struct node *next;

}LNode;

   回顾C++中三种传值的方式,为了方便地修改头节点,可以修改头指针LList的值使其指向不同的节点作为单链表的头节点。

   下面程序Del_X函数形参使用LList类型的变量L时要加引用为&,这属于引用传值法,只不过传的是结构体指针类型的变量(struct node *型),typedef将struct node*型定义成了新的类型LList型(结构体指针型),对结构体指针类型的变量L进行引用,就成了LList &*L,引用传值,L就可以被修改为不同的值。

左边这种方式用在C++的描述的算法中,以便于引用传值。

1. C++中的引用

// 递归删除不带头节点的单链表中所有值为x的节点。如果头节点就是要删除的元素,那么就需要加引用。

// 头指针LList指向头节点LNode,头节点可以被定义为链表上的任意节点。更新头节点要对LList* 型的结构体指针变量L进行修改,所以传值的时候形参必须使用引用,即:LNode *&L或者LList &L,两种方式等价,L的值可以被改变(LNode *L或者LList L,两种方式等价,L的值不可以被改变)。

// 可以自行编写程序自行测试:创建一个3节点的单链表,头指针指向第1个节点,使其成为3节点链表。再使头指针指向第2个节点,释放第1个节点,使其成为两个节点链表。

// C语言中不存在引用的问题,传过去的地址变量都能被改变。

#include <iostream>
using namespace std;

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LList;

void Del_X(LList &L,int x){    // 加引用&。注意这里是LList,相当于Node * &L
    LNode *p;
    if(L==NULL) return;
    if(L->data==x){
        p=L;
        L=L->next;                // 改变头节点,更新头节点L
        delete p;
        Del_X(L,x);
    }
    else
        Del_X(L->next,x);
}

void disL(LList L){
    LNode *p=L;
    while(p!=NULL){
        cout<<p->data<<endl;
        p=p->next;
    }
    cout<<"**"<<endl;
}

int main(){
    LList L=new LNode;      L->data=0;     // 这只是个地址变量,存放头节点地址,可以被改变
    LNode * L1=new LNode;   L->next=L1;    L1->data=1;
    LNode * L2=new LNode;   L1->next=L2;   L2->data=2;
    LNode * L3=new LNode;   L2->next=L3;   L3->data=3;
    LNode * L4=new LNode;   L3->next=L4;   L4->next=NULL;   L4->data=4;
    disL(L);
    Del_X(L,0);
    disL(L);
}

2. C语言没有引用的概念,可以直接修改头节点的地址,所以可以省略掉结构体后面的*LNode。

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

// C语言则不会出现这个问题

typedef struct Node{
    int data;
    struct Node *next;
}Node;

void Del_X(Node * L,int x){
    Node *p;
    if(L==NULL) return;
    if(L->data==x){
        p=L;
        L=L->next;
        free(p);
        Del_X(L,x);
    }
    else
        Del_X(L->next,x);
}

void disL(Node *L){
    Node *p=L;
    while(p!=NULL){
        printf("%d
",p->data);
        p=p->next;
    }
    printf("**");
}

int main(){
    Node * L= (Node *)malloc(sizeof(Node));   L->data=0;
    Node * L1=(Node *)malloc(sizeof(Node));   L->next=L1;    L1->data=1;
    Node * L2=(Node *)malloc(sizeof(Node));   L1->next=L2;   L2->data=2;
    Node * L3=(Node *)malloc(sizeof(Node));   L2->next=L3;   L3->data=3;
    Node * L4=(Node *)malloc(sizeof(Node));   L3->next=L4;   L4->data=4;
    L4->next=NULL;
    disL(L);
    Del_X(L,2);
    disL(L);
}

 

以上是关于数据结构-语法规则的主要内容,如果未能解决你的问题,请参考以下文章

java基础之语法和开发规则

GroovyGroovy 代码创建 ( 使用 Java 语法实现 Groovy 类和主函数并运行 | 按照 Groovy 语法改造上述 Java 语法规则代码 )

JSP语法

为啥此代码片段返回意外结果?

JSP 语法

JSP 基础语法