数据结构---链表
链表: 是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).
优点: 使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理.
缺点: 链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大.
链表类型
单向链表
它包含两个域,一个信息域和一个指针域.
struct Node { EleType element; struct Node *next; };
含头指针的示意图:
双向链表
每个节点有两个连接:一个指向前一个节点,(当此“连接”为第一个“连接”时,指向空值或者空列表);而另一个指向下一个节点,(当此“连接”为最后一个“连接”时,指向空值或者空列表)
struct Node { EleType element; struct Node *next; struct Node *prev; };
示意图:
循环链表
作为单向链表或者双向链表的一种变形----首节点和末节点连接在一起
具体实现(C语言)
图形描述实现函数:
1. 删除某个节点
2. 增加某个节点
3. 其余类似
单向链表---此处将结构放在实现函数中而非头文件中
头文件 list.h罗列除具体实现的函数原型
#ifndef _List_H_ #define _List_H_ #define EleType int struct Node; typedef struct Node *PtrToNode; typedef PtrToNode List; typedef PtrToNode Position; List Init(); List CreatList(); void PrintList(List list); List MakeEmpty(List list); int IsEmpty(List list); int IsLast(Position pos,List list); Position Find(EleType x,List list); void Delete(EleType x,List list); Position FindPrevious(EleType x,List list); void Insert(EleType x,List list,Position pos); void DeleteList(List list); Position Header(List list); //not implement Position First(List list); //not implement Position Advance(Position pos); //not implement EleType Retrieve(Position pos); //not implement #endif
各函数的具体实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<stdlib.h> #include "list.h" typedef struct Node { EleType element; struct Node *next; }Node; List Init() { List list; list=(Node *)malloc(sizeof(Node)); list->next=NULL; return list; } List CreatList() { int num,i; int element; List list; Position pos; list=Init(); pos=list; printf("How long the list would you want to creat!\n"); scanf("%d",&num); for(i=0;i<num;i++) { scanf("%d",&element); //if the element is not int,change Insert(element,list,pos); pos=pos->next; } return list; } int IsEmpty(List list) { return list->next==NULL; } int IsLast(Position pos,List list) { return pos->next==NULL; } Position Find(EleType x,List list) { Position p; p=list->next; while(p!=NULL&&p->element!=x) p=p->next; return p; } //It means the position before position(element of x) Position FindPrevious(EleType x,List list) { Position p; p=list; while(p->next!=NULL&&p->next->element!=x) p=p->next; return p; } void Delete(EleType x,List list) { Position p,temp; p=FindPrevious(x,list); if(!IsLast(p,list)) { temp=p->next; p->next=temp->next; free(temp); //free the space } } void Insert(EleType x,List list,Position pos) { Position temp; temp=(Node*)malloc(sizeof(Node)); if(temp==NULL) { printf("Out of space\n"); return; } temp->element=x; temp->next=pos->next; pos->next=temp; } void DeleteList(List list) { Position p,temp; p=list->next; list->next=NULL; while(p!=NULL) { temp=p->next; free(p); p=temp; } } void PrintList(List list) { Position temp; temp=list->next; printf("Header-->"); while(temp!=NULL) { printf("%d-->",temp->element); temp=temp->next; } printf("NULL\n"); }
(相对比较简陋,如有错误,望指出~thank you!)
测试代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<stdlib.h> #include "list.h" int main() { List list; list=CreatList(); PrintList(list); }
注:只给了非常简单的测试代码
双向链表---此处将结构放入头文件
----ps: 个人认为双向链表写的比单向好些(上面的写的那么糟糕, 不妨看看此处)
关于结构放入头文件和放入.c文件的区别见另一篇文章:
头文件 link.h
#ifndef _Linked_H #define _Linked_H #define EleType int struct Node { EleType element; struct Node *prev; struct Node *next; }; struct List { struct Node *header; int size; }; typedef struct Node Node; typedef struct List List; typedef Node *PtrToNode; typedef PtrToNode PNode; void PrintList(List list); List CreatList(int len); PNode CreatNode(EleType k); PNode Search(List l,EleType k); void Insert(List *l,PNode node); void Delete(List *l,PNode node); void DeleteList(List *l); int IsEmpty(List l); PNode GetKnode(List l,int k); int ChangeKthNode(List *l,int k,EleType newele); void InsertEnd(List *l,PNode pnode); void InsertKth(List *l,int k,PNode pnode); void ChangeTwoNodes(List *l,PNode pn1,PNode pn2); void QuickSort(List *l,int left,int right); #endif
具体函数实现: linkmethod.c
(PS: 看到一篇博客上说实现链表的10来种功能, 就尽可能多地写了以下方法---如有重要需补充,望指出!)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<stdlib.h> #include "link.h" /*creat node pointer for list*/ PNode CreatNode(EleType k) { PNode node; node=malloc(sizeof(Node)); if(node==NULL) { printf("Out of space!\n"); return NULL; } node->element=k; return node; } /*creat a list,it's a little bad*/ List CreatList(int len) { List list; int i; EleType k; if(len==0) { list.header=NULL; list.size=0; return list; } scanf("%d",&k); list.header=CreatNode(k); list.size=1; for(i=1;i<len;i++) { scanf("%d",&k); Insert(&list,CreatNode(k)); } return list; } /*print(show) the list*/ void PrintList(List list) { PNode temp; temp=list.header; while(temp!=NULL) { printf("%d-->",temp->element); temp=temp->next; } printf("null\n"); } /*get the node(pointer) with the element is k */ PNode Search(List l,EleType k) { PNode pos; pos=l.header; while(pos!=NULL&&pos->element!=k) pos=pos->next; return pos; } /*insert the node to list*/ void Insert(List *l,PNode node) { node->next=l->header; if(l->header!=NULL) l->header->prev=node; l->header=node; node->prev=NULL; l->size+=1; } /*delete the node in the list*/ void Delete(List *l,PNode node) { if(node->prev!=NULL) node->prev->next=node->next; else l->header=node->next; if(node->next!=NULL) node->next->prev=node->prev; l->size-=1; free(node); } /*delete the all nodes in list,header->null*/ void DeleteList(List *l) { PNode temp,p; p=l->header; l->header=NULL; while(p!=NULL) { temp=p->next; free(p); p=temp; } l->size=0; } /*exam whether the list is null? 1---null 0---not null*/ int IsEmpty(List l) { return l.header==NULL; } /*Get the Kth node in the list*/ PNode GetKnode(List l,int k) { if(k>l.size||k<1) { printf("The k is exceed the list!!\n"); return NULL; } int i; PNode pnode; pnode=l.header; for(i=1;i<k;i++) { pnode=pnode->next; } return pnode; } /*Change the Kth node's element*/ int ChangeKthNode(List *l,int k,EleType newele) { if(k>l->size||k<1) return 0; PNode temp; int i; temp=l->header; for(i=1;i<k;i++) temp=temp->next; temp->element=newele; return 1; } /*Add a node in the end of list*/ void InsertEnd(List *l,PNode pnode) { PNode pend; pend=GetKnode(*l,l->size); if(pend==NULL) l->header=pnode; else { pend->next=pnode; pnode->prev=pend; pnode->next=NULL; l->size+=1; } } /*Add a node in the Kth position of list*/ void InsertKth(List *l,int k,PNode pnode) { PNode pkth; pkth=GetKnode(*l,k); if(pkth==NULL) { printf("failed! k exceed the list length!\n"); return; } if(k==1) { Insert(l,pnode); } else { pnode->prev=pkth->prev; pnode->next=pkth; pkth->prev->next=pnode; pkth->prev=pnode; l->size+=1; } } int IsInList(List l,PNode pnode) { PNode temp; temp=Search(l,pnode->element); return pnode==temp; } /*change the two nodes'element*/ void ChangeTwoNodes(List *l,PNode pn1,PNode pn2) { if(IsInList(*l,pn1)!=1||IsInList(*l,pn2)!=1) { printf("error: There exist node not in List!\n"); return; } EleType temp; temp=pn1->element; pn1->element=pn2->element; pn2->element=temp; } /*Do quick sort to list*/ void QuickSort(List *l,int left,int right) { if(left>=right) { return; } int q; int i=left-1,j; EleType x=GetKnode(*l,right)->element; for(j=left;j<right;j++) { if(GetKnode(*l,j)->element<=x) { i++; ChangeTwoNodes(l,GetKnode(*l,i),GetKnode(*l,j)); } } ChangeTwoNodes(l,GetKnode(*l,i+1),GetKnode(*l,right)); q=i+1; QuickSort(l,left,q-1); QuickSort(l,q+1,right); }
测试代码 linktest.c
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<stdlib.h> #include "link.h" int main() { int i; List list; PNode pnode; list.header=CreatNode(4); list.size=1; Insert(&list,CreatNode(6)); Insert(&list,CreatNode(5)); PrintList(list); printf("list's len='%d\n",list.size); pnode=Search(list,4); Delete(&list,pnode); PrintList(list); pnode=GetKnode(list,3); if(pnode!=NULL) printf("the 3th node is=%d\n",pnode->element); printf("the change is success?: %d\n",ChangeKthNode(&list,2,20)); pnode=CreatNode(30); InsertKth(&list,2,pnode); PrintList(list); ChangeTwoNodes(&list,Search(list,5),Search(list,20)); PrintList(list); QuickSort(&list,1,list.size); PrintList(list); printf("%d\n",list.size); }
具体应用实例
近期内补上~