当前位置:   article > 正文

【数据结构】顺序表和单链表的定义与一些基本操作_顺序表和单链表的类型声明

顺序表和单链表的类型声明

一、单链表的定义

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以节点来表示的,每个结点的构成:date( 数据元素) + next(下个元素存储位置)

二、单链表的实现

  1. struct LNode{ //定义单链表结点类型
  2. ElemType data; //每个节点的数据域
  3. struct LNode *next; //指向下一个节点的指针
  4. };

不带头结点的单链表的创建及初始化:

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. typedef struct LNode { //定义单链表结点类型
  4. int data; //单链表数据域
  5. struct LNode* next; //单链表指针域
  6. }LNode, * LinkList;
  7. bool InitList1(LinkList L) { //初始化不带头结点的单链表
  8. L = NULL;
  9. return true;
  10. }
  11. bool InitList2(LinkList L) { //初始化带头结点的单链表
  12. L = (LinkList)malloc(sizeof(LNode));
  13. if (L == NULL)
  14. return false;
  15. L->next = NULL;
  16. return true;
  17. }
  18. int main(){
  19. LinkList L;
  20. InitList1(&L);
  21. InitList2(&L);
  22. return 0;
  23. }

 tips:虽然单链表的初始化对于头结点可有可无,但在实际解决问题时建议带头结点,写代码会更方便

三、单链表的基本操作

3.1、单链表的插入

①、带头结点的单链表

  1. ​​typedef struct LNode { //定义单链表结点类型
  2. int data; //单链表数据域
  3. struct LNode* next; //单链表指针域
  4. }LNode, * LinkList;
  5. bool ListInsert(LinkList L, int i, int e) {
  6. if (i < 1) //i值不合法的情况
  7. return false;
  8. LNode* p = L; //p从头结点指向扫描到的结点
  9. int j = 0; //当前p指向的第j个结点
  10. while (p != NULL && j < i - 1) //让p指向插入位序的前一个数据项
  11. {
  12. p = p->next;
  13. j++;
  14. }
  15. if (p == NULL) //i值超出链表容量的情况
  16. return false;
  17. LNode* s = (LNode*)malloc(sizeof(LNode));
  18. s->data = e;
  19. s->next = p->next;
  20. p->next = s;
  21. return true;
  22. }

在ListInsert函数中,我们首先对i的值进行判断,当i小于1,即i的值不合法,则返回false,再声明LNode型的指针p指向L的头结点,再声明j=0,通过循环来表示p当前指向第j个结点,当循环结束时,p指向i的前一个结点,这时需要判断p是否超出链表容量,下面用malloc函数开辟链表中一个结点大小的空间,再让s的数据域为e,s的next指针指向p的next指针,p的next指针指向s,这样就成功插入了一个结点

 ②、不带头结点的单链表

前面我们提到过,我们创建单链表时尽量选择添加头结点,如果没有头结点,那么在插入结点的时候就需要考虑i=1的特殊情况,因为没有头结点作为引入

  1. ​​typedef struct LNode { //定义单链表结点类型
  2. int data; //单链表数据域
  3. struct LNode* next; //单链表指针域
  4. }LNode, * LinkList;
  5. bool ListInsert(LinkList L, int i, int e) {
  6. if (i < 1) //i值不合法的情况
  7. return false;
  8. if (i == 1)
  9. {
  10. LNode* s = (LNode*)malloc(sizeof(LNode));
  11. s->data = e;
  12. s->next = L;
  13. L = s;
  14. return true;
  15. }
  16. LNode* p = L; //p从头结点指向扫描到的结点
  17. int j = 1; //当前p指向的第j个结点
  18. while (p != NULL && j < i - 1) //让p指向插入位序的前一个数据项
  19. {
  20. p = p->next;
  21. j++;
  22. }
  23. if (p == NULL) //i值超出链表容量的情况
  24. return false;
  25. LNode* s = (LNode*)malloc(sizeof(LNode));
  26. s->data = e;
  27. s->next = p->next;
  28. p->next = s;
  29. return true;
  30. }

3.2、单链表的删除

①、带头结点的链表

  1. ​​typedef struct LNode { //定义单链表结点类型
  2. int data; //单链表数据域
  3. struct LNode* next; //单链表指针域
  4. }LNode, * LinkList;
  5. bool ListDelete(LinkList L, int i, int e) {
  6. if (i < 1) //i值不合法的情况
  7. return false;
  8. }
  9. LNode* p = L; //p从头结点指向扫描到的结点
  10. int j = 0; //当前p指向的第j个结点
  11. while (p != NULL && j < i - 1) //让p指向插入位序的前一个数据项
  12. {
  13. p = p->next;
  14. j++;
  15. }
  16. if (p == NULL) //i值超出链表容量的情况
  17. return false;
  18. LNode* q = p->next; //q指向被删除的结点
  19. e=q->data; //e存储被删除结点的数据
  20. p->next = q->next; //被删除的结点的前一个结点指向被删除的结点的下一个结点
  21. free(q); //释放节点的空间
  22. return true;
  23. }

