数据结构中单链表的实现+单链表的C语言实现源代码

来源:互联网 发布:a5网站源码 编辑:程序博客网 时间:2024/04/27 18:39

线性表(List):零个或多个数据元素的有限序列。线性表的抽象数据类型。

线性表的顺序存储:

优点:无须为表示表中元素的逻辑关系而额外的存储空间,可以快速的取表中任意位置的元素。

缺点:插入和删除操作需要转移大量元素,线性表的长度较大时,难以确定存储空间的容量, 造成存储空间的“碎片”。

线性表的链式存储:

为了表示每一个数据元素a1与其直接后级数据元素ai+1之间的逻辑关系,对数据元素a1来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信号(即直接后继的存储位置)。存储数据元素信息的域叫做数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分组成数据元素ai的存储影像,称为结点(Node

其中头指针和头结点的区别:

1,头指针是指向链表的第一个结点的指针,若链表有都结点,则指向头结点的指针。头指针具有标示作用,所以常用头指针冠以链表的名字。无论链表是否为空,头指针均不为空,头指针是链表的必要条件。

2,头结点是为了操作的统一和方便设置的,放在头一个元素的结点之前,其数据域一般无意义。有了头结点,对其在第一元素位置前插入删除擦偶偶与其他结点的操作统一。头结点不是链表的必须要素。

带有头结点的指针;

空链表:

C语言中用结构指针表示结点:

typedef struct Node{int data;struct Node *next;}Node, *pNode,*LinkList;

 

其中单链表的抽象数据结构即操作有:

void InitList(LinkList *list);//初始化操作,建立空的单链表void ClearList(LinkList *list);//清空单链表。void ListInsert(LinkList *list,int i, int e);//单链表第i个位置后面插入变量evoid DestoryList(LinkList *list);//销毁链表bool ListEmpty(LinkList list);//判断单链表是否为空,为空返回真void GetElem(LinkList, int &e, int i);//将单链表中第i个位置的值返回给变量evoid ListDelete(LinkList *list, int i, int &e);//删除单链表表第i个位置元素void ListTraverse(LinkList list);//遍历线性表int ListLength(LinkList list);//返回线性表的长度void Recursion(LinkList list);//递归逆序输出单链表

各种函数的实现源代码:

void InitList(LinkList *list){*list = (LinkList)malloc(sizeof(Node));(*list)->next = NULL;(*list)->data = 0;}void ListInsert(LinkList *list, int i , int e)//第i个元素后面插入e{LinkList p = *list;if( i == 0){pNode q = (LinkList)malloc(sizeof(Node));q->next = NULL;q->data = e;p->next = q;}else{pNode p = (*list)->next;int j = 1;while( p && i > j){p = p->next;++j;}pNode q = (LinkList)malloc(sizeof(Node));q->next = p->next;q->data = e;p->next = q;}}void ListTraverse(LinkList list){pNode p = list;if(p != NULL){
p = p->next;
}
else 
{
return;
}
while(p){printf("%d\t", p->data);p = p->next;}}void Recursion(LinkList list)//递归的方法逆序输出链表{ if(NULL==list){ return;} if(list->next!=NULL){ Recursion(list->next); }printf("%d\t",list->data);}bool ListEmpty(LinkList list){pNode p = list;if(NULL == list->next)return true;elsereturn false;}void GetElem(LinkList list, int &e, int i){pNode p = list;if( i < 0 || i > ListLength(list))return ;p = p->next;int j = 1;while( j < i){p = p->next;j++;}e = p->data;}void ListDelete(LinkList *list, int i, int &e){pNode p = *list;if( i < 0 || i > ListLength(*list))return ;pNode q = p;p = q->next;int j = 1;while( j < i ){q = p;p = p->next;j++;}p->data = e;q->next = p->next;free(p);}int ListLength(LinkList list){pNode p = list;int i = 0;p = p->next;while(p){p = p->next;i++;}return i;}void ClearList (LinkList *list){pNode p = *list;if( p != NULL)p = p->next;pNode q;while( p ){q = p;p = p->next;free(q);}}void DestoryList(LinkList *list){pNode p = *list;if( p != NULL)p = p->next;pNode q;while( p ){q = p;p = p->next;free(q);}free(*list);}

测试函数源代码:

int main(){LinkList list;InitList(&list);ListInsert(&list, 0, 1);ListInsert(&list, 1, 2);ListInsert(&list, 2, 3);ListInsert(&list, 1, 4);ListInsert(&list, 1, 5);ListInsert(&list, 5, 6);ListInsert(&list, 6, 7);ListInsert(&list, 7, 8);ListInsert(&list, 8, 9);ListInsert(&list, 9, 10);printf("\n递归调用函数Reversion:\n");LinkList p = list->next;Recursion(p);printf("\n遍历链表ListTranverse:\n");ListTraverse(list);int j = ListLength(list);printf("\n链表的长度ListLength:%d\t",j);int e;GetElem(list, e,  3);printf("取链表特定的元素GetElem : %d\n",e);ListDelete(&list, 1, e);printf("\n删除链表中特定位置的元素:%d\n", e);ListTraverse(list);ClearList (&list);printf("\n链表清空ClearList: \n");ListInsert(&list, 0, 1);ListInsert(&list, 1, 2);ListInsert(&list, 2, 3);ListTraverse(list);DestoryList(&list);return 0;}


参考: 大话数据结构,数据结构(C语言版)严蔚敏版