iOS 链表面试题

567 阅读5分钟

1.创建一个链表

创建连接的第一步就是创建一个包含数据和指针的结构体,其中数据可以是任何类型的,指针类型,是当前结构体类型的,如下图,创建一个包含一个整形的数据 (data) 和一个本身结构类型的指针 (next指针)。如下示

struct nodeList { int data; struct nodeList *next; }; 开始创建一个链表,在这里用最简单的一种方式创建,通过for 循环创建链表,更新链表的头结点和尾节点.详细步骤

创建一个空的头节点和尾节点

开始for循环,每一次都创建一个node,通过malloc进行创建

如果当前节点是空的,将第一次创建的node 赋值给头节点,并且刷新data数据(更新当前节点)

如果当前节点不是空的,将当前节点(尾节点)的next 指针指向当前创建的node,并且刷新data数据(更新当前节点)

tips:更新当前节点就是,将创建的节点赋值给(当前节点也就是尾节点)

struct nodeList* createLinkList(){ //头结点 struct nodeList *head = NULL; //尾节点,当前节点 struct nodeList *currentNode = NULL;

for (int i = 0; i < 5; i++) {
    //创建一个节点
    struct  nodeList *node = (struct nodeList*)malloc(sizeof(struct nodeList));
    node->data = i;
    if (head ==NULL){
        //赋值头结点
        head = node;
    } else {
        //尾节点next指针指向创建的节点
        currentNode->next = node;
    }
    //更新当前节点
    currentNode = node;
}
return head;

} 2.打印一个链表

打印一个链表就比较简单了,找到当前节点,调用 node->data 进行数据的打印即可,注意找到当前节点,如下图

void printNodeList(struct nodeList*node){ struct nodeList *temp = node; while (temp != NULL) { //打印当前节点 std::cout << temp->data << std::endl; temp = temp->next; } } 3.单链表反转

单链表反转的步骤

定义一个遍历指针,初始化为头结点

定义一个反转链表的头部

开始进行遍历

当前结点的next指向新链表头部 更改链表头部为当前结点 移动遍历的指针 struct nodeList *reverseLinkList(struct nodeList *node){ // 定义遍历指针,初始化为头结点 struct nodeList *p = node; // 反转后的链表头部 struct nodeList *newH = NULL; // 遍历链表 while (p != NULL) { // 记录下一个结点 struct nodeList *temp = p->next; // 当前结点的next指向新链表头部 p->next = newH; // 更改新链表头部为当前结点 newH = p; // 移动p指针 p = temp; } // 返回反转后的链表头结点 return newH; } 4.倒数第K个链表结点

第一种方法,普通计算,让倒着计算,变成正着计算,例如 // 1 2 3 4 5 6 倒数第二个 就是 5 k=2 。正数:// 6-2+1=5 正数第五个就是要求的数。

struct nodeList *backwardsGetLinkNode(struct nodeList *node,unsigned int k){ // 1 2 3 4 5 6 倒数第二个 就是 5 k=2 // 6-2+1=5 正数第五个就是要求的数

struct nodeList *countNode = node;
int  count = 0;

//链表结点个数
while (countNode != NULL){
    count ++;
    countNode = countNode->next;
}

//算出正着多少位
int number = count - k + 1;
struct nodeList *getNode = node;
struct nodeList *inNode = NULL;

int  total= 0;
//找到对应位数的结点
while (getNode != NULL) {
    total ++;
    if (number == total){
        inNode = getNode;
        return inNode;
    }
    getNode = getNode->next;
}

} 第二种方法就相对简单一些

定义两个指针,前指针指向K-1的位置 后指针指向链表头部 同时移动前后指针,当前指针指向链表的最后一个 那么对应的后指针指向的就是倒数第K的结点 struct nodeList *backwardsDoublePointerGetLinkNode(struct nodeList *node,unsigned int k){ //前指针 指向K-1的位置 struct nodeList *pHead = node; //后指针, 指向链表的头部 struct nodeList *pBehind = node; for (int i = 0; i < k-1; ++i) { pHead = pHead->next; }

//前指针和后指针同时移动,当前指针指向最后,后指针指向倒数k个
while (pHead->next != NULL){
    pHead = pHead->next;
    pBehind = pBehind->next;
}
return pBehind;

} 5.链表中环的入口结点

判断链表中是否有环需要经过以下这几个步骤。这张图可以看到大致的结果 ? ws4.sinaimg.cn/large/006tN… ? ws4.sinaimg.cn/large/006tN…

链表中是否有环 用两个指针,一个慢指针和一个快指针指向头部 慢指针一步一步的走,快指针两步两步的走。 当两个指针重合的时候,证明这个链表一定有环 环的结点是几个 当两个指针重合判断出有环的时候 让慢指针重新走到当前的位置就可以确定环的结点有几个 怎么确定环的入口结点 还是创建两个指针,指针1和指针2 指针1指向链表的头部,指针2指向头部到环结点个数的结点 指针1和指针2同时前进 6.删除链表中重复的结点

例如这种链表1->2->3->3->4->4->5 处理后为 1->2->5,说起来的就很简单了,删除重复的结点就好了,但是实现的时候,确需要。。

先创建记录当前结点前的最晚访问过的不重复的结点pPre 创建指向当前结点的pCur 创建当前结点的next结点pNext 如果当前的结点和next结点相同那么这些结点,需要删除,重新更新pCur和pNext结点,如果不相同直接更新pCur和pNext结点 tips,如果从第一个结点就是重复的话,需要特殊处理一下