数据结构之链表操作
2016-02-28 13:42
531 查看
线性表链式存储结构定义:
为了表示每个数据元素ai与其后继数据元素aI+1之间的逻辑关系,对数据元素ai来说,除了存储其本身信息外,还需存储一个指示其直接后继的信息。我们把存储数据元素的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分信息组成数据元素ai的存储影像,称为结点(Node)。n个结点链结成一个链表,即为线性表(a1,a2,……,an)的链式存储结构,因为此链表的每个节点中只包含一个指针域,所以叫做单链表。
我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的额存取就必须从头指针开始进行了。
头指针和头节点的异同:
头指针:
头指针是指链表指向第一个结点的指针,若链表有头节点,则是指向头节点的指针。
头指针具有标识作用,作用常用头指针冠以链表的名字。
无论链表是否为空,头指针均不为空。头指针是链表的必要元素。
头节点:
头节点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义。
有了头节点,对在第一元素结点前插入结点和删除第一结点,其操作和其他结点的操作就统一了。
头节点不是链表的必须元素。
获取单链表某个元素:
算法思路:(1)声明一个结点p指向链表的第一个结点,初始化j从1开始。
(2)当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个节点,j累加1;
(3)若到链表末尾p为空,则说明第i个元素不存在。
(4)否则查找成功,返回结点p的数据。
单链表的插入与删除:
单链表第i个数据插入节点的算法思路:(1)声明一个结点p指向链表的第一个结点,初始化j从1开始。
(2)当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个节点,j累加1;
(3)若到链表末尾p为空,则说明第i个元素不存在;
(4)否则查找成功,在系统中生成一个空结点s;
(5)将数据元素e赋值给s->data;
(6)单链表的插入语句s->next=p->next;p->next=s;
(7)返回成功。
单链表第i个数据删除节点的算法思路:
(1)声明一个结点p指向链表的第一个结点,初始化j从1开始。
(2)当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个节点,j累加1;
(3)若到链表末尾p为空,则说明第i个元素不存在;
(4)否则查找成功,将欲删除的结点p->next赋值给q;
(5)单链表的删除标准语句p->next=q->next;
(6)将q结点中的数据赋值给e,作为返回;
(7)释放q结点;
(8)返回成功。
单链表的整表删除:
算法思路:(1)声明一结点p和q;
(2)将第一个结点赋值给p;
(3)循环:
将下一个结点赋值给q;
释放p;
将q赋值给p.
单链表的逆置操作:
算法思路:(1)声明一个结点p,将第一个结点赋值给p;
(2)将头节点的next域置NULL;
(3)循环:
声明一个结点q,指向p结点的next;
执行经典插入操作;
q赋值给p。
参考代码:
<span style="font-size:14px;">void Reverse(P</span>List plist) //逆置函数 { Node *p=plist->next; plist->next=NULL; while(p != NULL) { Node *q = p->next; p->next = plist->next; plist->next=p; p = q; } }
单链表参考程序代码:
先创建头文件:#pragma once //带头节点的单链表 typedef struct Node { int data; struct Node *next; }Node,*PList;//PList == Node* void InitList(PList plist); void Insert_head(PList plist,int val); //头插 void Insert_tail(PList plist,int val); //尾插 Node *Search(PList plist,int key); bool Delete(PList plist,int key); int GetLength(PList plist); bool IsEmpty(PList plist); void Clear(PList plist); void Destroy(PList plist); void Show(PList plist); void Reverse(PList plist); //链表逆置操作 bool Insert_pos(PList plist,int pos,int val); //按位置插入
再实现上述定义的函数:
#include<stdio.h> #include<malloc.h> #include<assert.h> #include"lianbiao.h" void InitList(PList plist) { assert(plist != NULL); plist->next = NULL; } static Node *BuyNode(int val) { Node *p=(Node *)malloc(sizeof(Node)); assert(p != NULL); p->data = val; p->next = NULL; return p; } void Insert_head(PList plist,int val) { Node *p = BuyNode(val); p->next = plist->next; plist->next = p; } void Insert_tail(PList plist,int val) { Node *p = BuyNode(val); Node *q; for(q=plist;q->next != NULL;q=q->next) { ; } q->next=p; } Node *Search(PList plist,int key) { for(Node *p=plist->next;p != NULL;p=p->next) { if(key==p->data) { return p; } } return NULL; } static Node *Searchprio(PList plist,int key) { for(Node *p=plist;p->next != NULL;p=p->next) { if(key == p->next->data) { return p; } } return NULL; } bool Delete(PList plist,int key) { Node *p; p=Search(plist,key); if(p == NULL) { return false; } Node *q=Searchprio(plist,key); if(q == NULL) { return false; } q->next=p->next; free(p); return true; } int GetLength(PList plist) { int count=0; for(Node *p=plist;p->next != NULL;p=p->next) { count++; } return count; } bool IsEmpty(PList plist) { return(plist->next == NULL); } void Clear(PList plist) { assert(plist != NULL); plist->next= NULL; } void Destroy(PList plist) { //Node *p=plist; while(plist->next != NULL) { Node *p = plist->next; plist->next = p->next; free(p); } } void Show(PList plist) { for(Node *p=plist->next;p!=NULL;p=p->next) { printf("%d ",p->data); } printf("\n"); } void Reverse(PList plist) //逆置函数 { Node *p=plist->next; plist->next=NULL; while(p != NULL) { Node *q = p->next; p->next = plist->next; plist->next=p; p = q; } } bool Insert_pos(PList plist,int pos,int val) // 1<pos<GetLength(plist) //按位置插入 { Node *p=plist; Node *q=BuyNode(val); int j=1; while(p && j<pos) { p=p->next; j++; } if(p == NULL ||j>pos ) { return false; } else { q->next = p->next; p->next=q; return true; } }
测试函数代码:
/* * 文件名称:tasklianbiao.cpp * 摘要:链表的基本运算 * * 当前版本:1.0 * 原作者:成耐克 * 完成日期:2016年1月25日 * 注:在Delete()函数中,与老师的意思有出入。我们可以当前节点,在得到当前的前驱结点,然后进行删除操作 */ #include<stdio.h> #include<vld.h> #include"lianbiao.h" int main() { Node head; InitList(&head); //头插 for(int i=0;i<15;i++) { //Insert_head(&head,i);//头插 Insert_tail(&head,i); //尾插 } Show(&head); int n=GetLength(&head); //删除元素前得到长度 printf("%d \n",n); Delete(&head,3); //删除某一个结点 Show(&head); int m=GetLength(&head); //删除元素后得到长度 printf("%d \n",m); if(IsEmpty(&head)==false) //判空操作 { printf("该链表不为空\n"); } //Clear(&head); int r=GetLength(&head); //删除元素后得到长度 printf("%d \n",r); if((Insert_pos(&head,2,100)) == true) { Show(&head); } else { printf("插入不成功!\n"); } // int r=GetLength(&head); //删除元素后得到长度 printf("%d \n",GetLength(&head)); Reverse(&head); //逆置测试 Show(&head); //Destroy(&head); return 0; }
总结完毕,欢迎指正!
相关文章推荐
- 2-11-一元多项式运算-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-10-归并扩展的线性单链表-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-9-扩展的线性单链表(带头结点)-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- HDU 1198 Farm Irrigation (并查集)
- 2-8-双循环链表链式存储结构-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构:索引之线性索引
- Java数据结构----树--红黑树
- Java数据结构----树--平衡二叉树
- 2-7-集合运算(A-B)∪(B-A)-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- Python数据结构(一)关于字典
- 2-6-静态链表-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 回文串判断与查找
- 2-5-归并链式存储的单链表-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-4-单链表链式存储结构-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-3-归并单链表(顺序表)-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-2-求并集A=A∪B-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-1-单链表顺序存储结构-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 《数据结构》带头结点单链表的合并
- 数据结构之串
- 《数据结构进行曲》 带头结点单循环链表的合并