数据结构之单链表(C语言实现)

来源:互联网 发布:怎么查看网络拨号密码 编辑:程序博客网 时间:2024/05/01 15:10

数据结构之单链表(C语言实现)

本次介绍三种单链表:普通单链表、循环链表和双向链表,后面的博客会继续介绍后两种链表


首先介绍单链表的特点:

1.链表是由一个个内存地址不连续的节点组成

2.每个节点最多只有一个前驱,一个后记(第一个节点只有后继没有前驱,最后一个节点只有前驱没有后继)

3.链表不支持随机存取(意思就是不能通过下标来进行找某个节点,只能从头到尾进行遍历)

4.链表的查找只能从头到尾对链表进行遍历,时间复杂度为O(n);而顺序表查找元素只要给一个下标即可,时间复杂度为O(1)

5.删除链表的某个节点时只需改变节点的指针,不需要移动大量元素


然后从三个方面来介绍三种链表的通用操作:

1.链表的初始化

2.申请一个链表节点

3.链表的头插法

4.链表的尾插法

5.获取链表长度

6.删除链表节点

7.查找指定值的节点

8.销毁链表(释放链表所有节点的内存空间)

9.输出单链表(输出单链表所有节点的数据域)


说明:以下单链表的实现,是数据域以整型为例,而且带有头结点。


一、普通单链表

1.单链表的结构

typedef struct _Node

{

int data;//数据域

struct _Node* next;//指针域

}Node, *List;


2.链表的操作

(1)链表的初始化(带头结点)

这里的初始化只要是指初始化头结点的指针域

void InitList(List plist){if (NULL == plist)return;plist->next = NULL;}

(2).申请一个链表节点

从堆中申请一个节点,注意这里是从堆中申请的内存,只能通过free(p)显式释放内存。即使是局部变量,该内存也不会随着函数调用完成而释放该内存。

static Node* BuyNode(int val){Node* pTmp = (Node*)malloc(sizeof(Node));pTmp->next = NULL;return pTmp;}


(3).链表头插法

这里的链表是带有头结点的,所以每次新插入的节点应插入头结点后面。

void InsertHead(List plist, int val){Node *pTmp = BuyNode(val);//申请一个节点,数据域为valpTmp->next = plist->next;plist->next = pTmp;}


(4).链表尾接法

每次将新插入的节点插入到最后一个节点后面,所以采用尾接法插入节点时首先要找到尾节点

void InsertTail(List plist, int val){Node *pTmp = BuyNode(val);Node *pCur;for (pCur = plist; NULL != pCur; pCur = pCur->next)//查找尾节点{;//空语句}pCur->next = pTmp;//将新节点插入到尾节点之后}


(5).获取链表长度

对链表进行遍历,每遍历一个节点,计数器加一。

int GetListLen(List plist){Node *pTmp = plist->next;int iCount = 0;while (NULL != pTmp){++iCount;pTmp = pTmp->next;}return iCount;}


(6).删除链表节点

删除指定值的链表节点时,需要遍历该链表,找到对应节点后想要删除该节点必须要知道该节点的前驱节点,这样才能正确删除该节点。

bool Delete(List plist, int val){Node* pPre = plist;//指向前驱节点Node* pCur = plist->next;//指向当前比较的节点while (NULL != pCur)//当链表没找完就继续找{if (pCur->data != val)//链表没找到就更新当前节点和它的前驱节点{pPre = pCur;//更新前驱节点为当前节点pCur = pCur->next;//更新当前节点为下一个节点}else{pPre->next = pCur->next;free(pCur);//释放待删节点的内存return true;//找到该节点返回true}}return false;}


(7).查找指定值的节点

查找指定值的节点也需要从头到尾遍历链表,若找到则返回该节点,没找到则返回NULL。

Node* Search(List plist, int val){Node *pCur = plist->next;while (NULL != pCur){if (pCur->data == val){return pCur;}pCur = pCur->next;}return NULL;}


(8).销毁链表

销毁链表就是释放链表中所有节点的内存。

void Destroy(List plist){Node* pCur = plist->next;//注意销毁链表后头结点的内存空间还是存在的,即空链表就是只有一个头结点的单链表while (NULL != pCur){plist = pCur->next;free(pCur);pCur = plist->next;}}


(9).输出单链表

输出单链表的操作也比较简单,从头到尾遍历单链表,每遍历一个节点就输出该节点的指针域

void Show(List plist){Node* pCur = plist->next;while (NULL != pCur){printf("%5d", pCur->data);pCur = pCur->next;}printf("\n");}


最后附上完整代码和运行结果:

//Link.h#include<stdio.h>#include<stdlib.h>typedef struct _Node{int data;struct _Node* next;}Node, *List;void InitList(List plist);void InsertHead(List plist, int val);void InsertTail(List plist, int val);bool Delete(List plist, int val);Node* Search(List plist, int val);int GetListLen(List plist);void Destroy(List plist);static Node* BuyNode(int val);void Show(List plist);



//Link.c#include "test.h"int main(){Node head;InitList(&head);for (int i = 0; i < 13; ++i){InsertTail(&head, i);//尾插法}ShowList(&head);printf("链表长度:%d\n", GetListLen(&head));for (int i = 0; i < 12; ++i){InsertHead(&head, i);//头插法}ShowList(&head);printf("链表长度:%d\n", GetListLen(&head));printf("search 12:\n");Node *p = Search(&head, 12);//查找节点if (p != NULL){printf("%d\n", p->data);}else{printf("Not Found\n");}printf("删除节点12:\n");//删除节点if (Delete(&head, 12)){ShowList(&head);}else{printf("链表中无此节点\n");}Destroy(&head);//销毁链表return 0;}void InitList(List plist){if (NULL == plist)return;plist->next = NULL;}void InsertHead(List plist, int val){Node *pTmp = BuyNode(val);pTmp->next = plist->next;plist->next = pTmp;}void InsertTail(List plist, int val){Node *pTmp = BuyNode(val);Node *pCur;for (pCur = plist; NULL != pCur->next; pCur = pCur->next){;//空语句}pCur->next = pTmp;}bool Delete(List plist, int val){Node* pPre = plist;Node* pCur = plist->next;while (NULL != pCur){if (pCur->data != val){pPre = pCur;pCur = pCur->next;}else{pPre->next = pCur->next;free(pCur);return true;}}return false;}Node* Search(List plist, int val){Node *pCur = plist->next;while (NULL != pCur){if (pCur->data == val){return pCur;}pCur = pCur->next;}return NULL;}int GetListLen(List plist){Node *pTmp = plist->next;int iCount = 0;while (NULL != pTmp){++iCount;pTmp = pTmp->next;}return iCount;}void Destroy(List plist){Node* pCur = plist->next;//注意销毁链表后头结点的内存空间还是存在的,即空链表就是只有一个头结点的单链表while (NULL != pCur){plist = pCur->next;free(pCur);pCur = plist->next;}}static Node* BuyNode(int val){Node* pTmp = (Node*)malloc(sizeof(Node));pTmp->next = NULL;pTmp->data = val;return pTmp;}void ShowList(List plist){Node* pCur = plist->next;while (NULL != pCur){printf("%5d", pCur->data);pCur = pCur->next;}printf("\n");}


运行结果:


0 0
原创粉丝点击