更新链表题目
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
|
||||
## 开源项目中用到的算法
|
||||
|
||||
数据结构往往是一个项目系统的核心,理解项目的数据结构和算法,才能真正理解项目的工作原理。这里聊聊常用`开源系统`中用到的数据结构和算法。
|
||||
数据结构往往是一个项目系统的核心,理解项目的数据结构和算法,才能真正理解项目的工作原理。这里聊聊常用`开源项目`中用到的数据结构和算法。
|
||||
|
||||
|
||||
每一条说清楚:
|
||||
@@ -12,7 +13,7 @@
|
||||
|
||||
### 项目简介
|
||||
|
||||
YYCache 是iOS系统上一套线程安全的Key-Value缓存实现,使用Objective-C语言实现。YYCache使用双向链表+hash表结构实现。
|
||||
YYCache 是iOS系统上一套线程安全的Key-Value缓存实现,使用Objective-C语言实现。YYCache使用双向链表队列+hash表结构实现。
|
||||
|
||||
### 用到的算法介绍
|
||||
|
||||
@@ -45,8 +46,8 @@ YYCache 是iOS系统上一套线程安全的Key-Value缓存实现,使用Object
|
||||
BOOL _releaseAsynchronously;
|
||||
}
|
||||
```
|
||||
_dic 就是存储缓存节点的hash结构。
|
||||
|
||||
_dic 就是存储缓存节点的hash结构
|
||||
_head 指向链表的头部,_tail指向链表的尾部,组成一个队列结构
|
||||
|
||||
## [cocos2d-objc](https://github.com/cocos2d/cocos2d-objc)
|
||||
|
||||
|
||||
+72
-27
@@ -1,21 +1,69 @@
|
||||
|
||||
##堆和栈
|
||||
|
||||
|
||||
栈的数据结构结构
|
||||
|
||||
```
|
||||
typede int Value;
|
||||
typedef struct Entry{
|
||||
Entry *next;
|
||||
Value value;
|
||||
}Entry;
|
||||
|
||||
typedef struct Stack{
|
||||
Entry *head;/*添加和删除都在这个节点指针上*/
|
||||
int length;
|
||||
int capacity;
|
||||
}Stack;
|
||||
|
||||
Stack create(unsigned int size);
|
||||
void push(Stack,Value);
|
||||
Value pop(Stack);
|
||||
|
||||
```
|
||||
|
||||
队列的数据结构结构
|
||||
|
||||
```
|
||||
typede int Value;
|
||||
typedef struct Entry{
|
||||
Entry *next;
|
||||
Value value;
|
||||
}Entry;
|
||||
|
||||
typedef struct Queue{
|
||||
Entry *front;/*删除都在这个节点指针上*/
|
||||
Entry *rear;/*添加在这个节点指针上*/
|
||||
int length;
|
||||
}Stack;
|
||||
|
||||
void enqueue(Queue,Value);
|
||||
void dequeue(Queue);
|
||||
```
|
||||
|
||||
|
||||
这里的题目是有关栈和队列的问题。
|
||||
|
||||
|
||||
#### 循环队列中元素个数
|
||||
|
||||
如果用一个循环数组q[0..m-1]表示队列时,该队列只有一个队列头指针front不设队列尾指针rear,求这个队列中从队列头到队列尾的元素个数(包含队列头、队列尾)
|
||||
如果用一个循环数组q[0..m-1]表示队列时,该队列只有一个队列头指针front,不设队列尾指针rear,求这个队列中从队列头到队列尾的元素个数(包含队列头、队列尾)
|
||||
|
||||
分析:
|
||||
|
||||
有rear指针时:
|
||||
|
||||
if rear>front count = rear-front+1
|
||||
else count = rear-front+m+1
|
||||
综合,count = (rear-front+m+1)%m
|
||||
|
||||
不用rear指针的话:
|
||||
数据结构中加一个 int count来计数。
|
||||
```
|
||||
if (rear>front)
|
||||
count = rear-front+1
|
||||
else
|
||||
count = rear-front+m+1
|
||||
```
|
||||
综合: `count = (rear-front+m+1)%m`
|
||||
|
||||
不用rear指针的话:
|
||||
数据结构中加一个 `int count`来计数。
|
||||
|
||||
|
||||
|
||||
@@ -38,46 +86,43 @@ a < f(top),把 a push 到 辅助栈中
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### 栈的push、pop序列
|
||||
|
||||
题目:输入两个整数序列。其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序。为了简单起见,我们假设push序列的任意两个整数都是不相等的。
|
||||
|
||||
比如输入的push序列是1、2、3、4、5,那么4、5、3、2、1就有可能是一个pop系列。
|
||||
比如输入的push序列是[1、2、3、4、5] ,那么[4、5、3、2、1]就有可能是一个pop序列
|
||||
|
||||
因为可以有如下的push和pop序列:
|
||||
push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,
|
||||
这样得到的pop序列就是4、5、3、2、1。
|
||||
但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。
|
||||
【push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop】
|
||||
|
||||
这样得到的pop序列就是【4、5、3、2、1】。
|
||||
|
||||
但序列【4、3、5、1、2】就不可能是push序列【1、2、3、4、5】的pop序列。
|
||||
|
||||
|
||||
这里只是要判断是不是pop序列,并没有要求所有的pop序列
|
||||
需要一个辅助栈(需要一个写好的栈结构辅助,如果是C语言,还要包装一个栈结构)
|
||||
|
||||
对序列A中的A[0]入栈,比较B[0]
|
||||
如果不相等,A[1]入栈
|
||||
直到A[i] = B[0]
|
||||
栈顶出栈,开始匹配B[1]
|
||||
如果A[i-1]!=B[1],那就继续入栈A[i+1]
|
||||
1. 对序列A中的A[0]入栈,比较B[0]
|
||||
2. 如果不相等,A[1]入栈
|
||||
3. 直到A[i] = B[0]
|
||||
4. 栈顶出栈,开始匹配B[1]
|
||||
5. 如果A[i-1]!=B[1],那就继续入栈A[i+1]
|
||||
|
||||
循环往复~
|
||||
如果最后,栈为空,就是一个pop序列;如果栈不为空,或者B数组都没有遍历到尾部,就肯定不是pop序列了
|
||||
6 .循环往复~
|
||||
7. 如果最后,栈为空,就是一个pop序列;如果栈不为空,或者B数组都没有遍历到尾部,就肯定不是pop序列了
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 颠倒栈
|
||||
#### 颠倒栈
|
||||
|
||||
题目:用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5},1在栈顶。颠倒之后的栈为{5, 4, 3, 2, 1},5处在栈顶。
|
||||
|
||||
思路一:所有元素pop出来,放到一个数组里,然后在从第一个元素开始入栈,空间复杂度需要 O(N)
|
||||
|
||||
思路一:所有元素pop出来,放到一个数组里,然后在从第一个元素开始入栈,空间复杂度需要 O(N)
|
||||
思路二: 递归方法。把栈看出2部分 :1 和 {2,3,4,5} , 把栈{2,3,4,5}颠倒过来,然后把1放到底部,那整个栈就颠倒过来了。
|
||||
|
||||
```
|
||||
void reverseStack(){
|
||||
|
||||
void reverseStack(){
|
||||
stack.pop();
|
||||
reverseStack();
|
||||
addTopToStackBottom();
|
||||
|
||||
+10
-2
@@ -10,7 +10,6 @@
|
||||
* 子串
|
||||
|
||||
|
||||
|
||||
#### 翻转句子中单词的顺序
|
||||
|
||||
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。
|
||||
@@ -18,7 +17,7 @@
|
||||
例如输入“I am a student.”,则输出“student. a am I”。
|
||||
|
||||
```
|
||||
char *revert(const char *source,char *dest);
|
||||
char *revert_by_word(const char *source,char *dest);
|
||||
```
|
||||
|
||||
思路一:反向拷贝
|
||||
@@ -35,6 +34,15 @@ b = a - b;
|
||||
a = a - b;
|
||||
```
|
||||
|
||||
最终示例代码:
|
||||
|
||||
```
|
||||
char *revert_by_word(const char *source,char *dest){
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
类似的题目还有:
|
||||
|
||||
不开辟用于交换数据的临时空间,如何完成字符串的逆序(在技术一轮面试中,有些面试官会这样问)
|
||||
|
||||
+3
-7
@@ -136,8 +136,7 @@ struct ListNode
|
||||
输入一个链表的头结点,从尾到头反过来输出每个结点的值。链表结点定义如下:
|
||||
|
||||
```
|
||||
struct ListNode
|
||||
{
|
||||
struct ListNode{
|
||||
int m_nKey;
|
||||
ListNode* m_pNext;
|
||||
};
|
||||
@@ -152,11 +151,9 @@ struct ListNode
|
||||
题目:给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:
|
||||
|
||||
```
|
||||
struct ListNode
|
||||
{
|
||||
struct ListNode{
|
||||
int m_nKey;
|
||||
ListNode* m_pNext;
|
||||
|
||||
};
|
||||
|
||||
//函数的声明如下:
|
||||
@@ -174,8 +171,7 @@ void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);
|
||||
有双向循环链表结点定义为:
|
||||
|
||||
```
|
||||
struct node
|
||||
{
|
||||
struct node{
|
||||
int data;
|
||||
struct node *front,*next;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user