标签:
链表是由一个个节点组成的,每个节点中都存储有一个指向下一个节点的指针。所以在创建链表的时候最好先写一个结构体,用来创建每一个节点。
例如:
typedef struct node
{
char name[20];// 开辟空间
struct node* next;
}Student;
1.创建链表:
Student* creatList(int n)
{
Student * head = new Student;
head -> next = NULL;
Student* pre = head;//记录新节点的前一个节点
cout<<" input name: ";
for (int i = 0; i < n; i++) {
Student* p = new Student;
cin>>p->name;
pre->next = p;
p->next = NULL;
pre = p;//重新改变pre的值
}
return head;
}
2.添加节点:
添加节点和删除节点之前可以先把链表的长度求出来,用起来比较方便。
int length(Student *head)
{
int i = 0;
Student * p = head->next;
while (p != NULL) {
i++;
p = p->next;
}
return i;
}
void addElement(Student* head, char* str, int index)
{
Student* p = head;
int len = length(head);
if (index<0||index>len+1) { //判断是否越界
cout<<"请重新输入:"<<endl;
return;
}
for (int i = 1; i<index; i++) { //找到需要插入位置的前一个位置的节点
p = p->next;
}
Student* news = new Student;
strcpy(news->name, str);
news->next = p->next; //让新节点的指针指向他前一个节点原本指向的节点
p->next = news; //让新节点的前一个节点的指针指向新节点
}
3. 删除节点
void removeElement(Student* head, int index)
{
Student* p = head;
int len = length(head);
if (index>len||index<0) { //判断要移除的节点的下标是否越界
cout<<"请重新输入:"<<endl;
return;
}
for (int i = 1; i < index; i++) { //找到要移除的节点的前一个节点
p = p->next;
}
Student* tmp = p->next ; //让指针tmp指向要移除的节点
p->next = tmp->next; //要移除节点的前一个节点的指针指向要移除节点的后一个节点
delete tmp;
}
4. 逆序输出链表
Node* reverse(Node* head)
{
if (head->next == NULL) {
return head;
}
else{
Node* p = head->next;
Node* q = head->next;
Node* t = NULL;
while (q != NULL) {
p = q->next;
q->next = t;
t = q;
q = p;
}
p = new Node;
p->next = t;
q = p;
return q;
}
}
备注:主要思想就是用三个指针依次改变链表节点的指向,达到反序的目的。
5. 合并链表(两个链表分别有序,要求合成的链表依然有序)
//非递归合并链表
Node* hebingList(Node* head1, Node* head2)
{
Node* pa = NULL;
Node* pb = NULL;
if (head1->next != NULL) {
pa = head1->next;
}
else{
return head2;
}
if (head2->next != NULL) {
pb = head2->next;
}
else{
return head1;
}
Node * head = head1;
Node * t = head;
while (pa != NULL && pb != NULL) {
if (pa->data >= pb->data) {
t->next = pb;
t = pb;
pb = pb->next;
}
else{
t->next = pa;
t = pa;
pa = pa->next;
}
}
if (pa != NULL) {
t->next = pa;
}
if (pb != NULL) {
t->next = pb;
}
return head;
}
//递归合并链表
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}
链表这一块如果单单用脑子想可能会稍微复杂点,但是可以把图画出来,就一目了然。
6. 最后说一个忘了是哪里的面试题,关于链表的,感觉也挺经典的。
题目是:有一百个球,每个球上都有编号,按顺序排列,每次取出偶数位置上的球,求最后一个剩余的球原来的编号是多少?
想来想去,也就用链表来解这道题比较简单一些。
具体实现代码如下:
typedef struct node{
int num;
struct node* next;
}Ball;
int length(Ball* head){
int i = 0;
Ball* p = head->next;
while (p != NULL) {
i++;
p = p->next;
}
return i;
}
Ball* creatList(int n){
Ball* head = new Ball;
head->next = NULL;
Ball* pre = head;
for (int i = 0; i < n; i++) {
Ball* p = new Ball;
p->num = i+1;
pre->next = p;
p->next = NULL;
pre = p;
}
return head;
}
void remove(Ball* head){
Ball* p = head;
int s = length(head);
while (length(head)>=2){
if (length(head)%2 == 0) {
for (int i = 0; i < s/2; i++) {
Ball* tmp = p->next;
p->next = tmp->next;
delete tmp;
p = p->next;
}
}
else{
for (int i = 0; i < (int)s/2-1; i++) {
Ball* tmp = p->next;
p->next = tmp->next;
delete tmp;
p = p->next;
}
delete p->next;
p->next = NULL;
}
p = head;
s/=2;
}
}
标签:
原文地址:http://www.cnblogs.com/benniuniu-gj/p/4454612.html