3.2指针与链表

3.2指针与链表

1. 指针

指针的概念
C/C++语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址。
如同一个房间的门口有一个房间号 123,那么这个 123 就是这个房间的地址,也可以说 123 指向该房间。
CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。一个变量的地址即为该变量的“指针”。

也就是说:指针变量是专门用来存放另一变量的地址(即指针)的,指针变量的值是地址(即指针)。
总结:指针是一个地址,而指针变量是存放地址(即指针)的变量

指针的声明

int *p;   // 声明一个 int 类型的指针 p
char *p;  // 声明一个 char 类型的指针 p
int *arr[10]; // 声明一个指针数组,该数组有10个元素,每个元素都是一个指向 int 类型对象的指针
int (*arr)[10]; // 声明一个数组指针,该指针指向一个 int 类型的一维数组
int **p;     // 声明一个指针 p ,该指针指向一个 int 类型的指针

指针变量的定义

int a=1, b=2, c=3;
int *p1 = &a;//定义指向整型数据的指针变量p1,并将变量a的地址赋给p1
int *p2 = &b;
int *p3 = &c;
cout<<a<<" "<<b<<" "<<c<<endl;      //1 2 3
cout<<p1<<" "<<p2<<" "<<p3<<endl;   //0x6ffdf4 0x6ffdf0 0x6ffdec
cout<<*p1<<" "<<*p2<<" "<<*p3<<endl;//1 2 3

NULL 指针
int *p = NULL;
NULL 指针是一个特殊的指针变量,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针。在多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是为操作系统保留的。但是,内存地址 0 有一个特别重要的意义,它表明该指针不指向一个可访问的内存位置。

char指针地址
C/C++语法中输出字符串指针,就是输出字符串,也就是说输出一个char*的指针一定是输出一个字符串,而不会输出指针,其它的类型都不会这样,如果把它转成 (void *) 就会输出地址。

char a='a';    char *p = &a;    cout<<(void *)p;

关于指针我们暂时不会过于深入,有兴趣可以阅读这篇 介绍指针的文章,会更深入一点

2. 链表

链表(单向链表、双向链表、单向循环链表、双向循环链表)
单向链表:由节点组成的单链表,每个节点有数据域和指针域,数据域用于存放数据,指针域指向下一个节点的地址,该链表的第一个节点被称作头节点,最后一个节点被称作尾节点,尾节点的指针域指向NULL。

#include<bits/stdc++.h>//静态链表的实现
using namespace std;
struct node{
    int data;//数据域
    struct node *next;//指针域
};
int main(){
    struct node a,b,c;
    a.data = 1, a.next = &b;
    b.data = 2, b.next = &c;
    c.data = 3, c.next = NULL;//结束标志
    struct node *head=&a, *pre=&a;
    while(pre!= NULL){
        cout<<pre->data<<" ";
        pre=pre->next;
    }
    return 0;
}
#include<bits/stdc++.h>//动态链表的实现
using namespace std;
typedef struct Node{
    int data;
    struct Node *next;
}Node, *List;

List add1(List list, int data){//头插法
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->next = list;
    return node;
}

List add2(Node* pre, int data){//尾插法
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->next = NULL;
    pre->next  = node;
    return node;
}
List add3(List list, int i, int data){//插入第 i个节点后
    Node* pre=list;
    while(--i) pre=pre->next; //将pre置为第 i个节点
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->next = pre->next;
    pre->next = node;
    return list;
}

void show(List list){//链表从头打印
    while(list){
        cout<<list->data<<" ";
        list = list->next;
    }cout<<endl;
}

int main(){
    List list=(Node*)malloc(sizeof(Node));
    list->data = 0;
    list->next = NULL;
    for(int i=1; i<=3; i++){
        list = add1(list, i);
    } show(list);

    Node *pre=list;
    while(pre->next!=NULL) pre=pre->next;
    for(int i=4; i<=6; i++){
        pre = add2(pre, i);
    } show(list);

    for(int i=7; i<=9; i++){
        list = add3(list,1, i);
    } show(list);
    return 0;
}

本次笔记中仅实现了单向链表的新增(头插法,尾插法,中间插入法)和输出,其余删除和修改并未实现,选手可以自行实现,对于链表的知识现阶段掌握到理论知识即可,几乎没有题目要求必须使用链表。

posted @ 2021-12-11 22:07  HelloHeBin  阅读(235)  评论(0编辑  收藏  举报