前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode刷题总结 -- 链表篇

LeetCode刷题总结 -- 链表篇

作者头像
看、未来
发布2020-08-26 11:24:44
4460
发布2020-08-26 11:24:44
举报

本篇将重点讲链表的基本操作(增删查改)

做链表的题目,总会遇到各种各样莫名其妙的问题,刚刚又解决一个卡了一下午的,原因是用于插入的节点是在循环之外分配空间的(为了省空间),之后没做清理,导致问题,而我的聚焦点却一直在:为什么使用了

代码语言:javascript
复制
temp = head; 
···
temp = temp->next;
··· 
return head;

之后,head居然也跟着偏了?不应该啊。

一切的一切,都源于对基础的把控不够。

所以,本篇我将致力于尽可能的剖析 “增删查改” 这几个基础到尘埃的函数。

如果觉得自己已经深刻领悟了这些操作的小伙伴,可以先去干别的事情了。

public.h

代码语言:javascript
复制
//这是一个通用链表基本操作的头文件

#include <stdio.h>	
#include <conio.h>
#include <stdlib.h>
#include <memory.h>
#include <assert.h>

//节点数据结构体
typedef struct test
{	

	char name[12];		//名字
	char pwd[8];		//密码
	int number;			//编号
	int flag;			//区分管理员和用户	// 	0 超级管理员 1 管理员  2 普通用户 3 屏蔽用户
	int money;			//仅用户有存款,初始500
	
} TEST_T;

//如果不多来一个数据域,怎么能体现出通用链表的优势
typedef struct reported
{
	int amount;//交易金额
	int rflag; //交易方式	1、存款 2、取款 3、转账转出 4、转账转入
	int lastmoney;//余额
	int lastmoney2;//收款者的余额
	int number1;//付款账户
	int number2;//入款账户
	char time[12];//操作时间
} REPORT_T;


//节点描述结构体
typedef struct point
{
	void *pData;				//指向数据域
	struct point *next;			//指向下一个节点
	
} POINT_T;

POINT_T * head ;
extern POINT_T * head;

my_list.c 概览

代码语言:javascript
复制
//创建结点/
POINT_T * creat(void *data )	//创建一个属于结构体point的函数,
//传入结构体test的指针便可以用以操作test变量,
{								//并返回一个point的指针用以操作point函数
	POINT_T *p=NULL;
	
	p=(POINT_T *)malloc(sizeof(POINT_T));
	if(p==NULL)
	{
		gotoxy(36,14);	
		printf("申请内存失败");
		exit(-1);
	}
	memset(p,0,sizeof(POINT_T));
	
	p->pData=data;
	p->next=NULL;
	return p;
}

/新增节点///
void add(POINT_T * the_head,void *data )				//这里的data不会和上面那个冲突吗?
{
	POINT_T * pNode=the_head;
	POINT_T *ls=creat(data);
	//后面再接上一个
	while (pNode->next != NULL)							//遍历链表,找到最后一个节点
	{
		pNode=pNode->next;
	}
	pNode->next=ls;			//ls 临时
}

删除节点/
void Del (POINT_T * the_head, int index)
{
	POINT_T *pFree=NULL;
	
	POINT_T *pNode=the_head;
	int flag=0;
	while (pNode->next!=NULL)
	{
		if(flag==index-1)
		{
			pFree=pNode->next;				//再指向数据域就爆了
			pNode->next=pNode->next->next;
			free(pFree->pData);
			free(pFree);
			break;
		}
		pNode=pNode->next;
		flag++;	
	}	
}

///计算节点数
int Count(POINT_T * the_head)
{
	int count=0;
	POINT_T *pNode1=the_head;
	while (pNode1->next!=NULL)
	{
		if(pNode1->next!=NULL)
		{
			pNode1=pNode1->next;
			count++;
		}		
	}	
	return count;
}

/查找固定节点数据//
POINT_T * find(POINT_T *the_head,int index)
{
	int f=0;
	POINT_T *pNode=NULL;
	int count=0;
	pNode=the_head;
	
	count=Count(the_head);
	
	if(count<index)	
		printf("find nothing");
	
	while(pNode->next!=NULL)
	{
		if(index==f)
			return pNode;
		pNode=pNode->next;
		f++;		
	}
}

创建节点

代码语言:javascript
复制
//创建结点/
POINT_T * creat(void *data )	//创建一个属于结构体point的函数,
								//传入结构体test的指针便可以用以操作test变量,
{								//并返回一个point的指针用以操作point函数
	POINT_T *p=NULL;			//每一个新节点都要置为空
	p=(POINT_T *)malloc(sizeof(POINT_T));//为新节点开辟空间
	if(p==NULL)
	{
		printf("申请内存失败");
		exit(-1);
	}
	memset(p,0,sizeof(POINT_T));//再次确保新节点清理干净了
	
	p->pData=data;				//再为新节点赋值
	p->next=NULL;				//将新节点置为无后
	return p;					//返回此节点
}

