算法与数据结构-单向链表的基本操作C语言实现

来源:互联网 发布:网络arp攻击怎么办 编辑:程序博客网 时间:2024/05/18 19:18

序言

通过这篇文章熟悉单向链表的常用操作。

单链表的基本操作

  1. 链表定义和初始化
  2. 单链表创建并赋值
  3. 检查单链表是否为空
  4. 清空单链表
  5. 遍历单链表
  6. 返回单链表的长度
  7. 单链表查找元素
  8. 单链表查找第pos个节点
  9. 交换单链表中两元素的位置
  10. 单链表第pos个节点后元素
  11. 单链表第pos个节点删除
  12. 单链表逆置
  13. 在单链表末尾添加一个节点
  14. 有序单链表中插入元素element保持有序


1. 单链表定义

/* 定义1 */struct listNode{    int data;    struct listNode *next;};/* 定义2:推荐 */typedef linkListNode{    int data;    linkListNode *next;}listNode;


2. 单链表初始化

/* 不带头结点的链表 */void InitList(struct listNode *linkList){    *linkList = NULL;}/* 带头结点的链表 */void InitList(struct listNode *linkList){    linkList = (struct listNode *)malloc(sizeof(struct listNode) * 1);    if (listNode == NULL)    {        printf("申请内存空间失败\n");        exit(1);    }    linkList -> next = NULL;}


3. 单链表创建并赋值

