数据结构笔记

数据结构笔记

必须吐槽一下,我都学了c的数据结构了,这一下子来了c++,就很烦,我又得重新整理,又出来那么多不理解的东西。

乱七八糟的知识准备:

当初c语言没学好的,都是要还的。

首先了解一下&(当然不怪我,这是c++的内容),参数的引用,什么时候用,有什么含义那?,可以理解对参数的结果需要带回来。下面看一下代码理解:

#include "stdio.h"
void test(int x){
    x=1024;
    printf("test 内部函数的x的值为:%d\n",x);
}

int main(){
    int x =1;
    printf("调用test前x的值为%d\n",x);
    test(x);
    printf("调用test后x的值为%d\n",x);
}

请添加图片描述

这就属于对于参数的结果没有带回来。那么如果我们在test函数里面传入的不是是x而是**&x**那?结果你也许猜到了,没错结果的值带了回来。结果如下请添加图片描述

单链表

单链表的定义
typedef struct LNode{
    int data;
    struct LNode* next;
}LNode,*LinkList;

不说别的,就这个定义就够了解一壶的了。

首先给还原一下,上面的定义与下面的定义相同

typedef struct LNode{
    int data;
    struct LNode* next;
}
typedef struct LNode LNode;
typedef struct LNode* LinkList;

稍微明白一点了把,这是两个重命名,**一把这个结构体重命名为LNode ,另一个是把指向这个结构体的指针重命名为LinkList。**一脸懵逼,这是为什么?

而且LNode*其实是完全等价于LinkList,是不是感觉什么鬼,越来越乱,多此一举问什么要整两个那。不要急一点一点的表示。

先在此说一下,助于理解

  1. 强调这是一个单链表 ,–使用LinkList
  2. 强调这是一个节点 --使用LNode *
单链表的初始化

代码都是默认带头节点的

bool InitList(LinkList &L){
    L=new LNode;
    if(L==NULL) return false;
    L->next=NULL;
   return true;
}
//这是测试,不是属于初始化的内容但是检测初始化的内容
void test(){
    LinkList L;
    InitList(L);
}

算了都补一下把,不带头节点:

bool InitList(LinkList &L){
    if(L==NULL) //区别在这
   return true;
}
单链表的判空

为什么传入的参数是L而不是&L,很简单,我们只需要判断,也不需要带回

bool Empty(LinkList L){
    if(L->next==NULL) return false;
    else
        return true;
}

不带头节点:

bool Empty(LinkList L){
    if(L==NULL) return false;//区别在这
    else
        return true;
}
单链表的插入

请添加图片描述

bool InsertLink(LinkList &L,int index,int element){
    if(index<1)
        return false;
    LNode * p; //指正p指向当前扫描到的节点
    p=L;
    int j=0; //当前p指向的是第几个节点
    while (p!=NULL && j<index-1){
        p=p->next;
        j++;
    }
    if(p==NULL)
        return false;
    LNode* s=new LNode;//LNode* s =(LNode* s)malloc(sizeof(LNode));c语言可以这样写;
    s->data=element;
    s->next=p->next;
    p->next=s;
    return true;
}

不带头节点:请添加图片描述

bool InsertLink(LinkList &L,int index,int element){
    
    if(index<1)
        return false;
    //对于i==1进行特殊处理,插入第一个节点与其他操作不同
    if(i==1){
    LNode *s =new LNode;
    s->data =e;
    s->next =L;
    L=s;
    return true;
    }
    LNode * p; //指正p指向当前扫描到的节点
    p=L;
    int j=1; //去呗在这里
    while (p!=NULL && j<index-1){
        p=p->next;
        j++;
    }
    if(p==NULL)
        return false;
    LNode* s=new LNode;//LNode* s =(LNode* s)malloc(sizeof(LNode));c语言可以这样写;
    s->data=element;
    s->next=p->next;
    p->next=s;
    return true;
}

拓展一下,后插操作(很有作用):

单链表的删除
bool DeleteList(LinkList &L,int index,int &e){
    if(index<1) return false;
    LNode *p;//指正p当前扫描的节点
    int j=0;//当前p指向第几个节点
    p=L;
    while (p!=NULL && j<index-1){
        p=p->next;
        j++;
    }
    if(p==NULL) return false;
    if(p->next==NULL) return false;
    LNode *q=p->next;
    e=q->data;
    p->next=q->next;
    free(q);
}
单链表按位查找