新增节点

代码语言:javascript
复制
/新增节点///
void add(POINT_T * the_head,void *data )				//这里的data不会和上面那个冲突吗?
{
	POINT_T * pNode=the_head;							//pNode和head指向同一块内存地址,但是pNode和head是互相独立的
	POINT_T *ls=creat(data);
	//后面再接上一个
	while (pNode->next != NULL)							//遍历链表,找到最后一个节点
	{
		pNode=pNode->next;								//pNode和head是互相独立的,所以此举并不会对head指向的位置进行修改
	}
	pNode->next=ls;			//ls 临时
}

指定位置插入节点

代码语言:javascript
复制
/插入节点///
void add(POINT_T * the_head,int index,void *data )				//这里的data不会和上面那个冲突吗?
{
	POINT_T * pNode=the_head;							//pNode和head指向同一块内存地址,但是pNode和head是互相独立的
	POINT_T *ls=creat(data);
	//后面再接上一个
	int i = 0;
	while (pNode->next != NULL && i<index)	
	{
		pNode=pNode->next;								//pNode和head是互相独立的,所以此举并不会对head指向的位置进行修改
	}
	ls->next = pNode->next;	//先将链表后部分接到新节点后面
	pNode->next=ls;			//再往链表前部分接上新节点
}

删除节点

代码语言:javascript
复制
删除节点/
void Del (POINT_T * the_head, int index)
{
	POINT_T *pFree=NULL;
	
	POINT_T *pNode=the_head;
	int flag=0;
	while (pNode->next!=NULL)
	{
		if(flag==index-1)
		{
			pFree=pNode->next;				//再指向数据域就爆了
			pNode->next=pNode->next->next;
			free(pFree->pData);				//释放数据域
			free(pFree);					//释放指针域
			break;
		}
		pNode=pNode->next;
		flag++;	
	}	
}

将这些函数一个一个分开写就不容易出错,但是合在一起的时候,问题就要出来了:

问题代码1:

代码语言:javascript
复制
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(NULL) {}
    
};

ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {    //传进来的参数不为空
    ListNode* temp1 = list1;
    ListNode* temp2 = list2;
	
	//ListNode* temp3 = new ListNode(0);	这要是放这里了问题就大了
	
    while (temp1->next != NULL && temp2!= NULL) {
        if (temp1->next->val >= temp2->val) {
            ListNode* temp3 = new ListNode(0);  //这个要放在这里,新插入的节点一定要是新鲜的
            temp3->val = temp2->val;  //这里要注意,对新指针赋值,一定要只赋值给单指针,不要把后面一串全弄过去,会出现环状链表
            temp3->next = temp1->next;
            temp1->next = temp3;
            temp2 = temp2->next;
        }
        temp1 = temp1->next;
    }
    if (temp2!= NULL) {
        temp1->next = temp2;
    }
    return list1;
}

问题代码2

这就是一个典型的成环链表。

代码语言:javascript
复制
//ListNode* reverseList(ListNode* head)
//{
//    ListNode* node_temp;
//    ListNode* new_head;
//
//    node_temp = head;
//    //遍历一个节点,就把它拿下来放到头去
//    while (head->next != NULL)
//    {
//        //先考虑只又两个节点的情况 
//        head = head->next;
//        new_head = head;
//        new_head->next = node_temp;
//        node_temp = new_head;
//    }
//    return new_head;
//}

得出经验

链表的题目吧,可以把上面那些拆分好的函数直接拿去用,将复杂的逻辑拆解之后就没那么烦了。

没必要非要挤在一块儿写

翻转链表

代码语言:javascript
复制
ListNode* reverseList(ListNode* head) 
{
    ListNode* node_temp = NULL; //这里设为NULL
    ListNode* new_head = NULL;   //链栈的头

    //遍历一个节点,就把它拿下来放到头去
    while (head != NULL)
    {
        node_temp = head;   //先将节点取出
        //先考虑只又两个节点的情况 
        head = head->next;  //这个不放这里又成环了

        node_temp->next = new_head;
	//刚开始相当于是置空的,因为前面并没有分配空间,而是NULL,这也是这个算法不成环的保证
        new_head= node_temp;
    }
    return new_head;
}    

关于链表成环的处理办法

链表误成环

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本篇将重点讲链表的基本操作(增删查改)
  • public.h
  • my_list.c 概览
  • 创建节点
  • 新增节点
  • 指定位置插入节点
  • 删除节点
  • 问题代码1:
  • 问题代码2
  • 得出经验
  • 翻转链表
  • 关于链表成环的处理办法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档