希望能继续坚持下去
这篇博客应该是为菜鸡(本人)听课听的疑惑点进行知识梳理(如有错误请指正)
数据结构中的链表估计很多人会觉得简单,我也是怕记不住所以就尝试整理一下笔记吧
目录
1.创建链表(初始化)
2.统计链表节点
3.打印链表(正向or反向)
4.选择排序(递归)
5.查找单链表某个节点开始后的所有节点(直至表尾)
6.删除节点(删除单链表的第i个元素)
7.在单链表的第i个位置插入元素e
8.链表反转
9.约瑟夫
10.插入排序
struct ListNode { //链表结点类
int data; //数据域,当然int类型可以改为自定义类型T等等
ListNode * next; //主要讨论单链表
};
typedef ListNode* LinkList;
void createList(LinkList &L, int n)//LinkList &L等价于ListNode * &L
{
if (n == 0)return;//递归基
else{ //此时传进来的是第一个节点的指针
L = new ListNode; //创建生成的新节点
L->data; //这里的date可以赋值或者是初始化,不限方式
L->next = NULL; //链表基本尾插法
createList(L->next, n - 1); //递归创建n个节点
}
}
int countList(LinkList L){ //传入的L是形参,不影响原链表
if (L == NULL)
return 0; //递归结束条件,递归基
else
return countList(L->next) + 1; //否则继续指向下一个节点,表长加1
}
void forward_printList(LinkList L){ //正向
if (L == NULL)return; //递归基
else{
cout << L->data <next); //递归链表循环
}
}
void reverse_printList(LinkList L){ //反向
if (L == NULL)return;
else{
reverse_printList(L->next);
cout << L->data <
【选择排序很像人一般的思维,先找最小的,然后找第二小的……………………一直排下去】
void sortLink(LinkList &L){
//从小到大排序,本例子是换节点,直接更换节点的数据域也是可以的
LinkList p=L;
LinkList q=L;
if(L->next!=NULL) //链表非空
{
while(p->next!=NULL)
{
if(p->next->data < q->next->data)//查找最小节点进行排序
{
q=p; //q指向最小节点的前一个节点
}
p=p->next;
}
p=q->next; //p指向本轮最小节点
q->next=q->next->next; //将本轮最小节点从链表中剔除
p->next=L->next; //将原来头节点后的节点接到最小节点的后面
L->next=p; //将最小节点接到头节点后面
sortLink(L->next); //将最小节点作为头节点进行递归调用
}
return;//递归基
}
链表排序不交换节点型!
(leetcode只过了25个测试点,另外三个测试点超时了所以就。。,正确性能保证,也好理解)
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
/*有时候函数的返回值不是void型,千万不要判节点为空就返回NULL,
例如:
if(head==NULL) return NULL;
//这样结果只会返回最后一个NULL造成错误,然后当void型可以返回return;(不要加NULL)
链表的递归可以巧妙用下面这个循环if(head!=NULL)跳过
*/
if(head!=NULL){
ListNode *p=head; //循环该节点找最小节点
ListNode *q=head; //标记头结点交换小节点
ListNode *record=head; //记录链表中最小节点的位置
int min=999999;
while(p!=NULL){
if(min>p->val)
{
min=p->val;
record=p;
}
p=p->next;
}
int temp=q->val;
q->val=min;
record->val=temp;
sortList(head->next);//排序后面未被排序好的链表
}
return head;
}
};
void Print_List(Linklist L, int val,int n) {//n为链表长度,val为开始遍历的节点
if (!L)return;
else
{
++po;
if (po > val && po <= n) {
if (L->next!=NULL) {
cout << L->next->date << " ";
}
}
Print_List(L->next, val,n);
}
}
int k = 1;
void delNode_List(LinkList &L, int i){
if (!L || delNodeflag)return;
else
{
LinkList q;
if (i == 1){//链表头
q = L;
L = L->next;
delete q;
}
else if (k == i - 1){ //找被删除节点的前驱
q = L->next; //基本操作
L->next = q->next;
delete q;
}
else {
k++; //循环链表
delNode_List(L->next, i, e); //递归
}
}
}
void insert(int value, int location, LinkList &node)//location为插入位置
{
if (location == 0)
{
LinkList p=new ListNode;
p->data=value;
node->next = p;
return;
}
insert(value, location--, node->next);
return;
}
用迭代法双指针(剑指offer里面有)
(直接链接了)
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
//双指针法
/**
* 迭代方法
* 1 -> 2 -> 3 -> 4 -> null
* null <- 1 <- 2 <- 3 <- 4
*
*
*
*/
ListNode* reverseList(ListNode* head) {
ListNode *prev=NULL;//前指针节点
ListNode *curr=head;//当前指针节点
//每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
while(curr!=NULL){
ListNode *nexttemp=curr->next;//临时节点,暂存当前节点的下一节点,用于后移
curr->next=prev; //将当前节点指向它前面的节点
prev=curr;//前指针后移
curr=nexttemp;//当前指针后移
}
return prev;
}
};
循环链表之约瑟夫环_浦柳人的博客-CSDN博客_约瑟夫循环链表
下面这篇博客很好
(PS:cur是要删除掉的结点,这里由于是单链表结构,并且没有存cur的前置结点,所以想要删除cur,我们可以换位思考为用cur->next的值覆盖掉cur的值,然后free掉cur->next这样等同于删掉了cur)很聪明的思路!
(5条消息) 单链表实现约瑟夫环(JosephCircle) 问题_edc370的博客-CSDN博客_单链表实现约瑟夫环
(文章转载:单链表的冒泡,快排,选择,插入,归并5种排序算法详解(多图+代码实现)_嵌入式与Linux那些事的博客-CSDN博客)
谢天谢地,我终于找到了oj地方和简洁代码了 插入排序oj
class Solution {
public:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
ListNode* insertionSortList(ListNode* head)
{
ListNode* dummy = new ListNode(INT_MIN);//创建空头节点,记录已经排序好的节点
while(head)
{
ListNode* p1 = dummy; //快慢链表指针遍历
ListNode *p2 = dummy->next;//快指针,方便链表的接入与删除
ListNode *tem = head;//保存要插入的节点
head = head->next; //原链表删除要插入新有序链表的结点
while(p2 != NULL && p2->val <= tem->val)
//p2为空则遍历到新链表尾部,此时会退出循环,或者是遍历到新节点数据比原链表数据大时退出
{
p1 = p1->next;
p2 = p2->next;
}
p1->next = tem; //新的有序链表接上
tem->next = p2;
}
return dummy->next;
}
};