数据结构-------链表(递归)操作

希望能继续坚持下去

这篇博客应该是为菜鸡(本人)听课听的疑惑点进行知识梳理(如有错误请指正)

数据结构中的链表估计很多人会觉得简单,我也是怕记不住所以就尝试整理一下笔记吧

目录

1.创建链表(初始化)

2.统计链表节点

3.打印链表(正向or反向)

4.选择排序(递归)

5.查找单链表某个节点开始后的所有节点(直至表尾)

6.删除节点(删除单链表的第i个元素)

7.在单链表的第i个位置插入元素e

8.链表反转

9.约瑟夫

10.插入排序



1.创建链表(初始化)

 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个节点
   }
}

2.统计链表节点

int countList(LinkList L){ //传入的L是形参,不影响原链表    
      if (L == NULL)
          return 0;     //递归结束条件,递归基
      else 
          return countList(L->next) + 1;    //否则继续指向下一个节点,表长加1
 }

3.打印链表(正向or反向)

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 <

4.选择排序(递归)

【选择排序很像人一般的思维,先找最小的,然后找第二小的……………………一直排下去】

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;
    }
};

5.查找单链表某个节点开始后的所有节点(直至表尾)

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);
	}

	
}

6.删除节点(删除单链表的第i个元素)

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); //递归
         }
     }
}

7.在单链表的第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;
}

8.链表反转

 用迭代法双指针(剑指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;
    }
};

9.约瑟夫

循环链表之约瑟夫环_浦柳人的博客-CSDN博客_约瑟夫循环链表

下面这篇博客很好

(PS:cur是要删除掉的结点,这里由于是单链表结构,并且没有存cur的前置结点,所以想要删除cur,我们可以换位思考为用cur->next的值覆盖掉cur的值,然后free掉cur->next这样等同于删掉了cur)很聪明的思路!

(5条消息) 单链表实现约瑟夫环(JosephCircle) 问题_edc370的博客-CSDN博客_单链表实现约瑟夫环

10.插入排序

(文章转载:单链表的冒泡,快排,选择,插入,归并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;
    }
};

你可能感兴趣的:(数据结构(笔记),链表,数据结构)