②、不带头结点的链表

  1. ​​typedef struct LNode { //定义单链表结点类型
  2. int data; //单链表数据域
  3. struct LNode* next; //单链表指针域
  4. }LNode, * LinkList;
  5. bool ListDelete(LinkList L, int i, int e) {
  6. if (i < 1) //i值不合法的情况
  7. return false;
  8. if (i == 1) {
  9. LNode* q = L;
  10. e = L->data;
  11. L = L->next;
  12. free(q);
  13. }
  14. LNode* p = L; //p从头结点指向扫描到的结点
  15. int j = 1; //当前p指向的第j个结点
  16. while (p != NULL && j < i - 1) //让p指向插入位序的前一个数据项
  17. {
  18. p = p->next;
  19. j++;
  20. }
  21. if (p == NULL) //i值超出链表容量的情况
  22. return false;
  23. LNode* q = p->next; //q指向被删除的结点
  24. e=q->data; //e存储被删除结点的数据
  25. p->next = q->next; //被删除的结点的前一个结点指向被删除的结点的下一个结点
  26. free(q); //释放节点的空间
  27. return true;
  28. }

3.3、单链表的查找

①、按位查找

  1. //按位查找,返回第i个​​元素(带头结点)
  2. typedef struct LNode { //定义单链表结点类型
  3. int data; //单链表数据域
  4. struct LNode* next; //单链表指针域
  5. }LNode, * LinkList;
  6. LNode* GetElem (LinkList L, int i) {
  7. if (i < 0) //i值不合法的情况
  8. return NULL;
  9. LNode* p = L; //p从头结点指向扫描到的结点
  10. int j = 0; //当前p指向的第j个结点
  11. while (p != NULL && j < i) //循环找到第i个结点
  12. {
  13. p = p->next;
  14. j++;
  15. }
  16. if (p == NULL) //i值超出链表容量的情况
  17. return NULL;
  18. return p;
  19. }

②、按值查找

  1. //按值查找,返回第i个​​元素(带头结点)
  2. typedef struct LNode { //定义单链表结点类型
  3. int data; //单链表数据域
  4. struct LNode* next; //单链表指针域
  5. }LNode, * LinkList;
  6. LNode* LocateElem (LinkList L, int e) {
  7. LNode* p = L; //p从头结点指向扫描到的结点
  8. int j = 0; //当前p指向的第j个结点
  9. while (p != NULL && p->data!=e) //让p指向插入位序的前一个数据项
  10. {
  11. p = p->next;
  12. }
  13. if (p == NULL) //超出链表容量的情况
  14. return NULL;
  15. return p;
  16. }

3.4、单链表的建立

①、头插法

  1. typedef struct LNode { //定义单链表结点类型
  2. int data; //单链表数据域
  3. struct LNode* next; //单链表指针域
  4. }LNode, * LinkList;
  5. LNode* LinkList_TailInsert (LinkList L) { //头插法建立单链表
  6. int x; //设置数据域的初始值
  7. L = (LNode*)malloc(sizeof(LNode)); //建立头结点
  8. L->next = NULL;
  9. LNode* s=L;
  10. scanf("%d", &x);
  11. while (x != 666) //循环结束的条件
  12. {
  13. s = (LNode*)malloc(sizeof(LNode));
  14. s->data = x;
  15. s->next = L->next;
  16. L->next = s;
  17. scanf("%d", &x);
  18. }
  19. return L;
  20. }

②、尾插法

  1. typedef struct LNode { //定义单链表结点类型
  2. int data; //单链表数据域
  3. struct LNode* next; //单链表指针域
  4. }LNode, * LinkList;
  5. LNode* LinkList_TailInsert (LinkList L) { //尾插法建立单链表
  6. int x; //设置数据域的初始值
  7. L = (LNode*)malloc(sizeof(LNode)); //建立头结点
  8. LNode* s, * r=L;
  9. scanf("%d", &x);
  10. while (x != 666) //循环结束的条件
  11. {
  12. s = (LNode*)malloc(sizeof(LNode));
  13. r->next = s;
  14. s->data = x;
  15. r = s;
  16. scanf("%d", &x);
  17. }
  18. r->next = NULL;
  19. return L;
  20. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/422419
推荐阅读
相关标签
  

闽ICP备14008679号