单链表

来源:互联网 发布:网络舆论 社会影响 编辑:程序博客网 时间:2024/06/08 18:49

单链表

#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <time.h>#define random(x) rand() % (x) //rand()的范围是在0与 ((unsigned int)-1 >> 1)...然后求余//然后求余之后那么范围在 X之内了typedef int Status;typedef int ElemType;//下面的2个结构体主要是体现一个体系,节点相当于溶液,链表相当于容器typedef struct LNode{ElemType data;struct LNode* next;}*LNode;typedef struct LinkList{struct LNode* head;int size;}LinkList;//由于链表包含这节点的指针,所以传递LinkList* List 相当于传一个2维指针//而二维指针传递代表着对链表的改变//所以对于没有改变链表的操作直接传递指针Status InitSingleList(LinkList* List);Status CreateSingleList(LinkList* List,int n);Status SingleListTraverse(LinkList List,int (visit)());Status SingleListReverse1(LinkList* List);Status SingleListReverse2(LinkList* List);LNode SingleListReverse3(LNode head);Status SingleListEmpty(LinkList List);Status ClearSingleList(LinkList* List);Status DestroySingleList(LinkList* List);Status SingleListInsert(LinkList* List,int i,ElemType e);Status SingleListDelete(LinkList* List,int i,ElemType* e);LNode LocateNode(LinkList List,ElemType);Status BubbleSort(LinkList* List);Status IsListLoop(LinkList List);//主要是把传进来的数据强制类型转换成一个类型,然后输出。//像上面的宏定义,都是体现一个泛形的是想int visit(void* ListData){printf("%d\t",*(int*)ListData);return 1;}int main(){LinkList List;int n = 0;if(InitSingleList(&List) == 0){fprintf(stderr,"inition list if fail");exit(1);}printf("please input the counter of number\n");scanf("%d",&n);CreateSingleList(&List,n);SingleListTraverse(List,&visit);SingleListReverse1(&List);SingleListTraverse(List,&visit);SingleListDelete(&List,2,&n);SingleListReverse2(&List);SingleListTraverse(List,&visit);List.head -> next = SingleListReverse3(List.head -> next);SingleListTraverse(List,&visit);SingleListInsert(&List,4,0);SingleListTraverse(List,&visit);BubbleSort(&List);SingleListTraverse(List,&visit);return 0;}//意图是如果有环那么一个跑得快的必然会和跑的慢的相遇Status IsListLoop(LinkList List){LNode head = List.head;LNode p = head,q = head;while(p && p -> next && p != q){p = p -> next -> next;q = q -> next;}if(p = q)return 1;elsereturn 0;}//排序如果少于2个节点,那么直接返回,//比如有3个节点,我用q标记第一个,p标记第3个,这样来让2个节点交换位子//这个东西在ptail的使用上要小心Status BubbleSort(LinkList* List){if(List -> size < 2)return 1;LNode head = List -> head,q = head,p = q -> next -> next,ptail = NULL;while(head -> next != ptail){q = head;p = q -> next -> next;while(p != ptail){if(q -> next -> data > p -> data){q -> next -> next = p -> next;p -> next = q -> next;q -> next = p;}p = p -> next;q = q -> next;}ptail = q -> next;}return 1;}LNode LocateNode(LinkList List,ElemType e){LNode head = List.head -> next;while(head && head -> data != e)head = head -> next;return head;}//对于&&操作一定要记得顺序问题//我个人习惯上喜欢把指针p指向头结点,标记位j = 1。既保持1的距离//当j = i时,p指向i的前一个结点Status SingleListInsert(LinkList* List,int i,ElemType e){if(i < 1 || i > List -> size + 1)return 0;LNode head = List -> head,p = head,PNew = NULL;int j = 1;while(p != NULL && j < i) { p = p -> next; j++; } if(!(PNew = (LNode) malloc (sizeof(struct LNode))) && !p)//careful the order return 0;PNew -> data = e;PNew -> next = p -> next;p -> next = PNew;List -> size++;return 1;}//同样保持1的距离Status SingleListDelete(LinkList* List,int i,ElemType* e){if(i < 1 || i > List -> size)return 0;LNode head = List -> head,p = head,q = NULL;int j = 1;while(p != NULL && j < i){ p = p -> next; j++;}q = p -> next;p -> next = q -> next;free(q);List -> size--;return 1;}Status DestroySingleList(LinkList* List){ClearSingleList(List);free(List -> head);List -> head = NULL;List -> size = 0;return 1;}Status ClearSingleList(LinkList* List){while(SingleListEmpty(*List) == 0 )DeleteListHead(List);List -> size = 0;return 1;}Status DeleteListHead(LinkList* List){if(List -> head -> next == NULL)return 0;LNode p = List -> head,q = p -> next;p -> next = q -> next;free(q);List -> size--;return 1;}Status SingleListEmpty(LinkList List){return List.size == 0 ? 1 : 0;}//这个递归适合在无头节点的情况下使用//如果是有头节点的话记得把首节点传进来LNode SingleListReverse3(LNode head){if(head -> next == NULL)return head;else{LNode NewHead = SingleListReverse3(head -> next);head -> next -> next = head;head -> next = NULL;return NewHead;}}//这个实现其实是把说有的节点逆向,包括头节点,让一个tail指向头节点,然后头尾相邻Status SingleListReverse2(LinkList* List){LNode head = List -> head,p = head -> next,q = NULL,tail = p;head -> next = NULL;while(p != NULL){q = p;p = p -> next;q -> next = head;head = q;}head = tail -> next;//从新然head指向头节点head -> next = q;//头节点的next指向尾节点tail -> next = NULL;//然后让首节点的next指向NULLreturn 1;}//头插法逆序,个人认为是最好的,能同时满足有无头节点Status SingleListReverse1(LinkList* List){LNode head = List -> head,p = head -> next,q = NULL;head -> next = NULL;while(p != NULL){q = p;p = p -> next;q -> next = head -> next;head -> next = q;}return 1;}Status SingleListTraverse(LinkList List,int (visit())){LNode head = List.head,p = head -> next;while(p != NULL){visit(&p -> data);p = p -> next;}printf("\n");return 1;}Status CreateSingleList(LinkList* List,int n){LNode head = List -> head,p = head,PNew = NULL;int i = 1;srand(time(NULL));while(i <= n){if((PNew = (LNode) malloc (sizeof(struct LNode))) == NULL)return 0;PNew -> next = NULL;PNew -> data = random(100);p -> next = PNew;p = p -> next;i++;}List -> size += n;return 1;}Status InitSingleList(LinkList* List){LNode head = NULL;if((head = (LNode) malloc (sizeof(struct LNode))) == NULL)return 0;head -> next = NULL;List -> head = head;List -> size = 0;return 1;}