数据结构-语法规则
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); }
以上是关于数据结构-语法规则的主要内容,如果未能解决你的问题,请参考以下文章
GroovyGroovy 代码创建 ( 使用 Java 语法实现 Groovy 类和主函数并运行 | 按照 Groovy 语法改造上述 Java 语法规则代码 )