LNode *GetElem(LinkList L ,int index){
    if(index<0) return NULL;//因为我们是带头节点,所以头节点可以看做第0个元素
    LNode *p;
    int j=0;
    p=L;
    while (p!=NULL &&j<index){
        p=p->next;
        j++;
    }
    return p;

第二种,可以参考理解一下

LNode *GetElem(LinkList L ,int index){
    int j=1;
    LNode *p = L->next;
    if(index==0) return L;
    if(index<1) return NULL;
    while (p!=NULL &&j<index){
       p=p->next;
       j++;
    }
    return p;
}

这里提一下,在我们学完按位查找之后,可以利用其封装性,应用到单链表的插入和删除中搜索到前节点的过程

请添加图片描述
请添加图片描述

单链表的按值查找
LNode* LocateElem(LinkList L, int element) {
    LNode* p = L->next;
    while (p != NULL && p->data != element) {
        p = p->next;
    }
    return p;
}
总结:

下面是整个链表的展示,包括实现功能

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

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

// 初始化
bool InitList(LinkList& L) {
    L = new LNode;
    if (L == NULL) return false;
    L->next = NULL;
    return true;
}

// 判断是否为空
bool Empty(LinkList L) {
    if (L->next == NULL) return true;
    else return false;
}

// 插入操作
bool InsertList(LinkList& L, int index, int element) {
    if (index < 1) return false;
    LNode* p; //指针p指向当前扫描到的节点
    p = L;
    int j = 0; //当前p指向的是第几个节点
    while (p != NULL && j < index - 1) {
        p = p->next;
        j++;
    }
    if (p == NULL) return false;
    LNode* s = new LNode;
    s->data = element;
    s->next = p->next;
    p->next = s;
    return true;
}

// 删除操作
bool DeleteList(LinkList& L, int index, int& e) {
    if (index < 1) return false;
    LNode* p; //指针p当前扫描的节点
    int j = 0; //当前p指向第几个节点
    p = L;
    while (p != NULL && j < index - 1) {
        p = p->next;
        j++;
    }
    if (p == NULL || p->next == NULL) return false;
    LNode* q = p->next;
    e = q->data;
    p->next = q->next;
    free(q);
    return true;
}

// 按位置查找
LNode* GetElem(LinkList L, int index) {
    if (index < 0) return NULL; //因为我们是带头节点,所以头节点可以看做第0个元素
    LNode* p;
    int j = 0;
    p = L->next; // 从第一个节点开始查找
    while (p != NULL && j < index) {
        p = p->next;
        j++;
    }
    return p;
}

// 按值查找,找到数据域==element的节点
LNode* LocateElem(LinkList L, int element) {
    LNode* p = L->next;
    while (p != NULL && p->data != element) {
        p = p->next;
    }
    return p;
}

// 求表长的长度
int Length(LinkList L) {
    int len = 0;
    LNode* p = L->next;
    while (p != NULL) {
        p = p->next;
        len++;
    }
    return len;
}

void test() {
    LinkList L;
    if (InitList(L)) {
        printf("链表初始化成功.\n");
    } else {
        printf("链表初始化失败。\n");
        return;
    }

    // 测试插入操作
    for (int i = 1; i <= 5; i++) {
        if (InsertList(L, i, i * 10)) {
            printf("在位置%d插入元素%d成功。\n", i, i * 10);
        } else {
            printf("位置%d的插入失败。\n", i);
        }
    }

    // 测试删除操作
    int deletedElement;
    if (DeleteList(L, 3, deletedElement)) {
        printf("删除的元素:%d\n", deletedElement);
    } else {
        printf("3号位置的删除失败。\n");
    }

    // 测试查找操作
    int findElement = 20;
    LNode* foundNode = LocateElem(L, findElement);
    if (foundNode) {
        printf("在位置%p找到元素%d。\n", foundNode, findElement);
    } else {
        printf("没有找到元素%d\n", findElement);
    }

    // 输出链表长度
    int len = Length(L);
    printf("链表长度:%d\n", len);
}

int main() {
    test();
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值