9、尾插,和任意位置插入
发布时间:2025-06-24 17:43:53 作者:北方职教升学中心 阅读量:840
顺序表扩容后任然可能造成空间的浪费,并且顺序表扩容带来性能消耗
二、初始化
//尾删void SLTPopBack(SLTNode** pphead) { assert(*pphead); if (!(*pphead)->next) { free(*pphead); *pphead = NULL; return; } SLTNode* ptail = *pphead; SLTNode* prev = NULL; while (ptail->next) { prev = ptail; ptail = ptail->next; } prev->next = NULL; free(ptail); ptail = NULL; return;}//头删void SLTPopFront(SLTNode** pphead) { assert(*pphead); SLTNode* node = (*pphead)->next; free(*pphead); *pphead = node; return;}//任意位置删除void SLTErase(SLTNode** pphead, SLTNode* pos) { assert(*pphead); assert(pos); if (pos == *pphead) { SLTPopFront(pphead); } else { SLTNode* p = *pphead; while (p->next != pos) { p = p->next; } p->next = pos->next; free(pos); pos = NULL; } return;}
4、链表的中心结点
https://leetcode.cn/problems/middle-of-the-linked-list/description/
题目分析
采用快慢指针进行分析,快指针每次走两步,慢指针每次走一步,当
fast = NULL 或者 fast -> next = NULL 时,slow指针指向的就是中间位置的指针。移除链表元素
- (一)链表的结构定义
- (二)链表的功能实现
- 1、链表的回文结构
https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId=49&&tqId=29370&qru=/ta/2016test/question-ranking
题目分析
这道题有两个思路:
方法一 : 采用数组,将链表的结点数据依次放入数组之中,然后创建两个指针向中间移动,依次比较。//头删void erasePopFront(SeqList* SL) { for (int i = 1; i < SL->count; i++) { SL->data[i - 1] = SL->data[i]; } SL->count -= 1; return;}//尾删void erasePopBack(SeqList* SL) { assert(SL); assert(SL->count); SL->count -= 1; return;}//任意位置删除void erase(SeqList* SL, int pos) { if (pos < 0 && pos >= SL->count) return; for (int i = pos; i < SL->count - 1; i++) { SL->data[i] = SL->data[i + 1]; } SL->count -= 1; return;}
(三)顺序表例题分析
1、链表的回文结构
- 题目分析
- 方法一
- 方法二
- 6、链表的插入
链表的插入分为头插、合并两个有序数组
- 1、链表的回文结构
- (四)顺序表的弊端
- 题目分析
方法一
class PalindromeList {public: bool chkPalindrome(ListNode* A) { int arr[1000], i = 0; ListNode* p = A; while (p) { arr[i++] = p->val; p = p->next; } int left = 0, right = i - 1; while(left <= right) { if(arr[left++] != arr[right--]) return false; } return true; }};
方法二
这种在原链表上进行修改的反转操作有妙用
6、(二)顺序表的功能实现
1、8、移除链表元素
8、移除链表元素
https://leetcode.cn/problems/remove-linked-list-elements/
class Solution {public: ListNode* removeElements(ListNode* head, int val) { ListNode* newhead = NULL, *tail = NULL, *p = head; while(p){ if(p->val != val){ if(newhead == NULL) { newhead = tail = p; }else{ tail->next = p; tail = tail->next; } } p = p->next; } if(tail) tail->next = NULL; return newhead; }};
小结: 如果 tail 不是NULL, 要将 tail 置空。删除
删除操作分为头删、
SLTNode* BuyNode(SLTDataType x) { SLTNode* p = (SLTNode*)malloc(sizeof(SLTNode)); p->data = x; p->next = NULL; return p;}
2、顺序表
用物理地址连续的存储单元依次储存数据结构的线性结构,一般采用数组实现。
//头插void insertPushFront(SeqList* SL, SLdataType x) { SLCheckCapacity(SL); for (int i = SL->count - 1; i >= 0 ; i--) { SL->data[i + 1] = SL->data[i]; } SL->data[0] = x; SL->count += 1; return;}//尾插void insertPushBack(SeqList* SL, SLdataType x) { SLCheckCapacity(SL); SL->data[SL->count++] = x; return; }//任意位置插入void insert(SeqList* SL, SLdataType x, int pos) { if (pos < 0 && pos > SL->count) return; SLCheckCapacity(SL); for (int i = SL->count - 1; i >= pos; i--) { SL->data[i + 1] = SL->data[i]; } SL->data[pos] = x; SL->count += 1; return;}
5、销毁
typedef int SLTDataType;typedef struct SListNode { SLTDataType data; struct SListNode* next;}SLTNode;
(二)链表的功能实现
1、合并两个有序链表
https://leetcode.cn/problems/merge-two-sorted-lists/description/
题目分析
这道题的思路并不困难,主要是学一种新的头节点创建方式,通过 malloc 申请内存来获得头节点。扩容
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
class Solution {public: int removeDuplicates(vector<int>& nums) { int src = 1, dst = 0; while(src < nums.size()){ if(nums[src] == nums[dst]){ src += 1; } else{ nums[++dst] = nums[src++]; } } return dst + 1; }};
题目中我们用到双指针指针删除重复项,其中while 循环的条件设计十分巧妙
2、链表和顺序表都是线性表顺序表 : 物理结构连续,逻辑结构连续
链表 : 物理结构不一定连续(动态内存申请的空间可能是连续的,但是一般不会), 逻辑结构连续
一、class Solution {public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode* newhead, * tail; newhead = tail = (ListNode*)malloc(sizeof(ListNode)); newhead->next = NULL; while(list1 && list2){ if(list1->val < list2->val){ tail->next = list1; tail = tail ->next; list1 = list1->next; }else{ tail->next = list2; tail = tail->next; list2 = list2->next; } } if(list1) tail->next = list1; if(list2) tail->next = list2; ListNode* ret = newhead->next; free(newhead); newhead = NULL; return ret; }};
小结:这道题可以有三种方式创建头结点
1、直接开辟变量 Node head, 返回head->next;
2、
删除操作需要整体前移 : 从前面向后面遍历,反之会产生数据的覆盖。顺序表
顺序表 : 物理结构连续,逻辑结构连续
链表 : 物理结构不一定连续(动态内存申请的空间可能是连续的,但是一般不会), 逻辑结构连续
class Solution {public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode* newhead, * tail; newhead = tail = (ListNode*)malloc(sizeof(ListNode)); newhead->next = NULL; while(list1 && list2){ if(list1->val < list2->val){ tail->next = list1; tail = tail ->next; list1 = list1->next; }else{ tail->next = list2; tail = tail->next; list2 = list2->next; } } if(list1) tail->next = list1; if(list2) tail->next = list2; ListNode* ret = newhead->next; free(newhead); newhead = NULL; return ret; }};
小结:这道题可以有三种方式创建头结点
1、直接开辟变量 Node head, 返回head->next;
2、
删除操作需要整体前移 : 从前面向后面遍历,反之会产生数据的覆盖。顺序表
- (一)顺序表的结构定义
- (二)顺序表的功能实现
- 1、随机链表的复制
- 题目分析
- 结束语