写在前面
关于链表的知识(内含代码)
链表和顺序表的对比
链表的各种操作(C语言)
关于链表的知识笔者已经忘得差不多了,,,以上三篇文章基本可以应对大部分简单题。
从尾到头打印链表
题目描述
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
限制:0 <= 链表长度 <= 10000
个人题解及出现的问题(C语言)
int* reversePrint(struct ListNode* head, int* returnSize){
struct ListNode* p;
p=head;
int cnt=0;
while(p)
{
cnt++;
p=p->next;
}
*returnSize=cnt;
int * array=(int *)malloc(sizeof(int)*cnt);
int i=cnt-1;
p=head;
while(p)
{
array[i--]=p->val;
p=p->next;
}
return array;
}
问题:关于while(p)
和while(p!=null)
的使用
两者是同样作用!!!
一般结点末端都会赋值为NULL,而正常结点都会有一个地址址
网上题解(C语言)
int* reversePrint(struct ListNode* head,int*returnSize)
{
struct ListNode *p=head;
int cnt=0;
while(p)//遍历链表得到链表结点数量,之所以要重新将head赋值给p,原因是如果直接使用head,遍历结束后head的位置会到链表最后,不方便后续代码。
{
cnt++;
p=p->next;
}
*returnSize=cnt;//将数值cnt赋值给returnSize指向的地址空间,returnSize是一个地址,*returnSize是这个地址下的值。
int* ans=(int *)malloc(sizeof(int)*cnt);//动态生成cnt大小的ans数组
int i=cnt-1;//倒序输出
p=head;
while(p)
{
ans[i--]=p->val;
p=p->next;
}
return ans;
}
关于链表遍历重新将head赋值给p的问题
关于指针的使用问题
用两个栈实现队列
题目描述
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
网上思路
对于题目的解读
1、CQueue
首先初始化,没有参数,所以是 [],然后我们注意到 CQueue() 函数是没有返回值的,用 null 来表示(不要问我为什么用 null 表示。。。)
2、deleteHead
删除操作,没有参数,所以是 [],根据题意若队列中没有元素,deleteHead 操作返回 -1 ,所以输出值为 -1 。
3、appendTail
插入操作,有参数,此时是 **5 **,并且 appendTail() 函数没有返回值的,用 null 来表示。
4、appendTail
插入操作,有参数,此时是 **2 **,并且 appendTail() 函数没有返回值的,用 null 来表示。
5、deleteHead
删除操作,没有参数,所以是 [],此时队列中有元素,先进入的是 5,后进入的是 2,根据队列 先进先出 的性质,元素 5 出列,所以返回值是 5 。
6、deleteHead
删除操作,没有参数,所以是 [],此时队列中有元素,只有元素 2,所以返回值是 2 。
思路
用两个栈来实现对一个队列的插入(入栈)和删除(出栈)。 栈的特点:只能对栈顶元素进行操作。
队列:队首只能进行删除操作,队尾只能进行插入操作。
此题要求的是:队列尾部插入整数和在队列头部删除整数。
将两个栈顶分别作为队列尾部和队列头部,即需要插入整数时,将将队列尾部作为栈顶1,需要删除整数时,将队列头部作为栈顶2。
需要注意的是,每次执行插入操作时,需要检测栈2是否为空,如果不为空,需要先执行进栈1的操作。
网上题解
笔者代码实在是写的不好,以后会勤加练习的。
关于C语言编写的代码,读起来有点困难,所以写点思路放在前面。
思路:新元素入队就入栈1,出队就在将栈1元素压入栈2后,出栈2。
代码一(C语言)
typedef struct
{
int s1_cnt;//栈中元素个数
int s2_cnt;
int *s1;//栈
int *s2;
}CQueue;
CQueue* cQueueCreate()
{
CQueue *obj=(CQueue *)malloc(sizeof(CQueue));//动态申请一个大小为CQueue结构体大小的空间
obj->s1_cnt=0;//数量初始化
obj->s2_cnt=0;
obj->s1=(int *)malloc(sizeof(int)*10000);//内存空间初始化
obj->s2=(int *)malloc(sizeof(int)*10000);
return obj;
}
void cQueueAppendTail(CQueue* obj,int value)//入栈
{
obj->s1[(obj->s1_cnt)++]=value;
}
int cQueueDeleteHead(CQueue* obj)
{
if(obj->s2_cnt==0)//先检测负责删除的栈中是否有元素,如果没有,则检测入栈中是否有元素
{
if(obj->s1_cnt==0)
{
return -1;
}
while(obj->s1_cnt>0)
{
obj->s2[(obj->s2_cnt)++]=obj->s1[--(obj->s1_cnt)];
}
}
return obj->s2[--(obj->s2_cnt)];
}
void cQueueFree(CQueue* obj)
{
free(obj->s1);
free(obj->s2);
free(obj);
}
代码二(Java)
class CQueue
{
private Stack<Integer> stack1;
private Stack<Integer> stack2;
public CQueue()//初始化(实例化)两个栈
{
this.stack1=new Stack<>();
this.stack2=new Stack<>();
}
public void appendTail(int vaule)//在队列尾插入元素
{
while(!stack2.isEmpty())//stack2不为空
{
stack1.push(stack2.pop());//push:进栈;pop:出栈【将stack2栈顶元素弹出后,压入stack1中】
}
stack1.push(value);
}
public int deleteHead()//删除队首元素
{
while(!stack1.isEmpty())
{
stack2.push(stack1.pop());
}
if(stack2.isEmpty())
{
return -1;
}
return stack2.pop();
}
}