数据结构实战——线性表的单链表实现
2014-10-31 23:11
393 查看
转载请声明出处:/article/7920491.html
相关概念
前面我们说了线性结构的顺序存储表示(数组表示法),接下来看一下线性结构的链式存储表示(指针表示法)。我们可以发现,顺序表的插入、删除操作平均都要移动约一半的元素。当顺序表的长度非常大时,这个时间的消耗还是不容忽视的,这也是顺序存储的最大缺陷。因此顺序表常常用于那些无需频繁插入和删除元素的应用。而链式存储不再依靠内存的连续性来反映元素之间的逻辑关系,而是通过指针链接体现元素之间的逻辑关系。链表没有了顺序表所要求的存储必须连续的弱点,但也失去了顺序表随机存取任一个元素的优点。
链表的每个存储单元除了要存储数据元素本身之外,还需要存储一个指示直接后继元素的信息--指针。这两部分信息构成一个结点。结点中表示数据元素的域称为数据域,指向直接后继存储位置的域称为指针域。链表的这种存储结构使得链表无需像顺序表那样预先分配好所有的存储空间,而是在插入一个新元素时临时为新的元素分配结点。本篇讲述只包含一个指针域的单链表,后一篇博客讲述双链表。
下图给出了一个节点的示意图:
注意头结点和首元结点的区别,存储的元素,从首元结点开始存储,头结点只为了方便插入/删除操作。
单链表的定义
每个结点由一个结构体表示,其中有数据域 data 和指针域 next。
单链表的12种基本操作
其中需要注意插入新结点时,有前插和后插两种方式,这里我都实现了。代码如下:
单链表的主程序实现
基于上述实现的单链表的12种功能,如下进行调用调试。
程序运行结果,如下图所示:
是不是很简单啊?后一篇博客我们在来玩一玩双向链表~
转载请声明出处:/article/7920491.html
源码下载
相关概念
前面我们说了线性结构的顺序存储表示(数组表示法),接下来看一下线性结构的链式存储表示(指针表示法)。我们可以发现,顺序表的插入、删除操作平均都要移动约一半的元素。当顺序表的长度非常大时,这个时间的消耗还是不容忽视的,这也是顺序存储的最大缺陷。因此顺序表常常用于那些无需频繁插入和删除元素的应用。而链式存储不再依靠内存的连续性来反映元素之间的逻辑关系,而是通过指针链接体现元素之间的逻辑关系。链表没有了顺序表所要求的存储必须连续的弱点,但也失去了顺序表随机存取任一个元素的优点。
链表的每个存储单元除了要存储数据元素本身之外,还需要存储一个指示直接后继元素的信息--指针。这两部分信息构成一个结点。结点中表示数据元素的域称为数据域,指向直接后继存储位置的域称为指针域。链表的这种存储结构使得链表无需像顺序表那样预先分配好所有的存储空间,而是在插入一个新元素时临时为新的元素分配结点。本篇讲述只包含一个指针域的单链表,后一篇博客讲述双链表。
下图给出了一个节点的示意图:
注意头结点和首元结点的区别,存储的元素,从首元结点开始存储,头结点只为了方便插入/删除操作。
单链表的定义
每个结点由一个结构体表示,其中有数据域 data 和指针域 next。
/* 线性表的单链表实现 -- 定义 */ #ifndef LNODEOPERATION_H_INCLUDED #define LNODEOPERATION_H_INCLUDED typedef struct LNODE{ int data; //数据域,表示当前结点存储的数据元素 LNODE *next; //指针域,存储直接后继元素的地址 }LNODE; bool InitList_L(LNODE *&pHead); void DestroyList_L(LNODE *&pHead); void ClearList_L(LNODE *pHead); bool ListEmpty_L(LNODE *pHead); int ListLength_L(LNODE *pHead); int GetElem_L(LNODE *pHead, int i, int &e); int LocateElem_L(LNODE *pHead, int e); bool PriorElem_L(LNODE *pHead, int cur_e, int &pre_e); bool NextElem_L(LNODE *pHead, int cur_e, int &next_e); bool ListInsertFront_L(LNODE *pHead, int i, int x);//前插 bool ListInsertBack_L(LNODE *pHead, int i, int x);//后插 bool ListDelete_L(LNODE *pHead, int i, int &x); void ListTravers(LNODE *pHead); #endif // LNODEOPERATION_H_INCLUDED
单链表的12种基本操作
其中需要注意插入新结点时,有前插和后插两种方式,这里我都实现了。代码如下:
/* 线性表的单链表实现 -- 12种基本操作 */ #include<stdio.h> #include<stdlib.h> #include<malloc.h> #include "LnodeOperation.h" bool InitList_L(LNODE *&pHead){ //pHead指向头结点,Head头结点的next指针初始置为NULL pHead = (LNODE *)malloc(sizeof(LNODE)*1); if (pHead == NULL) return false; pHead->next = NULL; return true; } void DestroyList_L(LNODE *&pHead){ //删除单链表所有结点(包括头结点Head),pHead置为空 ClearList_L(pHead); free(pHead); pHead = NULL; } void ClearList_L(LNODE *pHead){ //Head头结点的next指针置为空 LNODE *pa,*pb; pa = pHead->next; //pa指向Head头结点 while (pa != NULL){ pb = pa->next; free(pa); pa = pb; } pHead->next = NULL; } bool ListEmpty_L(LNODE *pHead){//判断链表是否为空 if (pHead->next == NULL) return true; return false; } int ListLength_L(LNODE *pHead){//返回链表长度 int count = 0; LNODE *pa = pHead->next; while(pa != NULL){ count++; pa = pa->next; } return count; } int GetElem_L(LNODE *pHead, int i, int &e){//返回链表位序为i的元素 //合法性校验 if (i < 1) return -1; if (i > ListLength_L(pHead)) return -2; int count = 0; LNODE *pa = pHead->next; while(pa != NULL){ count++; if (count == i){ e = pa->data; return 0; } pa = pa->next; } return -3; } int LocateElem_L(LNODE *pHead, int e){//返回单链表中首个e元素的位序 LNODE *pa; pa = pHead->next; int count = 0; while(pa != NULL){ count++; if (pa->data == e) return count; pa = pa->next; } return 0; } bool PriorElem_L(LNODE *pHead, int cur_e, int &pre_e){//返回cur_e直接前驱 LNODE *pa; pa = pHead->next; if (pa == NULL) return false; else if (pa->data == cur_e) return false; else{ while(pa->next != NULL){ if (pa->next->data == cur_e){ pre_e = pa->data; return true; } pa = pa->next; } return false; } } bool NextElem_L(LNODE *pHead, int cur_e, int &next_e){//返回cur_e直接后继 LNODE *pa; int lastElem; pa = pHead->next; if (pa == NULL) return false; while(pa->next != NULL){ if (pa->data == cur_e){ next_e = pa->next->data; return true; } pa = pa->next; } return false; } bool ListInsertFront_L(LNODE *pHead, int i, int x){//在链表第i个结点前面插入x LNODE *pn, *pa, *pb; int count = 0; pn = (LNODE*)malloc(sizeof(LNODE)*1); if (pn == NULL) return false; pa = pHead->next;//pa指向当前第i个结点 pb = pHead;//pb指向当前结点的前驱结点,即第i-1个结点 if (pa == NULL){//如果原链表为空的 pn->data = x; pn->next = pa; pb->next = pn; return true; } while(pa != NULL){//否则 count++; if (count == i) break; pb = pa; pa = pa->next; } if (count != i) return false;//说明需求位序i不合法 pn->data = x; pn->next = pa;//pn的后继置为pa pb->next = pn;//pa的原前驱的后继置为pn return true; } bool ListInsertBack_L(LNODE *pHead, int i, int x){//在链表第i个结点后面插入x LNODE *pn, *pa; int count = 0; pn = (LNODE*)malloc(sizeof(LNODE)*1); if (pn == NULL) return false; pa = pHead->next;//pa指向当前第i个结点 if (pa == NULL){//如果链表为空 pn->data = x; pn->next = pa; pHead->next = pn; return true; } while(pa != NULL){//否则 count++; if (count == i) break; pa = pa->next; } if (count != i) return false; pn->data = x; pn->next = pa->next;//pn的后继置为pa的原后继 pa->next = pn;//pa的后继置为pn return true; } bool ListDelete_L(LNODE *pHead, int i, int &x){//删除链表第i个结点 LNODE *pa, *pb; int count = 0; pa = pHead->next; pb = pHead; while(pa != NULL){ count++; if (count == i) break; pb = pa; pa = pa->next; } if (count != i) return false;//位序i不合法 x = pa->data;//保存被删除的结点数据 pb->next = pa->next;//pa的原前驱直接指向pa的后继 free(pa);//释放被删除位置的结点空间 return true; } void ListTravers(LNODE *pHead){ LNODE *pa = pHead->next; while(pa != NULL){ printf("%d ",pa->data); pa = pa->next; } printf("\n"); }
单链表的主程序实现
基于上述实现的单链表的12种功能,如下进行调用调试。
/** @author:lichunchun @date:2015/3/25 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "LnodeOperation.h" int main(){ LNODE *pHead; char str[30],*th; int temp,select,item,length=0; printf("(1)初始化单链表h\n"); InitList_L(pHead); printf("(2)请给出将要插入链表中的元素:"); gets(str); printf("(3)依次用后插法插入上述元素\n"); th = strtok(str," "); while(th != NULL){ temp = atoi(th); if (!ListInsertBack_L(pHead,length++,temp)) return 0; th = strtok(NULL," "); } printf("(4)输出单链表h:"); ListTravers(pHead); printf("(5)单链表h长度=%d\n",ListLength_L(pHead)); printf("(6)单链表h为%s\n",(ListEmpty_L(pHead))?"空":"非空"); printf("(7)您想获取这个链表的第几个元素?"); scanf("%d",&select); if (!GetElem_L(pHead,select,item)) printf("(8)单链表h的第%d个元素=%d\n",select,item); else printf("(8)非法位序!\n"); printf("(9)元素2的位序=%d\n",LocateElem_L(pHead,2)); printf("(10)在第3个元素后面插入元素10\n"); ListInsertBack_L(pHead,3,10); printf("(11)在第1个元素前面插入元素11\n"); ListInsertFront_L(pHead,1,11); printf("(12)输出单链表h:"); ListTravers(pHead); printf("(13)删除单链表h的第2个元素\n"); ListDelete_L(pHead,2,item); printf("(14)输出单链表h:"); ListTravers(pHead); printf("(15)释放单链表h\n"); DestroyList_L(pHead); return 0; }
程序运行结果,如下图所示:
是不是很简单啊?后一篇博客我们在来玩一玩双向链表~
转载请声明出处:/article/7920491.html
源码下载
相关文章推荐
- 数据结构学习----线性表的链式表示之升序排序的单链表(Java实现)
- 数据结构复习——线性表的链式存储实现(单向链表)
- 数据结构(2)--线性表单链表的主要操作的实现
- 数据结构(7)线性表之链表C++实现差集
- c/c++ 数据结构-线性表(单链表基本操作的实现)
- 数据结构(三):线性表的链式存储结构 - 双链表的实现
- 【数据结构】线性表的单链表存储结构表示和实现
- 2.数据结构--线性表之链表实现
- 数据结构专题——线性表之单链表及其Java实现
- 数据结构专题——线性表之双链表及其Java实现
- (一)数据结构之线性表的简单实现:链表
- PHP数据结构之三 线性表中的单链表的PHP实现
- 数据结构(6)线性表之链表C++实现交集
- 数据结构2:线性表的链表表示和实现
- 数据结构:线性表的链式存储(单向链表)--Java实现
- Java数据结构之简单链表的定义与实现方法示例
- C#实现双链表(线性表)
- C#实现单链表(线性表)
- 数据结构的基础---线性群集存储模式(数组、链表和hash)
- 数据结构C++模板实现之----------------单向链表