总结常见链表题型
1.链表中倒数第k个结点
题目:输入一个链表,输出链表中倒数第k个节点,为了符合大多数人的习惯,本题从1开始计数,即链表的尾巴节点是倒数第一个节点。
方法1:先遍历链表得到链表的个数n,倒数第k个节点就是n-k+1再遍历一次链表,找到第n-k+1个节点就是倒数第k个节点;这种方法遍历两次链表;
方法2:先遍历链表把链表压入一个栈,再出栈,第k次出栈就是第k个节点;
方法3:先反转链表,再遍历
方法4:定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1;第二个指针保持不动,从第k步开始,第二个指针也开始遍历,两个指针差距k-1个距离
2.两个链表升序的链表合并有递归和非递归方式。里面还有反转链表。
#ifndef _head_
#define _head_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
typedef struct ST_LinkTable
{
int data;
ST_LinkTable *next;
};
class LinkTable
{
public:
LinkTable();
~LinkTable();
void test();
//link1
bool createLinkTable(ST_LinkTable* nodes);
bool InsertTable(int data, ST_LinkTable * nodes);
bool Insert(int data, ST_LinkTable * nodes);
bool FindData(int data, ST_LinkTable * nodes);
bool FindData_info(int data, int *pos, ST_LinkTable * nodes);
int GetLength(ST_LinkTable* nodes);
bool Delete(int data, ST_LinkTable * nodes);
//link2
bool createLinkTable1(ST_LinkTable* nodes);
//merge
//递归
ST_LinkTable* mergeTable(ST_LinkTable *link1, ST_LinkTable *link2);
//非递归
ST_LinkTable* LinkTable::mergeTable1(ST_LinkTable *link1, ST_LinkTable *link2);
//反转链表
void TurnLinkTable(ST_LinkTable *link);
protected:
private:
ST_LinkTable *head;
ST_LinkTable *head1;
};
#endif
#include "head.h"
LinkTable::LinkTable()
{
}
LinkTable::~LinkTable()
{
}
bool LinkTable::createLinkTable1(ST_LinkTable* nodes)
{
nodes = (ST_LinkTable*)malloc(sizeof(ST_LinkTable));
if(nodes == NULL)
{
return false;
}
memset(nodes, 0, sizeof(ST_LinkTable));
head1 = nodes;
return true;
}
bool LinkTable::createLinkTable(ST_LinkTable* nodes)
{
nodes = (ST_LinkTable*)malloc(sizeof(ST_LinkTable));
if(nodes == NULL)
{
return false;
}
memset(nodes, 0, sizeof(ST_LinkTable));
head = nodes;
return true;
}
int LinkTable::GetLength(ST_LinkTable* nodes)
{
ST_LinkTable *temp;
temp = nodes;
int len = 0;
while(temp != NULL)
{
len++;
temp = temp->next;
}
return len;
}
bool LinkTable::FindData(int data, ST_LinkTable * nodes)
{
ST_LinkTable *temp = nodes;
while(temp != NULL)
{
if(temp->data == data)
{
return true;
}
temp = temp->next;
}
return false;
}
bool LinkTable::Insert(int data, ST_LinkTable * nodes)
{
ST_LinkTable* temp = nodes;
int depth = GetLength(nodes) - 1;
//find insert nodes
int len = 0;
while((temp != NULL) && (len < depth))
{
temp = temp->next;
len++;
}
//Malloc new node
ST_LinkTable* node = (ST_LinkTable*)malloc(sizeof(ST_LinkTable));
if(node == NULL)
{
return false;
}
memset(node, 0, sizeof(ST_LinkTable));
node->next = NULL;
temp->next = node;
temp->data = data;
}
bool LinkTable::InsertTable(int data, ST_LinkTable * nodes)
{
//find data
if(FindData(data, nodes))
{
//find data
printf("Already Exists\n");
return false;
}
else
{
//not find data Begin Insert
Insert(data, nodes);
}
}
bool LinkTable::FindData_info(int data, int *pos, ST_LinkTable * nodes)
{
bool ret = false;
ST_LinkTable *temp = nodes;
int len = GetLength(nodes) - 1;
int depth = 0;
while((temp != NULL) && (depth < len))
{
if(temp->data == data)
{
ret = true;
break;
}
depth++;
}
*pos = depth;
return ret;
}
bool LinkTable::Delete(int data, ST_LinkTable * nodes)
{
bool ret = false;
ST_LinkTable *temp = nodes;
ST_LinkTable *node;
ST_LinkTable *delete_node;
int pos = 0;
ret = FindData_info(data, &pos, nodes);
if(ret == false)
{
return ret;
}
int len = 0;
if(pos == 0)
{
//head
delete_node = head;
head = head->next;
free(delete_node);
}
else
{
while((temp != NULL) && (len < pos))
{
temp = temp->next;
}
node = temp->next->next;
temp = node;
delete_node = temp->next;
free(delete_node);
}
}
void LinkTable::test()
{
createLinkTable(head);
InsertTable(1,head);
InsertTable(2,head);
InsertTable(3,head);
InsertTable(4,head);
InsertTable(5,head);
createLinkTable1(head1);
InsertTable(2,head1);
InsertTable(4,head1);
InsertTable(6,head1);
InsertTable(8,head1);
InsertTable(10,head1);
TurnLinkTable(head);
//ST_LinkTable* temp = mergeTable(head,head1);
ST_LinkTable* temp1 = mergeTable1(head,head1);
}
//合并链表 有两种 一种通过递归。另一种非递归方式
//递归方式
ST_LinkTable* LinkTable::mergeTable(ST_LinkTable *link1, ST_LinkTable *link2)
{
if(link1 == NULL)
{
return link2;
}
if(link2 == NULL)
{
return link1;
}
ST_LinkTable * temp = NULL;
if(link1->data < link2->data)
{
temp = link1;
temp->next = mergeTable(link1->next, link2);
}
else
{
temp = link2;
temp->next = mergeTable(link1, link2->next);
}
return temp;
}
//非递归方式 合并链表
ST_LinkTable* LinkTable::mergeTable1(ST_LinkTable *link1, ST_LinkTable *link2)
{
if(link1 == NULL)
{
return link2;
}
if(link2 == NULL)
{
return link1;
}
ST_LinkTable* temp = (ST_LinkTable*)malloc(sizeof(ST_LinkTable));
ST_LinkTable* node = temp;
while((link1 != NULL) && (link2 != NULL))
{
if(link1->data < link2->data)
{
node->next = link1;
link1 = link1->next;
}
else
{
node->next = link2;
link2 = link2->next;
}
node = node->next;
}
if(link1 != NULL)
{
node->next = link1;
}
if(link2 != NULL)
{
node->next = link2;
}
return temp->next;
}
//
void LinkTable::TurnLinkTable(ST_LinkTable *link)
{
ST_LinkTable *temp;
ST_LinkTable *ph;
ST_LinkTable *news = NULL;
ph = link;
while(ph != NULL)
{
temp = ph->next;
//颠倒 节点
//原来是1->2->3->4->5 颠倒节点 1<-2<-3<-4<-5 把1的节点用临时变量保存,存在2的下一个上。循环然后在3的下一个上存2的节点。依次类推就成反转了。
//
ph->next = news;
news = ph;
ph = temp;
}
int a = 0;
return ;
}
3.反转链表
4.删除倒数第K个元素
方法1:遍历第一遍确定位置,第二遍开始删除。
方法2:用两个指针。第一个指针不动,下一个指针走倒数K个节点的个数。如果不是尾节点,循环直到找到倒数K节点。
5.删除链表中重复节点