/* 创建一个单链表,并将数组元素顺序附给链表 *//* 单链表创建:尾插法 */void *ListCreate(struct listNode *linkList,int array[], int n){    //链表初始化    InitList(linkList);    //指向尾节点的变量 + 节点变量    listNode *rear, *new;    rear = *linkList;    for (int i = 0; i < n; i++)    {        new = (struct listNode *)malloc(sizeof(struct listNode) * 1);        new -> data = array[i];        rear -> next = new;        rear = new;    }    rear -> next = NULL;}

注释:
(1)rear与linkList的关系:linkList是整个单链表,rear是指向尾节点的变量。rear会随着循环不断变化节点,而linkList则随着循环增长为一个多节点链表。
(2)rear和rear->next区分:是两个独立的指针。

rear->next = new将尾节点指针指向新节点
rear = new将尾节点指向新节点
rear->next = NULL将链表指针域置空,以便以后遍历时确认其是链表尾部。


4. 检查链表是否为空

/* 检查链表是否为空,为空返回1,否则返回0 */int CheckListEmpty(struct ListNode *L){    if (L == NULL)        return 1;    else        return 0;}


5. 清空单链表

/* 清空单链表,但仍保留head节点 */int EmptyList(struct listNode *L){    struct listNode *nodeScan, *nextNode;    if (L == NULL)                   //链表为空        return 0;    nodeScan = *L;    while (nodeScan -> next != NULL)    {        nextNode = nodeScan -> next;        free(nodeScan);        nodeScan = nextNode;    }    L->next == NULL;    return 1;}


6. 遍历单链表

void TraverseList(struct listNode *L){    struct listNode *nodeScan = *L;    while (nodeScan != NULL)    {        printf("%d ", nodeScan -> data);        nodeScan = nodeScan ->next;    }}


7. 返回单链表的长度

int LengthOfList(struct listNode *L){    int len = 0;    struct listNode *nodeScan = *L;    while (nodeScan != NULL)    {        len++;        nodeScan = nodeScan -> next;    }    return len;}


8. 单链表查找元素element

int FindEleInList(struct listNode *L, int element){    int pos = 0;     //元素位置计数    struct listNode *nodeScan = *L;    while (nodeScan != NULL)    {        pos++;        if (element = nodeScan -> data)        {            return pos;        }        nodeScan = nodeScan -> next;    }    printf("element is not within this list!\n");    return 0;}           


9. 单链表查找第pos个元素

//int NodeSearch()struct listNode *NodeSearch(struct listNode *L, int pos){    struct listNode *nodeScan = *L;    int count = 1;    if (pos == 1)        return nodeScan -> data;    while (count < pos)    {        count++;        nodeScan = nodeScan -> next;        if (nodeScan == NULL)        {            printf("node search error\n");            exit(1);        }    }    return nodeScan;    //return nodeScan -> data;}


10. 交换单链表中两元素的位置

void ExchangeNode(struct listNode *L, int i, int j){    if (i == j)        return;    struct listNode *Node1,*Node2,*tempNode;    //节点临时存储空间申请(需要存储数据就需要申请空间)    tempNode = (struct listNode *)malloc(sizeof(struct listNode) * 1);    //节点提取    Node1 = NodeSearch(L, i);    Node2 = NodeSearch(L, j);    //节点元素值交换    tempNode -> data = Node1 -> data;    Node1 -> data = Node2 -> data;    Node2 -> data = tempNode -> data;   }


11. 单链表第pos个节点后元素

int NodeInsertion(struct listNode *L, int pos, int element){    int count = 1;    struct listNode *nodeScan = *L;    struct listNode *newNode = NULL;    struct listNode *originNode = NULL;    while (count != pos)    {        count++;        nodeScan = nodeScan -> next;        originNode = nodeScan -> next;    }    //创建新节点    newNode = (strcut listNode *)malloc(sizeof(struct listNode) * 1);    if (newNode == NULL)    {        printf("node allocate failed\n");        return 0;    }    newNode -> data = element;    //新节点    nodeScan -> next = newNode;    newNode -> next = originNode;    return 1;}


12. 单链表第pos个节点删除

int DeleteListNode(struct listNode *L, int pos){    int count = 1;    struct listNode *nodeScan = *L;    struct listNode *originNode= NULL;    while (count != pos)    {        count++;        originNode = nodeScan;        nodeScan = nodeScan -> next;        if (nodeScan == NULL)            printf("pos is beyond max len of List\n");    }    originNode -> next = nodeScan -> next;    int temp = nodeScan -> data;    free(nodeScan);    return temp;}   


13. 单链表逆置

/* 单链表逆置:加入原链表1->2->3->4,逆置后4->3->2->1 *///本文都是基于不带头结点的链表进行操作的void InvertList(struct listNode *L){    struct listNode *nodeScan = *L;                //搜索节点    struct listNode *nextNode = nodeScan -> next;  //下一节点    struct listNode *tempNode = NULL;              //暂存节点    nodeScan -> next = NULL;                       //首节点next指向NULL    while (nextNode != NULL)    {        tempNode = nextNode -> next;   //暂存下一节点的next指针        nextNode -> next = nodeScan;   //回指上一节点        //搜索节点和下一节点依次往后挪动一个        nodeScan = nextNode;        nextNode = tempNode;    }}   


14. 在单链表末尾添加一个节点

void AddNodeInEnd(struct listNode *L, int element){    struct listNode *nodeScan = *L;    struct listNode *newNode = NULL;    newNode = (struct listNode *)malloc(sizeof(struct listNode) * 1);    newNode -> data = element;    newNode -> next = NULL;    while (nodeScan -> next != NULL)    {        nodeScan = nodeScan -> next;    }    nodeScan -> next = newNode;          //查找链表结尾并元素}


15. 有序单链表中插入元素element,保持有序

void AddItemToSeqList(struct listNode *L, int element){    struct listNode *newNode;    newNode = (struct listNode *)malloc(sizeof(struct listNode) * 1);    if (newNode == NULL)    {        printf("mem alocate failed\n");        exit(1);    }    newNode -> data = element;    //比首节点元素还小,插入到链表头之前    if (L == NULL || (L -> data > element)    {        newNode -> next = L;        L = newNode;        return;    }    //查找插入位置    struct listNode *nodeScan = *L;    struct listNode *preNode = NULL;    while (nodeScan != NULL)    {        preNode = nodeScan;        nodeScan = nodeScan -> next;    }    //将元素插入到preNode和nodeScan之间    preNode -> next = newNode;    newNode -> next = nodeScan;}



Acknowledgements:
http://blog.csdn.net/tuwenqi2013/article/details/51800381
http://blog.csdn.net/bzhxuexi/article/details/41721429
http://blog.csdn.net/sh_frankie/article/details/48577927
http://blog.csdn.net/lzuacm/article/details/7437852
http://blog.csdn.net/guoyong10721073/article/details/9009625
http://www.cnblogs.com/Camilo/p/3927912.html(推荐)

2017.08.12
文章错误和不足之处,欢迎讨论交流。

阅读全文
0 0