创建单链表
typedef struct node
{
int data;
node *next;
}Node, *LinkList;
//建立链表
Node* createList1(const int a[], int n)
{
Node *head, *endPtr;
head = endPtr = NULL;
for(int i=0;i<n;i++)
{
Node *temp = new Node;
temp->data = a[i];
temp->next = NULL;
if(i==0)
{
head = endPtr = temp;
// endPtr->next = NULL;
}
else
{
endPtr->next = temp;
endPtr = temp;
}
}
return head;
}
/*建立链表2*/
Node* createList2(int a[],int n)
{
Node *ListHead = new Node;
ListHead->data = a[0];
ListHead->next = NULL;
for(int i=n-1;i>0;i--)
{
Node *tmp = new Node;
tmp->data = a[i];
tmp->next = ListHead->next;
ListHead->next = tmp;
}
return ListHead;
}
1、从一个单链表中返回倒数第n个元素
维护两个指针,保持两个指针距离为n,当后面的指针为NULL时,前面的指针即为所求
实现:
Node *findNthToLast(Node *head, int n)
{
Node *ptr1 = head, *ptr2 = head;
if(head==NULL) //如果链表为空
return NULL;
//保证ptr2与ptr1间隔n-1
if(n<=0)
return NULL;
else
{
for(int i=1;i<=n-1;i++)
{
ptr2 = ptr2->next;
if(ptr2==NULL) //如果链表长度小于n
return NULL;
}
}
while(ptr2->next!=NULL)
{
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
return ptr1;
}
2、 给出单链表的头指针和一个结点指针,在O(1)时间删除该结点。
把下一个节点的data复制到需要删除的节点覆盖原来的内容,再把下一个节点删除,最后将该节点的next指针指向下下个节点。有两个特殊情况需要单独处理:要删除节点位于链表的尾部;链表只有一个节点。
实现
bool deleteNode(Node *head,Node *node)
{
if(head==NULL)
return false;
//要删除节点不是尾节点
if(node->next!=NULL)
{
Node *tmpPtr = node->next;
node->data = tmpPtr->data;
node->next = tmpPtr->next;
delete tmpPtr;
}
else
{
if(head==node) //链表只有一个节点
{
delete node;
head = NULL;
}
else //删除节点为尾节点
{
Node *tmp = head;
while(tmp->next!=node)
{
tmp = tmp->next;
}
tmp->next = NULL;
delete node;
}
}
return true;
}
3、单链表逆置
3.1递归实现:
void reverse(Node *pCur,LinkList &ListHead)
{
if(NULL==pCur||NULL==pCur->next)
{
ListHead = pCur;
}
else
{
Node *pNext = pCur->next; //保存后继节点的指针
reverse(pNext,ListHead);
pNext->next = pCur;
pCur->next = NULL;
}
}
3.2非递归实现
void reverseList(LinkList &head)
{
if(head==NULL||head->next==NULL) //边界检查
return NULL;
Node *pPre = head; //用来指向前驱节点
Node *pCur = pPre->next; //用来指向当前节点
Node *pNext = NULL; //用来指向后继节点
while(pCur!=NULL)
{
pNext = pCur->next; //保存后继节点的指针
pCur->next = pPre; //将当前节点的指针域指向前驱节点
pPre = pCur;
pCur = pNext;
}
head->next = NULL;
head = pPre; //新的头节点
}
4、从尾到头打印链表,要求不改变链表结构
4.1、借助栈来实现
void PrintListReversing(LinkList pHead)
{
stack<Node*> nodes;
Node* pNode = pHead;
if(pNode==NULL)
return;
while(pNode!=NULL) //将节点依次入栈
{
nodes.push(pNode);
pNode = pNode->next;
}
while(!nodes.empty()) //出栈
{
pNode = nodes.top();
cout<<pNode->data<<endl;
nodes.pop();
}
}
4.2由于递归本质就是栈结构,因此也可以用递归实现
void PrintListReversing2(Node* pHead)
{
if(pHead==NULL)
return;
if(pHead!=NULL)
{
if(pHead->next!=NULL)
{
PrintListReversing2(pHead->next);
}
cout<<pHead->data<<endl;
}
}
5、使用单链表实现大数的加法
/*有两个由单链表表示的数。每个结点代表其中的一位数字。
数字的存储是逆序的, 也就是说个位位于链表的表头。
写一函数使这两个数相加并返回结果,结果也由链表表示。*/
//eg. Input:(3->9->6), (4->7->8->3)
// Output:(7->6->5->4)
Node *ListAdd(Node* L1, Node* L2)
{
if(L1==NULL)
return L2;
if(L2==NULL)
return L1;
Node *ptr1 = L1, *ptr2 = L2, *ResultPtr=NULL, *TmpPtr=NULL;
int carry = 0;
Node *p_node = new Node();
p_node->data = (L1->data+L2->data)%10;
p_node->next = NULL;
carry = (L1->data+L2->data)/10;
ResultPtr = TmpPtr = p_node;
TmpPtr->next = NULL;
L1 = L1->next;
L2 = L2->next;
while(L1 && L2)
{
Node *pNode = new Node();
TmpPtr->next = pNode;
int tmp = L1->data+L2->data+carry;
carry = tmp/10;
pNode->data = tmp%10;
pNode->next = NULL;
TmpPtr = TmpPtr->next;
L1 = L1->next;
L2 = L2->next;
}
while(L1)
{
Node *pNode = new Node();
TmpPtr->next = pNode;
int tmp = L1->data+carry;
carry = tmp/10;
pNode->data = tmp%10;
pNode->next = NULL;
TmpPtr = TmpPtr->next;
L1 = L1->next;
}
while(L2)
{
Node *pNode = new Node();
TmpPtr->next = pNode;
int tmp = L2->data+carry;
carry = tmp/10;
pNode->data = tmp%10;
pNode->next = NULL;
TmpPtr = TmpPtr->next;
L2 = L2->next;
}
if(carry)
{
Node *pNode = new Node();
TmpPtr->next = pNode;
pNode->data = carry;
pNode->next = NULL;
}
return ResultPtr;
}