数据结构_c语言单链表的创建_1

本文详细介绍了在C语言中如何定义链表结构体、初始化链表以及在链表头部插入新节点的方法,同时讨论了C语言中指针和引用的区别,以及如何处理链表头指针的传递和内存管理。
摘要由CSDN通过智能技术生成
  • 首先,在代码中定义一个结构体 LNode 用来表示链表节点,其中包含整数类型的数据成员 data 和指向下一个节点的指针 next
  • 定义一个别名 LinkList 表示指向 LNode 结构体的指针,即链表指针。
  • 函数 List_Init 用于初始化链表,将传入的链表头指针 pHead 置为 NULL,表示空链表。该函数返回一个布尔值表示是否初始化成功。
  • 函数 List_Empty 用于判断链表是否为空,通过检查链表头指针 pHead 是否为 NULL 来确定链表是否为空。如果链表为空,函数返回 true,否则返回 false。
#include <stdio.h>
#include<stdlib.h>
typedef struct LNode {
    int data;
    struct LNode * next;
} LNode, *LinkList;
// 初始化链表
bool List_Init (LinkList &pHead) {
    pHead = NULL;
    return true;
}
// 判断单链表是否为空
bool List_Empty (LinkList pHead) {
    return pHead == NULL;
}

需要注意到以下几点:

  • 在 C 语言中,没有内置的 bool 类型,可以考虑使用 int 类型来替代,0 表示 false,非零值表示 true。
  • 参数传递时应该使用指针引用(LinkList &pHead),以便在函数内部修改头指针的值。
  • 如果需要在函数内部分配内存来表示新的链表节点,可以使用 malloc 函数来分配内存

另外,在 C 语言中,LinkList &pHeadLinkList pHead 有以下区别:

  1. LinkList &pHead

    • 这种写法使用了引用(reference)的概念,但实际上 C 语言并不支持引用。
    • 在 C++ 中,通过 & 符号可以创建引用类型,用于传递参数时不复制变量而直接操作原始对象。但在 C 中,这样的写法是无效的。在 C 中,通常会使用指针来模拟引用的功能。使用LinkList* pHead
  2. LinkList pHead

    • 这种写法表示将 pHead 声明为一个指向 LinkList 结构体的指针变量。如果使用 LNode表示时可以写作LNode* newhead
    • 当传递该变量作为参数时,会传递指针的副本,即函数内部对指针值的修改不会影响外部的指针变量。

在 C 语言中,要在函数中修改指针所指向的内容(比如链表头指针),需要传递指针的指针(LinkList* pHead) 或者返回新的头指针,以便在函数外部更新指针的值。

修改指针指向分内容,传递指针的指针代码如下

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

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

// 初始化链表
void List_Init(LinkList *pHead) {
    *pHead = NULL;
}

// 在链表头部插入新节点
// 不带虚拟头结点的头插法
void List_InsertFront(LinkList *pHead, int val) {
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    if (newNode == NULL) {
        printf("Error: Memory allocation failed.\n");
        return;
    }
    newNode->data = val;
    newNode->next = *pHead;
    *pHead = newNode;
}

