一、线性表
1.链表
1.1 链表原地反转
#include <iostream>
using namespace std;
typedef struct node
{
int data;
struct node *next;
} NODE;
NODE *createlist( int n )
{
NODE *head = NULL;
while ( n-- )
{
NODE *p = new NODE;
cin >> p->data;
p->next = head;
head = p;
}
return head;
}
void print( NODE *h )
{
NODE *p;
for (p = h; p;p=p->next)
{
cout << p->data;
if( p->next != NULL)
cout << ' ';
}
cout << endl;
}
void del( NODE *h)
{
NODE *p;
do
{
p = h;
h = p->next;
delete p;
} while (h != NULL);
}
int main()
{
int t;
cin >> t;
while ( t-- )
{
int n;
cin >> n;
NODE *head;
head = createlist(n);
print(head);
del(head);
}
return 0;
}
1.2 单链表节点交换
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node() { next = NULL; }
Node(int x) : data(x) { next = NULL; }
};
class LinkList
{
public:
Node *head;
LinkList() { head = new Node(0); }
void CreateList(int arr[], int n)
{
while (--n >= 0)
{
Node *temp = new Node(arr[n]);
temp->next = head->next;
head->next = temp;
head->data++;
}
}
bool Swap(int pos1, int pos2)
{
if (pos1 < 1 || pos1 > head->data ||
pos2 < 1 || pos2 > head->data)
return false;
Node *p = head;
while (--pos1)
{
p = p->next;
pos2--;
}
Node *q = p;
while (--pos2)
{
q = q->next;
}
//此时p为第一个需要交换节点的前驱,q为第二个需要交换节点的前驱
//第一步,交换前驱
Node *temp = p->next; //先用临时指针指向第一个需要交换节点
p->next = q->next; //p的next变为第二个节点
q->next = temp; //q的next变为第一个节点
//第二步,交换后继
temp = q->next->next; //先用临时指针指向第一个需要交换节点的后继节点
q->next->next = p->next->next; //第一个节点的next变为第二个节点的后继节点
p->next->next = temp; //第二个节点的后继节点变为第一个节点的后继节点
return true;
}
void Show()
{
Node *p = head->next;
while (p)
{
cout << p->data << ' ';
p = p->next;
}
cout << endl;
}
};
int main(int argc, char const *argv[])
{
int n;
cin >> n;
int *arr = new int[n];
for (int i = 0; i < n; i++)
cin >> arr[i];
LinkList ll;
ll.CreateList(arr, n);
ll.Show();
delete[] arr;
int t = 2;
while (t--)
{
int pos1, pos2;
cin >> pos1 >> pos2;
if (ll.Swap(pos1, pos2))
ll.Show();
else
cout << "error" << endl;
}
return 0;
}
1.3 双向链表祖玛
#include <iostream>
using namespace std;
class Node
{
public:
char data;
Node *front, *next;
Node() { front = next = NULL; }
Node(char ch) : data(ch) { front = next = NULL; }
};
class LinkList
{
public:
Node *head;
int length;
LinkList() : length(0) { head = new Node('-'); }
void CreateList(string str)
{
while (!str.empty())
{
Node *temp = new Node(str.back());
str.pop_back();
if (head->next)
head->next->front = temp;
temp->next = head->next;
head->next = temp;
temp->front = head;
length++;
}
}
void Insert(int pos, char ch)
{
Node *p = head;
while (pos--)
{
p = p->next;
}
Node *temp = new Node(ch);
temp->front = p;
temp->next = p->next;
if (p->next)
p->next->front = temp;
p->next = temp;
length++;
ZM(p->next);
}
void DeleteNode(Node *p, int n) //传入需要删除的第一个位置的前一个位置与删除个数
{
while (n--) //删除n个p->next节点
{
Node *temp = p->next;
p->next = p->next->next;
if (p->next)
p->next->front = p;
delete temp;
length--;
}
//确保传入的不是头节点,而是其余有值的节点
if (p->front != NULL)
ZM(p);
else if (p->next)
ZM(p->next);
}
void ZM(Node *p)
{
int n = 1; //记录需要删除的节点个数
Node *q = p; //在p的前后移动寻找相同值
Node *temp; //指向需要开始删除节点的前一个节点的指针
while (q->front)
{
if (q->front->data == p->data)
{
n++;
q = q->front;
}
else
break;
}
temp = q->front;
q = p;
while (q->next)
{
if (q->next->data == p->data)
{
n++;
q = q->next;
}
else
break;
}
if (n >= 3)
DeleteNode(temp, n);
}
void Show()
{
Node *p = head->next;
while (p)
{
cout << p->data;
p = p->next;
}
if (length)
cout << endl;
else
cout << head->data << endl;
}
};
int main(int argc, char const *argv[])
{
string str;
cin >> str;
LinkList ll;
ll.CreateList(str);
//ll.Show();
int t;
cin >> t;
while (t--)
{
int pos;
char ch;
cin >> pos >> ch;
ll.Insert(pos, ch);
ll.Show();
}
return 0;
}
二、串
1.字符串翻转
这里收录两种简便方法
//方法一:利用algorithm头文件中的reverse函数翻转字符串
#include <algorithm>
string s1;
reverse(s1.begin(), s1.end());
//方法二:利用string自带的assign函数
string s1, s2;
s2.assign(s1.rbegin(), s1.rend());
2.KMP算法
#include <iostream>
using namespace std;
void SetNext(int *next, string pat)
{
next[0] = 0;
int len = 0;
int i = 1;
while (i < pat.length())
{
if (pat[len] == pat[i])
{
len++;
next[i++] = len;
}
else
{
if (len > 0)
len = next[len - 1]; //让len等于前一个的
else
next[i++] = len; //就是零
}
}
}
void MoveNext(int *next, int n)
{
for (int i = n - 1; i > 0; i--)
next[i] = next[i - 1];
next[0] = -1;
}
void KMP(string text, string pattern)
{
int *next;
next = new int[pattern.length()];
SetNext(next, pattern);
MoveNext(next, pattern.length());
int m = text.length();
int n = pattern.length();
int i = 0, j = 0;
while (i < m)
{
if (j == n - 1 && text[i] == pattern[j])
{
cout << "FOUND at " << i - j << endl;
j = next[j];
i++;
}
if (text[i] == pattern[j])
{
i++;
j++;
}
else
{
j = next[j];
if (j == -1)
{
i++;
j++;
}
}
}
delete[] next;
}
int main()
{
string text;
string pattern;
cin >> text >> pattern;
KMP(text, pattern);
return 0;
}
3.最长重复子串
求串的最长重复子串长度(子串不重叠)。例如:abcaefabcabc的最长重复子串是串abca,长度为4。
#include <iostream>
using namespace std;
int FindMaxSubStr(string str)
{
for (int len = str.length() / 2; len > 0; len--)
{
for (int i = 0; i < str.length() - len; i++)
{
string s1 = str.substr(i, len);
string s2 = str.substr(i + len);
if (s2.find(s1) != string::npos)
return len;
}
}
return -1;
}
int main(int argc, char const *argv[])
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
cout << FindMaxSubStr(str) << endl;
}
return 0;
}
3.子串循环问题
给定一个字符串,求需要添加至少几个字符到字符串末尾才能使得整个字符串串由某一个不为本身的子串循环构成?
如"abca",添加"bc"后构成"abcabc",其由子串"abc"循环构成;也可以添加"abca"后构成"abcaabca",其由子串"abca"循环构成,相比之下"bc"只有2个字符,添加的字符量最少。
#include <iostream>
using namespace std;
void SetNext(string p, int next[])
{
next[0] = 0;
int len = 0, i = 1;
while (i < p.length())
{
if (p[i] == p[len])
{
len++;
next[i++] = len;
}
else
{
if (len)
len = next[len - 1];
else //len=0
next[i++] = len;
}
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
int *next = new int[str.length()];
SetNext(str, next);
int len = str.length();
int cirlen = len - next[len - 1];
int add = cirlen - len % cirlen;
if (cirlen != len && len % cirlen == 0)
add = 0;
cout << add << endl;
delete[] next;
}
}