链表
链表应该是面试时被提及的最频繁的数据结构。链表是由指针把若干个结点连接成链状结构。链表的创建,插入结点,删除结点等操作都只需要20行左右的代码就能实现,比较适合面试。
题目:输入一个链表的头结点,从尾到头 反过来打印出每个结点的值。要求不改变链表的结构。
思路:
通过递归来实现反过来输出链表,当访问到一个结点的时候,先递归输出它后面的结点,在输出结点本身,这样就可以输出反过来的链表了
单链表:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//单链表结点翻转 - 递归
typedef struct ListNode {
int key;
struct ListNode * next;
}ListNode;
#define LISTSIZE 1000
ListNode ListNodePool[LISTSIZE];//创建结点池,在需要的时候直接获取,比new ListNode时间快
int NodeNum = 0;
//nil是表头,NIL是它的指针,绑定一下
ListNode nil;
ListNode * NIL;
ListNode * getNewNode(){
return &ListNodePool[NodeNum++];
}
void listInit(){
NIL = &nil;
NIL->next = NULL;
NIL->key = 0;
}
//dstNode是一个指向指针的指针,,如果插入的链表是一个空链表的时候,新插入的结点就是链表的头指针,这时会
//改变头指针,因此必须吧dstNode参数设置为指向指针的指针,否则在这个函数范围外,dstNode 仍然是一个空指针。
void singleListInsterAfter(ListNode ** dstNode, ListNode * NewNode) {
if (*dstNode == NULL) {
*dstNode = NewNode;
}
else {
ListNode * tempNode = * dstNode;
while (tempNode ->next != NULL) {//找到尾结点
tempNode = tempNode->next;
}
tempNode->next = NewNode;
}
}
int data[LISTSIZE];
void showList(){
ListNode * curNode = NIL->next;
while (curNode != NULL){
printf("%d ", curNode->key);
curNode = curNode->next;
}
printf("\n");
}
void PrintListReversingling_Recursively(ListNode * pHead) {
if (pHead != NULL) {
if (pHead->next != NULL) {
PrintListReversingling_Recursively(pHead->next);
}
printf("%d ", pHead->key);
}
}
void main(){
freopen("input.txt", "r", stdin);
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++){
scanf("%d", &data[i]);
//printf("%d ", data[i]);
}
printf("\n");
listInit();
for (int i = 0; i < N; i++){
ListNode * node = getNewNode();
node->key = data[i];
singleListInsterAfter( &NIL->next, node);
}
//按照插入的顺序输出
showList();
//翻转单链表
ListNode * pHead = NIL;
PrintListReversingling_Recursively(pHead->next);
}
双链表:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//LinkedList API
//双链表结点 从尾到头打印链表
typedef struct ListNode {
int key;
struct ListNode * next;
struct ListNode * prev;
}ListNode;
#define LISTSIZE 1000
ListNode ListNodePool[LISTSIZE];//创建结点池,在需要的时候直接获取,比new ListNode时间快
int NodeNum = 0;
//nil是表头,NIL是它的指针,绑定一下
ListNode nil;
ListNode * NIL;
ListNode * getNewNode(){
return &ListNodePool[NodeNum++];
}
void listInit(){
NIL = &nil;
NIL->next = NIL;
NIL->prev = NIL;
NIL->key = 0;
}
void listInsertAfter(ListNode * dstNode, ListNode * NewNode){
NewNode->next = dstNode->next;
NewNode->prev = dstNode;
dstNode->next = NewNode;
NewNode->next->prev = NewNode;
}
//end of LinkedList API
int data[LISTSIZE];
void showList(){
ListNode * curNode = NIL->next;
while (curNode != NIL){
cout << curNode->key << " ";
curNode = curNode->next;
}
cout << endl;
}
void PrintListReversingling_Recursively(ListNode * pHead) {
if (pHead != NIL) {
if (pHead->next != NIL) {
PrintListReversingling_Recursively(pHead->next);
}
printf("%d ", pHead->key);
}
}
void main(){
freopen("input.txt", "r", stdin);
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++){
scanf("%d", &data[i]);
//printf("%d ", data[i]);
}
printf("\n");
listInit();
for (int i = 0; i < N; i++){
ListNode * node = getNewNode();
node->key = data[i];
listInsertAfter(NIL->prev, node);//NIL->prev 尾节点
}
//按照插入的顺序输出
ListNode * curNode = NIL->next;
while (curNode != NIL){
cout << curNode->key << " ";
curNode = curNode->next;
}
cout << endl;
ListNode * pHead = NIL;
PrintListReversingling_Recursively(pHead->next);
}
a. 创建:10个随机的数字,将其插入到链表中
b. 遍历:将这10个数字按照插入顺序输出
c. 添加、删除:使用插入排序的方法调整链表节点的顺序,使得节点按值的升序排列
//LinkedList API
//双向链表结点
typedef struct ListNode {
int key;
struct ListNode * next;
struct ListNode * prev;
}ListNode;
#define LISTSIZE 1000
ListNode ListNodePool[LISTSIZE];//创建结点池,在需要的时候直接获取,比new ListNode时间快
int NodeNum = 0;
//nil是表头,NIL是它的指针,绑定一下
ListNode nil;
ListNode * NIL;
ListNode * getNewNode(){
return &ListNodePool[NodeNum++];
}
void listInit(){
NIL = &nil;
NIL->next = NIL;
NIL->prev = NIL;
NIL->key = 0;
}
void listInsertAfter(ListNode * dstNode, ListNode * NewNode){
NewNode->next = dstNode->next;
NewNode->prev = dstNode;
dstNode->next = NewNode;
NewNode->next->prev = NewNode;
}
void listInsertAtFront(ListNode * node){
listInsertAfter(NIL, node);
}
void listDelete(ListNode * node){
node->prev->next = node->next;
node->next->prev = node->prev;
}
ListNode * listSearch(int k){
ListNode * x = NIL->next;
while (x != NIL && x->key != k){
x = x->next;
}
return x;
}
//end of LinkedList API
int data[LISTSIZE];
void insertSort(int data[], int N){
for (int i = 1; i < N; i++){
int key = data[i];
int j;
for (j = i - 1; j >= 0; j--){
if (data[j] > key){
data[j + 1] = data[j];
}
else{
break;
}
}
data[j + 1] = key;
}
}
void showData(int N){
for (int i = 0; i < N; i++){
cout << data[i] << " ";
}
cout << endl;
}
void showList(){
ListNode * curNode = NIL->next;
while (curNode != NIL){
cout << curNode->key << " ";
curNode = curNode->next;
}
cout << endl;
}
void listInsertSort(){
ListNode * curNode = NIL->next->next;
ListNode * tmpNode;
while (curNode != NIL){
//cout << curNode->key << " " << endl;
ListNode * dstNode = NIL->next;
while (dstNode != curNode && dstNode->key < curNode->key){
dstNode = dstNode->next;
}
dstNode = dstNode->prev;
tmpNode = curNode->next;
listDelete(curNode);
listInsertAfter(dstNode, curNode);
curNode = tmpNode;
}
}
void main(){
freopen("input.txt", "r", stdin);
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++){
/*cin >> data[i];
cout << data[i] << " ";*/
scanf("%d", &data[i]);
//printf("%d ", data[i]);
}
//cout << endl;
printf("\n");
listInit();
ListNode * dstNode = NIL;
for (int i = 0; i < N; i++){
ListNode * node = getNewNode();
node->key = data[i];
listInsertAfter(NIL->prev, node);
//dstNode = dstNode->next;
}
//按照插入的顺序输出
ListNode * curNode = NIL->next;
while (curNode != NIL){
cout << curNode->key << " ";
curNode = curNode->next;
}
cout << endl;
//插入按照从小到大排序输出,数组实现
insertSort(data, N);
showData(N);
//插入按照从小到大排序输出,链表实现
listInsertSort();
showList();
}