// 打印链表
void List_Print(LinkList pHead) {
    LNode* current = pHead;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

int main() {
    LinkList head;
    List_Init(&head);

    // 插入一些数据
    List_InsertFront(&head, 3);
    List_InsertFront(&head, 5);
    List_InsertFront(&head, 7);

    List_Print(head);

    return 0;
}

上述代码示例中:

  • List_Init 函数接受一个指向链表头指针的指针,并将头指针置为 NULL。
  • List_InsertFront 函数接受一个指向链表头指针的指针以及要插入的值,在链表头部插入新节点。
  • 在 main 函数中,通过向函数传递头指针的指针来更新链表。

 

在不传递指针的指针的情况下,可以使用返回值来实现链表操作。

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

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

// 初始化链表并返回头节点
LNode* List_Init() {
    return NULL;
}

// 在链表头部插入新节点,并返回新的头节点
LNode* List_InsertFront(LNode *pHead, int val) {
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    if (newNode == NULL) {
        printf("Error: Memory allocation failed.\n");
        return pHead;
    }
    newNode->data = val;
    newNode->next = pHead;
    
    return newNode; // 返回新的头节点
}

// 打印链表
void List_Print(LNode *pHead) {
    LNode* current = pHead;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

int main() {
    LNode* head = List_Init();

    // 插入一些数据,并更新头节点
    head = List_InsertFront(head, 3);
    head = List_InsertFront(head, 5);
    head = List_InsertFront(head, 7);

    List_Print(head);

    return 0;
}

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

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

// 初始化链表并返回头节点
LinkList List_Init() {
    return NULL;
}

// 在链表头部插入新节点,并返回新的头节点
LinkList List_InsertFront(LinkList pHead, int val) {
    LinkList newNode = (LinkList)malloc(sizeof(LNode));
    if (newNode == NULL) {
        printf("Error: Memory allocation failed.\n");
        return pHead;
    }
    newNode->data = val;
    newNode->next = pHead;

    return newNode; // 返回新的头节点
}

// 打印链表
void List_Print(LinkList pHead) {
    LinkList current = pHead;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

int main() {
    LinkList head = List_Init();

    // 插入一些数据,并更新头节点
    head = List_InsertFront(head, 3);
    head = List_InsertFront(head, 5);
    head = List_InsertFront(head, 7);

    List_Print(head);

    return 0;
}

在上面的示例中,LNode 结构体表示链表节点。List_Init 函数用于初始化链表并返回头节点。List_InsertFront 函数用于在链表头部插入新节点,并返回新的头节点。List_Print 函数负责打印链表中每个节点的数据。通过这种方式,而不需要传递指针的指针。

上述两种例子是链表不具有虚拟头结点的情况,当链表带有虚拟头结点时,只需虚将拟头节点的指针作为参数传递,可以方便地对链表进行插入、删除和遍历等操作,而不再需要传递指针的指针。

链表的头指针直接指向链表的第一个节点,而不是指向一个额外的虚拟头节点。如果需要添加一个虚拟头节点来简化链表的操作或者避免一些特殊情况的处理,可以像下面这样修改程序:

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

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

// 初始化链表(带虚拟头节点)
void List_Init(LinkList *pHead) {
    *pHead = (LNode*)malloc(sizeof(LNode));
    (*pHead)->next = NULL; // 虚拟头节点的 next 指针为 NULL
}

// 在链表头部插入新节点
void List_InsertFront(LinkList pHead, int val) {
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    if (newNode == NULL) {
        printf("Error: Memory allocation failed.\n");
        return;
    }
    newNode->data = val;
    newNode->next = pHead->next;
    pHead->next = newNode;
}

// 打印链表
void List_Print(LinkList pHead) {
    LNode* current = pHead->next; // 跳过虚拟头节点
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

int main() {
    LinkList head;
    List_Init(&head);

    // 插入一些数据
    List_InsertFront(head, 3);
    List_InsertFront(head, 5);
    List_InsertFront(head, 7);

    List_Print(head);

    return 0;
}

当使用带有虚拟头节点的链表结构时,修改链表时不再需要传递指针的指针,因为在这种情况下,只需传递指向虚拟头节点的指针即可完成对链表的修改操作。在代码示例中,通过将指向虚拟头节点的指针作为参数传递给操作函数,可以直接操作链表的头部和其他节点,而无需传递指针的指针,也无需函数返回。

所以,在上述的修改后的程序中,通过将虚拟头节点的指针作为参数传递,可以方便地对链表进行插入、删除和遍历等操作,而不再需要传递指针的指针。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
定义单链表类,创建带头结点的单链表(节点类型为整型数据),要求包含以下成员函数: 1. 头插法创建单链表(利用构造函数实现) 2. 尾插法创建单链表(重载构造函数实现) 3. 链表的遍历 4. 按值删除一个节点 5. 按位置删除一个节点 6. 判断该链表是否递增有序 7. 链表的析构 具体实现如下: ```c++ #include <iostream> using namespace std; class Node { public: int data; Node* next; Node(int d = , Node* n = NULL) : data(d), next(n) {} }; class LinkedList { private: Node* head; public: LinkedList() { head = new Node(); } LinkedList(int arr[], int n) { head = new Node(); Node* p = head; for (int i = ; i < n; i++) { p->next = new Node(arr[i]); p = p->next; } } ~LinkedList() { Node* p = head; while (p) { Node* q = p; p = p->next; delete q; } } void insertHead(int x) { head->next = new Node(x, head->next); } void insertTail(int x) { Node* p = head; while (p->next) { p = p->next; } p->next = new Node(x); } void traverse() { Node* p = head->next; while (p) { cout << p->data << " "; p = p->next; } cout << endl; } void remove(int x) { Node* p = head; while (p->next && p->next->data != x) { p = p->next; } if (p->next) { Node* q = p->next; p->next = q->next; delete q; } } void removeAt(int i) { Node* p = head; int j = ; while (p->next && j < i) { p = p->next; j++; } if (p->next) { Node* q = p->next; p->next = q->next; delete q; } } bool isSorted() { Node* p = head->next; while (p && p->next) { if (p->data > p->next->data) { return false; } p = p->next; } return true; } }; int main() { int arr[] = { 1, 3, 5, 7, 9 }; LinkedList list1(arr, 5); list1.traverse(); // 1 3 5 7 9 LinkedList list2; list2.insertHead(9); list2.insertHead(7); list2.insertHead(5); list2.insertHead(3); list2.insertHead(1); list2.traverse(); // 1 3 5 7 9 list1.remove(5); list1.traverse(); // 1 3 7 9 list2.removeAt(2); list2.traverse(); // 1 3 7 9 cout << list1.isSorted() << endl; // 1 cout << list2.isSorted() << endl; // 1 return ; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值