线性表的链式表示和实现
来源:互联网 发布:免费淘宝账号和密码 编辑:程序博客网 时间:2024/05/18 13:05
线性表的链式表示和实现
首先来看一下线性表的顺序存储和链式存储的区别
顺序存储结构 —— 可随机存储,但插入或删除需要移动大量元素
链式存储结构 —— 便于插入或删除,但不可随机存取(其实可以通过操作使其随机存取)
线性链表
以存储的数据为整型(int)为例:
头结点的定义:
typedef struct HNode{ int length; char info[100]; struct LNode *next;}HNode;
注:大部分示例程序都直接用链表节点的类型来声明头节点,但我觉得应该为头节点定义单独的类型,也许这样会使操作变得略微麻烦,但也会带来很多好处。比如,当链表中的节点存储的数据为浮点型数组、字符型数组等类型的数据,而头结点是用整形来存储链表的长度的时候,分开定义更为合理。
链表节点的定义
typedef struct LNode{ int data; struct LNode *next;}LNode;
1、创建空链表
HNode* createNullList() /**创建空链表的函数的定义**/{ HNode* head; head=(HNode*)malloc(sizeof(HNode)); head->length = 0; if(head!=NULL){ head->next=NULL; printf("Has create null list success!\n"); } else printf("Out of space!\n"); return head;}
2、判断链表是否为空
int isNullList(HNode *head) /**判断是否链表是否为空的函数的定义(Y-1,N-0)**/{ return head->next==NULL;}
3、在链表的结尾添加新节点
int append_t(HNode *head, int n) /**在已存在的链表最后增加一个新结点的函数的定义(Y-1,N-0)**/{ LNode *p, *pnew; pnew=(LNode*)malloc(sizeof(LNode)); if(pnew==NULL){ printf("Out of space!\n"); return 0; } else{ pnew->data = n; p = head->next; /*p先指向头结点*/ if(p == NULL){ /*如果链表为空*/ head->next = pnew; pnew->next = NULL; } else{ while(p->next!=NULL) /*若p所指不是链尾*/ p=p->next; /*p后移一个结点*/ p->next=pnew; /*链尾的next存储新结点指针*/ pnew->next=NULL; /*使新结点成为链尾*/ } head->length++; } return 1;}
4、由结点中的元素查找结点的位序
int locate(HNode *head, int n, LNode **p) /**求某结点的指针,并返回其位序的函数的定义**/{ int i = 1; *p = NULL; *p = head->next; /*将头结点的next域赋值给p,使指向第一个结点*/ while(*p != NULL && (*p)->data != n){ i++; *p = (*p)->next; } if(*p == NULL) return 0; return i;}
5、由某结点的指针查找该节点的前驱结点的指针
LNode* locatePre(HNode *head, LNode *p) /**求p所指结点的前驱的函数的调用**/{ LNode *ptemp; ptemp = head->next; while(ptemp != NULL && ptemp->next != p) ptemp = ptemp->next; return ptemp;}
6、在某结点之后插入一个新结点
int append_t(HNode *head, int n) /**在已存在的链表最后增加一个新结点的函数的定义(Y-1,N-0)**/{ LNode *p, *pnew; pnew=(LNode*)malloc(sizeof(LNode)); if(pnew==NULL){ printf("Out of space!\n"); return 0; } else{ pnew->data = n; p = head->next; /*p先指向头结点*/ if(p == NULL){ /*如果链表为空*/ head->next = pnew; pnew->next = NULL; } else{ while(p->next!=NULL) /*若p所指不是链尾*/ p=p->next; /*p后移一个结点*/ p->next=pnew; /*链尾的next存储新结点指针*/ pnew->next=NULL; /*使新结点成为链尾*/ } head->length++; } return 1;}
7、删除结点
int deletendnd(HNode *head, int i, int *e) /**结点的删除函数的定义**/{ int j = 0; LNode *p, *q; p = head->next; if(i == 1){ j = 1; head->next = p->next; *e = p->data; free(p); return 1; } while(p->next != NULL && j < i-2){ p = p->next; j++; } if(!(p->next) || j > i-2) return 0; q = p->next; p->next = q->next; *e = q->data; free(q); head->length--; return 1;}
————————————————————————————-
完整代码:
除了以上基本操作外,本代码又添加了一些其他功能,并且改善了交互性。
本代码的头结点与其余结点采用的是不同的数据类型,因此增加了代码的复杂性
#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct LNode{ int data; struct LNode *next;}LNode;typedef struct HNode{ int length; char info[100]; struct LNode *next;}HNode;HNode* createNullList(); /**创建空链表的函数的声明**/int isNullList(HNode*); /**判断是否链表是否为空的函数的声明(Y-1,N-0)**/int append_h(HNode*, int); /**在已存在的链表最前增加一个新结点的函数的声明(Y-1,N-0)**/int append_t(HNode*, int); /**在已存在的链表最后增加一个新结点的函数的声明(Y-1,N-0)**/int locate(HNode*, int, LNode**); /**求某结点的指针并返回位序的函数的声明**/LNode* locatePre(HNode*, LNode*); /**求p所指结点的前驱的函数的声明**/LNode* locfda(HNode*, int); /**查找某位序的元素的数据的函数的声明**/int insert(HNode*, LNode*, int); /**在某结点之后插入一个新结点的函数的声明(Y-1,N-0)**/int deletendndnd(HNode*, int); /**结点的删除函数的声明**/int clear(HNode*); /**清空链表的函数的声明**/int batchadd(HNode*, int, int*); /**批量添加结点的函数的声明**/void reverse(HNode*); /**单链表的就地逆置函数的声明**/void print_L(HNode*);void print_hyphen(int);/******************************************************************************************************************/int main(void){ int data; /*结构体成员的数据*/ LNode *p; print_hyphen(5); printf("单链表的操作示例"); print_hyphen(5); printf("\n"); HNode *head; if((head=createNullList()) != NULL) /**创建空链表的函数的调用**/ { char info[50]; printf("请输入此链表的信息(50个字符以内):\n"); gets(info); strcpy(head->info, "The example for CSDN!\n"); strcpy(head->info + strlen("The example for CSDN!\n"), info); } else{ exit(1); } int end = 0; while(!end){ print_hyphen(15); printf("\n"); printf("请输入指令来执行操作\n"); print_hyphen(15); printf("\n"); printf("1、判断链表是否为空\n2、在链表最前增加一个新结点\n3、在链表最后增加一个新结点\n4、查找某位序的元素的数据\n"); printf("5、在某结点之后插入一个新结点\n6、删除某结点并返回其值\n7、查找某元素的位序\n8、清空链表\n"); printf("9、求某结点的前驱\n10、查看链表信息\n11、批量添加结点\n12、显示链表长度\n13、查看链表数据\n14、逆置链表\n15、退出演示\n"); print_hyphen(15); printf("\n"); printf("输入要使用的功能的序号: "); int opt; scanf("%d",&opt); print_hyphen(15); printf("\n"); switch(opt){ case 1: if(isNullList(head)) /**判断是否链表是否为空的函数的调用(Y-1,N-0)**/ printf("链表为空!\n"); else printf("链表不为空!\n"); break; case 2: printf("请输入要添加到链头的结点的数据: "); scanf("%d",&data); /**输入要添加的结点的数据*/ if(append_h(head, data)) /**在已存在的链表最后增加一个新结点的函数的调用(Y-1,N-0)**/ printf("添加成功!\n"); print_L(head); break; case 3: printf("请输入要添加到链尾的结点的数据: "); scanf("%d",&data); /**输入要添加的结点的数据*/ if(append_t(head, data)) /**在已存在的链表最后增加一个新结点的函数的调用(Y-1,N-0)**/ printf("添加成功!\n"); print_L(head); break; case 4:{ int site; printf("请输入位序号: "); scanf("%d",&site); p = locfda(head, site); if(p != NULL) printf("Has find the node!\n其数据为:%d\n", p->data); else printf("Don't find the node!\n"); break; } case 5: printf("请输入要求在其后插入新结点的结点的数据: "); scanf("%d",&data); locate(head, data, &p); int isinsert; printf("请输入新结点的数据: "); scanf("%d",&data); isinsert = insert(head, p, data); /**在某结点之后插入一个新结点的函数的调用(Y-1,N-0)**/ if(isinsert) printf("插入成功!\n"); else printf("未插入成功!\n"); print_L(head); break; case 6: printf("请输入要删除的结点的位序: "); int deletesi; scanf("%d",&deletesi); int deletend; if(deletendnd(head,deletesi,&deletend)) /**结点的删除函数的调用**/ printf("删除成功!\n其值为: %d\n", deletend); else printf("未删除成功!\n"); print_L(head); break; case 7: printf("请输入要寻找的结点的数据: "); int islocate; scanf("%d",&data); LNode *head_findnode; /*要寻找的结构体的指针*/ islocate = locate(head, data, &head_findnode); /**求某结点的指针的函数的调用**/ if(head_findnode != NULL) printf("Has find the node!\n其位序为:%d\n", islocate); else printf("Don't find the node!\n"); break; case 8: if(clear(head)) printf("清空成功!\n"); else printf("清空失败!\n"); break; case 9: printf("请输入要求前驱结点的结点的数据: "); scanf("%d",&data); LNode *prep; locate(head, data, &p); prep=locatePre(head,p); /**求p所指结点的前驱的函数的调用**/ if(prep==NULL) printf("Don't find the prenode!\n"); else printf("Has find the prenode!The data is %d\n",prep->data); break; case 10: printf("%s\n", head->info); break; case 11:{ int i; int batchnum; int batch[100]; printf("请输入要批量添加的结点的个数: "); scanf("%d",&batchnum); printf("请输入各结点的数据(用空格隔开): "); for(i = 0; i < batchnum; i++) scanf("%d", batch+i); if(batchadd(head, batchnum, batch)) printf("批量添加成功!\n"); print_L(head); break; } case 12: printf("当前链表长度为: %d\n", head->length); break; case 13: print_L(head); break; case 14: reverse(head); printf("链表逆置后为:\n"); print_L(head); break; case 15: print_hyphen(15); printf("\n"); printf("再见!\n"); print_hyphen(15); end = 1; break; default: print_hyphen(15);printf("\n"); printf("无此序号,请重新输入!\n"); print_hyphen(15);printf("\n"); } } return 0;}/*********************************************************************************************************************/HNode* createNullList() /**创建空链表的函数的定义**/{ HNode* head; head=(HNode*)malloc(sizeof(HNode)); head->length = 0; if(head!=NULL){ head->next=NULL; printf("Has create null list success!\n"); } else printf("Out of space!\n"); return head;}int isNullList(HNode *head) /**判断是否链表是否为空的函数的定义(Y-1,N-0)**/{ return head->next==NULL;}int append_h(HNode *head, int n) /**在已存在的链表最前增加一个新结点的函数的定义(Y-1,N-0)**/{ LNode *p, *pnew; pnew = (LNode*)malloc(sizeof(LNode)); if(pnew == NULL){ printf("Out of space!\n"); return 0; } pnew->data = n; pnew->next = head->next; head->next = pnew; head->length++; return 1;}int append_t(HNode *head, int n) /**在已存在的链表最后增加一个新结点的函数的定义(Y-1,N-0)**/{ LNode *p, *pnew; pnew=(LNode*)malloc(sizeof(LNode)); if(pnew==NULL){ printf("Out of space!\n"); return 0; } else{ pnew->data = n; p = head->next; /*p先指向头结点*/ if(p == NULL){ /*如果链表为空*/ head->next = pnew; pnew->next = NULL; } else{ while(p->next!=NULL) /*若p所指不是链尾*/ p=p->next; /*p后移一个结点*/ p->next=pnew; /*链尾的next存储新结点指针*/ pnew->next=NULL; /*使新结点成为链尾*/ } head->length++; } return 1;}int locate(HNode *head, int n, LNode **p) /**求某结点的指针,并返回其位序的函数的定义**/{ int i = 1; *p = NULL; *p = head->next; /*将头结点的next域赋值给p,使指向第一个结点*/ while(*p != NULL && (*p)->data != n){ i++; *p = (*p)->next; } if(*p == NULL) return 0; return i;}LNode* locatePre(HNode *head, LNode *p) /**求p所指结点的前驱的函数的调用**/{ LNode *ptemp; ptemp = head->next; while(ptemp != NULL && ptemp->next != p) ptemp = ptemp->next; return ptemp;}LNode* locfda(HNode *head, int n) /**查找某位序的元素的数据的函数的定义**/{ LNode *p = head->next; if(n < 1 || n > head->length) return NULL; while(n > 1 && p != NULL){ p = p->next; n--; } if(n > 1) return NULL; else return p;}int insert(HNode *head, LNode *p, int n) /**在某结点之后插入一个新结点的函数的定义(Y-1,N-0)**/{ LNode *pnew = (LNode*)malloc(sizeof(LNode)); if(pnew == NULL){ printf("Out of space!\n"); return 0; } pnew->data = n; pnew->next = p->next; p->next = pnew; head->length++; return 1;}int batchadd(HNode *head, int n, int *s) /**批量添加结点的函数的定义**/{ LNode *p, *pnew; int i; p = head->next; if(head->next == NULL){ pnew=(LNode*)malloc(sizeof(LNode)); if(pnew==NULL){ printf("Out of space!\n"); return 0; } pnew->data = s[0]; head->next = pnew; pnew->next = NULL; p = pnew; head->length++; i = 1; } else{ while(p->next != NULL) p = p->next; i = 0; } while(i < n){ pnew=(LNode*)malloc(sizeof(LNode)); if(pnew==NULL){ printf("Out of space!\n"); return 0; } pnew->data = s[i]; pnew->next = NULL; p->next = pnew; p = pnew; i++; head->length++; } return 1;}int deletendnd(HNode *head, int i, int *e) /**结点的删除函数的定义**/{ int j = 0; LNode *p, *q; p = head->next; if(i == 1){ j = 1; head->next = p->next; *e = p->data; free(p); return 1; } while(p->next != NULL && j < i-2){ p = p->next; j++; } if(!(p->next) || j > i-2) return 0; q = p->next; p->next = q->next; *e = q->data; free(q); head->length--; return 1;}int clear(HNode *head){ LNode *pa, *pb; pa = pb = head->next; while(pa != NULL && pb != NULL){ pb = pa->next; free(pa); pa = pb->next; free(pb); } return 1;}void reverse(HNode *head) /**单链表的就地逆置函数的定义**/{ LNode *p, *q; p = head->next; head->next = NULL; while(p != NULL){ q = p; p = p->next; q->next = head->next; head->next = q; }}void print_L(HNode *head){ printf("\n当前链表中的数据为:\n"); LNode *p = head->next; while(p != NULL){ printf("%d ", p->data); p = p->next; } printf("\n");}void print_hyphen(int n){ while(n--) printf("-");}
阅读全文
1 0
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现
- 线性表的链式表示和实现(链式)
- 线性表的链式表示和实现----线性(单)链表
- 线性表得链式表示和实现
- C内存简析
- 今天给大家讲一些JS的东西,同时也是我们日常看到的APP当中很常见的一个模块,拖拽标题
- Dimens适配与布局适配
- 短信验证
- recycleview+okhttp请求数据
- 线性表的链式表示和实现
- PullToRefresh添加轮播图为头布局
- 链表题_1
- Android 仿萤石客户端横向滚动时间轴
- centos 6.8的iptables不同于7
- 静态变量的初始化,静态变量在类内定义,在类外进行初始化。
- MyBatis 入门级配置文件
- 文本处理三剑客之sed
- ADS-B及雷达显示终端7.2