您的位置:首页 > Web前端

单链表中的常见算法问题(剑指offer5/13/15/16/17)

2014-04-12 23:39 218 查看
1.单链表的结点

struct ListNode {
int m_nKey;
ListNode* m_pNext;
};

2.创建链表

ListNode* createList(int length) {
//创建表头结点
ListNode* head = new ListNode();
head->m_pNext = NULL;
ListNode* p = head;

int value = 0; //临时存储用户键入的第i个结点值
for (int i = 0; i < length; ++i) {
cout << "ListNode" << i << ":\t";
cin >> value;

//将新创建的结点插入链表中
ListNode* q = new ListNode();
q->m_nKey = value;
q->m_pNext = NULL;
p->m_pNext = q;
p = q;
}

return head;
}


3.删除链表

void deleteList(ListNode* head) {
if (NULL == head) {
return;
}

ListNode* p = head;
ListNode* q = p;
while (p->m_pNext) {
q = p;
p = p->m_pNext;

delete q;
q = NULL;
}

delete head;
head = NULL;
}


4.遍历输出链表(从表头到表尾)

void showList(ListNode* head) {
//如果是空链表直接退出
if (NULL == head)
return;

ListNode* p = head->m_pNext;
while (p != NULL) {
cout << p->m_nKey << "\t";
p = p->m_pNext;
}

cout << endl;
}


5.链表的长度

int listLength(ListNode* head) {
if (NULL == head) {
return 0;
}

int length = 0;
ListNode*p = head->m_pNext;
while (NULL != p) {
p = p->m_pNext;
++length;
}
return length;
}


6.链表逆置

ListNode* listReverse(ListNode* sourceHead) {
if (NULL == sourceHead)
return NULL;

ListNode* newHead = new ListNode();
newHead->m_pNext = NULL;

ListNode* p = NULL; //中间结点

while (sourceHead->m_pNext != NULL) {
//将原来链表的第一个结点从链表中删除
p = sourceHead->m_pNext;
sourceHead->m_pNext = p->m_pNext;

//将删除掉的结点以头插法插入到新的链表中
p->m_pNext = newHead->m_pNext;
newHead->m_pNext = p;
}

return newHead;
}


7.O(1)时间删除一个指定结点

void deleteListNode(ListNode* pHeadListNode, ListNode* pToBeDeleted) {
if (NULL == pHeadListNode || NULL == pToBeDeleted) {
return;
}

//方法二:在保证链表中包含待删除结点的前提下,将待删除结点的下一个结点值
//替换掉要删除结点的值,然后删除待删除结点的下一个结点

//如果待删除结点是链表中的唯一结点
ListNode* pHeadNext = pHeadListNode->m_pNext;
if (pHeadNext == pToBeDeleted && pHeadNext ==
NULL) {
delete pToBeDeleted;
pToBeDeleted = NULL;
pHeadNext = NULL;
}
//如果要删除的结点不是最后一个结点,且待删除的链表的长度大于1
else if (pToBeDeleted->m_pNext != NULL) {
ListNode* pDeletedNext = pToBeDeleted->m_pNext;
pToBeDeleted->m_nKey = pDeletedNext->m_nKey;
pToBeDeleted = pDeletedNext->m_pNext;

delete pDeletedNext;
}
//如果待删除结点是链表的末尾结点(也是最常见的操作方法)
else {
//方法一:找到要删除结点,用其前一个结点指向其下一个结点,从而达到删除的目的
ListNode* p = pHeadListNode;
ListNode* q = pHeadListNode->m_pNext;
while (q != pToBeDeleted && q != NULL) {
p = q;
q = q->m_pNext;
}
if (q != NULL) {
p->m_pNext = q->m_pNext;
}
}
}


8.输出单链表中的倒数第K个结点的值

int findLastKNodeValue(ListNode* head, const unsigned int k) {
if (NULL == head || k <= 0) {
return -1;
}

//计数器
unsigned int count = 0;
ListNode* p = head;
ListNode* q = head;

//如果链表长度多于k,则q先遍历k个值
while (count < k && q != NULL) {
q = q->m_pNext;
++count;
}

//如果少于k直接退出
if (NULL == q) {
return -1;
}

//如果链表的结点多于k个,两个指针一起遍历到先遍历指针为NULL时
while (NULL != q) {
q = q->m_pNext;
p = p->m_pNext;
}

//当链表长度多于k时,输出倒数第k个结点的值
return p->m_nKey;
}


9.合并两个排序的链表

ListNode* mergeSortedLinkedList(ListNode* head1, ListNode* head2) {
//有个链表为空时返回另外一个链表即可--代码的鲁棒性
if (NULL == head1) {
return head2;
}

if (NULL == head2) {
return head1;
}

//合并后的新头 结点
ListNode* head = new ListNode();
head->m_pNext = NULL;

ListNode* s = head;
while (NULL != head1->m_pNext && NULL != head2->m_pNext) {
ListNode* p = head1->m_pNext;
ListNode* q = head2->m_pNext;

if (p->m_nKey < q->m_nKey) {
head1->m_pNext = p->m_pNext;

p->m_pNext = s->m_pNext;
s->m_pNext = p;
s = p;
} else {
head2->m_pNext = q->m_pNext;

q->m_pNext = s->m_pNext;
s->m_pNext = q;
s = q;
}

}

while (NULL != head1->m_pNext) {
ListNode* p = head1->m_pNext;
head1->m_pNext = p->m_pNext;

p->m_pNext = s->m_pNext;
s->m_pNext = p;
s = p;
}

while (NULL != head2->m_pNext) {
ListNode* q = head2->m_pNext;
head2->m_pNext = q->m_pNext;

q->m_pNext = s->m_pNext;
s->m_pNext = q;
s = q;
}

return head;
}

测试代码

/*
*
*  Created on: 2014-3-20 16:16:52
*      Author: danDingCongRong
*/

#include<iostream>
using namespace std;

int main() {
int listLen = 0;
cout << "输入链表的长度:\t";
cin >> listLen;

ListNode* head = createList(listLen);
cout << "原始链表:" << endl;
showList(head);

cout << "链表的长度为:" << listLength(head) << endl;

ListNode* newHead = listReverse(head);
cout << "逆置后的链表:" << endl;
cout << "" << endl;
showList(newHead);

cout << "倒数第5个数是:" << endl;
cout << findLastKNodeValue(newHead, 5) << endl;

ListNode* head1 = createList(listLen);
cout << "原始链表:" << endl;
showList(head1);

ListNode* head2 = createList(listLen);
cout << "原始链表:" << endl;
showList(head2);

cout << "合并两个有序的链表:" << endl;
ListNode* head3 = mergeSortedLinkedList(head1, head2);
showList(head3);

cout << "链表的长度为:" << listLength(head3) << endl;

return 0;
}


注:部分代码参考自剑指offer


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: