【数据结构】单链表--基础

来源:互联网 发布:男士去黑头洗面奶 知乎 编辑:程序博客网 时间:2024/06/13 22:23


在实现单链表的基本功能后

单链表的几个基本问题:

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?

顺序表(物理位置相邻):优点:在一段内存中用数组连续存放,所以方便随机查找元素。

    缺点:动态开辟,容易造成内存浪费,需要一个元素,开辟过多。前面添加元素时,要逐个挪动后面的每个元素,较麻烦。

    场景:数据频繁查找修改,但很少添加。

单链表(物理位置不相邻):优点:方便开辟,用多少开辟多少,不会造成内存空间浪费。

    缺点:不方便直接查找。

    场景:频繁添加数据,但很少查询。

2.从尾到头打印单链表 :

可以运用递归的方法从尾到头打印。

从头节点向后递归,结束条件当节点为空

返回输出该节点的值。

void PrintTailToHead(ListNode *pList) //逆序打印 用递归{if (pList == NULL)return;PrintTailToHead(pList->next);//子问题printf("%d->", pList->data);}

3.删除一个无头单链表的非尾节点 :

  1.将后面节点的值赋给pos

  2.删除pos

void EraseNonTail(ListNode *pos) //无头删除指定非尾节点{assert(pos);ListNode *cur = pos->next;//1.交换与后面的值DataType tmp = cur->data;cur->data = pos->data;pos->data = tmp;//2.删除后面的节点pos->next = cur->next;free(cur);}

4.在无头单链表的一个节点前插入一个节点:

  1.在pos后面插入一节点

   2.将pos与后面的值交换

void InsertNonFront(ListNode *pos, DataType x) //在无头单链表的一个节点前插入一个节点{assert(pos);//1.后面插入ListNode *tmp = BuyNode(x);tmp->next = pos->next;pos->next = tmp;//2.值交换DataType n = pos->data;pos->data = tmp->data;tmp->data = n;}

5.单链表实现约瑟夫环 :

   已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依规律重复下去,直到圆桌周围的人全部出列。

  俩个循环 里循环走数k个,将第k个删除。外循环从删除后下一个再开始直到剩下一个节点。

ListNode* JoseohRing(ListNode *pList, int k)//约瑟夫环{if (pList == NULL)return NULL;ListNode *cur = pList;while (cur->next != cur){int count = k;while (--count) //走k-1次{cur = cur->next;}ListNode *next = cur->next;cur->data = next->data;cur->next = next->next;free(next);}return cur;}

6.逆置/反转单链表 

ListNode* Reverse(ListNode *pList)//链表的逆置{if ((pList == NULL) || (pList->next == NULL))return pList;else{ListNode *newHead = NULL;ListNode *cur = pList;while (cur){ListNode *tmp = cur;cur = cur->next;tmp->next = newHead;newHead = tmp;}return newHead;}}

7.单链表排序(冒泡排序|快速排序)

void BubbleSort(ListNode *pList)//冒泡排序{if ((pList == NULL) || (pList->next == NULL))return;else{ListNode *tail = NULL;while (tail != pList->next){int exchange = 0;ListNode *cur = pList;ListNode *next = cur->next;while (next != tail){if (cur->data > next->data){DataType tmp = cur->data;cur->data = next->data;next->data = tmp;exchange = 1;}next = next->next;cur = cur->next;}if (exchange == 0)return;tail = cur;}}}

8.合并两个有序链表,合并后依然有序

ListNode* MergeList(ListNode *pList1, ListNode *pList2)//归并排序{if (pList1 == NULL)return pList2;else if (pList2 == NULL)return pList1;else{//摘做头ListNode *list = NULL;if (pList2->data < pList1->data){list = pList2;pList2 = pList2->next;}else{list = pList1;pList1 = pList1->next;}ListNode *tail = list;while (pList1 && pList2){if (pList1->data < pList2->data){tail->next = pList1;pList1 = pList1->next;}else{tail->next = pList2;pList2 = pList2->next;}tail = tail->next;}if (pList1)tail->next = pList1;elsetail->next = pList2;return list;}}

9.查找单链表的中间节点,要求只能遍历一次链表 

 定义 fast 与 slow fast每走2个slow走一个 fast走完全部,slow走了一半 为中节点

ListNode* FindMidNode(ListNode *pList)//查找单链表的中间节点{ListNode *fast = pList;ListNode *slow = pList;ListNode *prev = pList;while ((fast)&&(fast->next)){fast = fast->next;fast = fast->next;prev = slow;slow = slow->next;}if (fast == NULL)slow = prev;return slow;}

10.查找单链表的倒数第k个节点,要求只能遍历一次链表

   将fast先走k-1 然后与slow同时走 fast走动尾节点时,slow为倒数第k节点

//k<=链表个数ListNode* FindTailkNode(ListNode *pList, DataType k)//查找单链表的倒数第k个节点{if (pList == NULL)return NULL;ListNode *fast = pList;ListNode *slow = pList;while (--k){fast = fast->next;}while (fast->next){fast = fast->next;slow = slow->next;}return slow;}








原创粉丝点击