习题一:通过一趟遍历确定长度为n的单链表中值最大的节点
分析:
通过上一篇文章,我们可以得知,在只能遍历一次的情况下对数值进行比较,可以使用双指针。
下面给出代码:
SLTNode* SLTFind(SLTNode* phead) {
SLTNode* src =phead,*dst=phead;
while (src) {
if (src->data >= dst->data) {
dst = src;
}
src = src->next;
}
return dst;
}
进行测试:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode {
SLTDataType data;
struct SListNode* next;
}SLTNode;
//打印链表中存储的元素的值
void SLTPrint(SLTNode* phead) {
SLTNode* cur = phead;
while (cur) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
//生成节点的函数
SLTNode* BuySLTNode(SLTDataType x) {
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL) {
perror("malloc fail");
return NULL;
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//对链表进行尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x) {
assert(pphead);
SLTNode* newnode = BuySLTNode(x);
if (*pphead == NULL) {
*pphead = newnode;
}
else {
//找尾
SLTNode* tail = *pphead;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = newnode;
}
}
//目标函数
SLTNode* SLTFind(SLTNode* phead) {
SLTNode* src =phead,*dst=phead;
while (src) {
if (src->data >= dst->data) {
dst = src;
}
src = src->next;
}
return dst;
}
int main() {
SLTNode* plist = NULL;
SLTPushBack(&plist, 1);
SLTPushBack(&plist, 0);
SLTPushBack(&plist, 4);
SLTPushBack(&plist, 6);
SLTPushBack(&plist, 9);
SLTPushBack(&plist, 7);
SLTPrint(plist);
SLTNode* a=SLTFind(plist);
printf("%d\n",a->data);
return 0;
}
运行结果如下:
成功!
习题二:
将链表中所有结点的链接方向“原地”逆转,即要求仅利用原表的存储空间。
SLTNode* SLTReverse(SLTNode* phead){
if(phead==NULL)
return NULL;
//特殊情况,头指针为空
SLTNode*n1,*n2,*n3;
n1=NULL;
n2=phead;
n3=n2->next;
while(n2){
//翻转
n2->next=n1;
//迭代
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
//此处不为return n2,若n2已经为NULL时,说明n1已经指向了最后一个节点
}
进行测试:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode {
SLTDataType data;
struct SListNode* next;
}SLTNode;
void SLTPrint(SLTNode* phead) {
SLTNode* cur = phead;
while (cur) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
SLTNode* BuySLTNode(SLTDataType x) {
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL) {
perror("malloc fail");
return NULL;
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
void SLTPushBack(SLTNode** pphead, SLTDataType x) {
assert(pphead);
SLTNode* newnode = BuySLTNode(x);
if (*pphead == NULL) {
*pphead = newnode;
}
else {
//找尾
SLTNode* tail = *pphead;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = newnode;
}
}
SLTNode* SLTReverse(SLTNode* phead){
if(phead==NULL)
return NULL;
SLTNode*n1,*n2,*n3;
n1=NULL;
n2=phead;
n3=n2->next;
while(n2){
//翻转
n2->next=n1;
//迭代
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
int main() {
SLTNode* plist = NULL;
SLTPushBack(&plist, 1);
SLTPushBack(&plist, 0);
SLTPushBack(&plist, 4);
SLTPushBack(&plist, 6);
SLTPushBack(&plist, 9);
SLTPushBack(&plist, 7);
SLTPrint(plist);
SLTNode* p=SLTReverse(plist);
SLTPrint(p);
return 0;
}
运行结果如下:
下一次会讲到链表的合并、分割、回文判断,请期待哦!