算法导论之链表基础知识回顾
链表是一种非常基础的数据结构,很多算法的实现都是基于链表的,熟悉链表的基本操作还是很有必要的。
以下只是给出了链表的非常基础的操作,包括建立,排序,插入和删除等,本是我自己用来复习数据结构用的,贴出来仅供参考;
以下只是给出了链表的非常基础的操作,包括建立,排序,插入和删除等,本是我自己用来复习数据结构用的,贴出来仅供参考;
/***
本程序用来回顾关于链表的一些基本操作
包括链表的建立,排序,插入和删除等,在本程序中使用的是单向链表
后注:一开始我虽然建立了head节点为一没有key值的单独节点,但我在程序中只是利用了head节点来指向链表的第一个节点
并没有像算法导论中所说的那样把它作为哨兵节点,其实如果想把它作为哨兵节点也很简单,只需要把链表中最后一个元素的next域
指向head节点即可,这样也就建立了一个循环链表。这样在判断链表结束时的条件就是:p->next != head
****/
#include <iostream>
using namespace std;
typedef struct linknode
{
int key;
struct linknode* prev;
struct linknode* next;
}linknode,*linkpoint;
//创建链表,输入-1表示创建结束,创建顺序与输入顺序一致
void CreateLink(linkpoint &head)
{
int key;
linkpoint p,q;
q = head;
while(cin>>key&&key!=-1)
{
p = new linknode;
p->key = key;
p->next = q->next;
p->prev = q;
q->next = p;
q = p;
}
}
//链表的遍历
void traversing(linkpoint p)
{
linkpoint q = p->next;
while(q != NULL)
{
cout<<q->key<<" ";
q = q->next;
}
cout<<endl;
}
//链表的排序1
//思路如下(选择排序):
//从第一个节点往后逐个遍历,对于当前节点来说,从它后面所有的节点中选择一个key最小的节点与当前节点交换key值
void Linklist_Sort_01(linkpoint &head)
{
linkpoint p,q,r = NULL;
int value;
p = head->next;
while(p)
{
value = p->key;
q = p->next;
while(q)
{
if(value > q->key)
{
value = q->key;
r = q;
}
q = q->next;
}
if(r && p->key != r->key)
{
value = p->key;
p->key = r->key;
r->key = value;
}
p = p->next;
r = NULL;//每执行完一次外while循环,都要给r重新赋值
}
}
//链表的排序2
//思路如下(插入排序):
//从第二个节点开始,逐个作为新的元素插入到前面已经排好序的链表中,当然这只是一个虚拟的插入过程,因为在这个过程中,并没有新的元素插入,而只有元素的移动
//因为在排序的过程中,元素总的个数并没有发生变化
void Linklist_Sort_02(linkpoint &head)
{
linkpoint p,q,r;
int value;
p = head->next;
while(p)
{
q = p->next;
if(q)
{
value = q->key;
r = p;
while((r != head)&&(r->key > value))
{
q->key = r->key;
q = r;
r = r->prev;
}
q->key = value;
}
p = p->next;
}
}
//向当前以head为头的链表中插入值为value的元素,插入后依然保持有序
//注:当执行插入操作时,必须保证当前链表是有序的
void Linklist_Insert(linkpoint head,int value)
{
linkpoint p,q,r;
r = head;
p = head->next;
//在给value寻找位置的过程中,节点指针r和p一直保持前后指针关系
while(p&&p->key < value)
{
r = p;
p = p->next;
}
q = new linknode;
q->key = value;
//根据p是否NULL分两种情况处理
if(p)
{
q->next = p;
q->prev = r;
r->next = q;
p->prev = q;
}
else
{
q->next = p;
q->prev = r;
r->next = q;
}
}
int Linklist_Delete(linkpoint head,int value)
{
linkpoint p;
bool flag = false;
p = head->next;
while(p)
{
if(p->key == value)
{
p->prev->next = p->next;
if(p->next)
p->next->prev = p->prev;
if(flag == false)
flag = true;
}
p = p->next;
}
if(flag)
return 1;
return 0;
}
int main()
{
linkpoint head;
int value;
head = new linknode;
head->next = NULL;
head->prev = NULL;
cout<<"Create List:(end with the -1 input)"<<endl;
CreateLink(head);
cout<<"Before Sorted:"<<endl;
traversing(head);
cout<<"After Sorted:"<<endl;
Linklist_Sort_01(head);
traversing(head);
cout<<"Please input the num you want to insert into the current list:"<<endl;
cin>>value;
Linklist_Insert(head,value);
traversing(head);
cout<<"Please input the num you want to delete in the current list:"<<endl;
cin>>value;
Linklist_Delete(head,value);
traversing(head);
return 0;
}
本程序用来回顾关于链表的一些基本操作
包括链表的建立,排序,插入和删除等,在本程序中使用的是单向链表
后注:一开始我虽然建立了head节点为一没有key值的单独节点,但我在程序中只是利用了head节点来指向链表的第一个节点
并没有像算法导论中所说的那样把它作为哨兵节点,其实如果想把它作为哨兵节点也很简单,只需要把链表中最后一个元素的next域
指向head节点即可,这样也就建立了一个循环链表。这样在判断链表结束时的条件就是:p->next != head
****/
#include <iostream>
using namespace std;
typedef struct linknode
{
int key;
struct linknode* prev;
struct linknode* next;
}linknode,*linkpoint;
//创建链表,输入-1表示创建结束,创建顺序与输入顺序一致
void CreateLink(linkpoint &head)
{
int key;
linkpoint p,q;
q = head;
while(cin>>key&&key!=-1)
{
p = new linknode;
p->key = key;
p->next = q->next;
p->prev = q;
q->next = p;
q = p;
}
}
//链表的遍历
void traversing(linkpoint p)
{
linkpoint q = p->next;
while(q != NULL)
{
cout<<q->key<<" ";
q = q->next;
}
cout<<endl;
}
//链表的排序1
//思路如下(选择排序):
//从第一个节点往后逐个遍历,对于当前节点来说,从它后面所有的节点中选择一个key最小的节点与当前节点交换key值
void Linklist_Sort_01(linkpoint &head)
{
linkpoint p,q,r = NULL;
int value;
p = head->next;
while(p)
{
value = p->key;
q = p->next;
while(q)
{
if(value > q->key)
{
value = q->key;
r = q;
}
q = q->next;
}
if(r && p->key != r->key)
{
value = p->key;
p->key = r->key;
r->key = value;
}
p = p->next;
r = NULL;//每执行完一次外while循环,都要给r重新赋值
}
}
//链表的排序2
//思路如下(插入排序):
//从第二个节点开始,逐个作为新的元素插入到前面已经排好序的链表中,当然这只是一个虚拟的插入过程,因为在这个过程中,并没有新的元素插入,而只有元素的移动
//因为在排序的过程中,元素总的个数并没有发生变化
void Linklist_Sort_02(linkpoint &head)
{
linkpoint p,q,r;
int value;
p = head->next;
while(p)
{
q = p->next;
if(q)
{
value = q->key;
r = p;
while((r != head)&&(r->key > value))
{
q->key = r->key;
q = r;
r = r->prev;
}
q->key = value;
}
p = p->next;
}
}
//向当前以head为头的链表中插入值为value的元素,插入后依然保持有序
//注:当执行插入操作时,必须保证当前链表是有序的
void Linklist_Insert(linkpoint head,int value)
{
linkpoint p,q,r;
r = head;
p = head->next;
//在给value寻找位置的过程中,节点指针r和p一直保持前后指针关系
while(p&&p->key < value)
{
r = p;
p = p->next;
}
q = new linknode;
q->key = value;
//根据p是否NULL分两种情况处理
if(p)
{
q->next = p;
q->prev = r;
r->next = q;
p->prev = q;
}
else
{
q->next = p;
q->prev = r;
r->next = q;
}
}
int Linklist_Delete(linkpoint head,int value)
{
linkpoint p;
bool flag = false;
p = head->next;
while(p)
{
if(p->key == value)
{
p->prev->next = p->next;
if(p->next)
p->next->prev = p->prev;
if(flag == false)
flag = true;
}
p = p->next;
}
if(flag)
return 1;
return 0;
}
int main()
{
linkpoint head;
int value;
head = new linknode;
head->next = NULL;
head->prev = NULL;
cout<<"Create List:(end with the -1 input)"<<endl;
CreateLink(head);
cout<<"Before Sorted:"<<endl;
traversing(head);
cout<<"After Sorted:"<<endl;
Linklist_Sort_01(head);
traversing(head);
cout<<"Please input the num you want to insert into the current list:"<<endl;
cin>>value;
Linklist_Insert(head,value);
traversing(head);
cout<<"Please input the num you want to delete in the current list:"<<endl;
cin>>value;
Linklist_Delete(head,value);
traversing(head);
return 0;
}
我没有什么雄心壮志,我只想给自己和关心自己的家人和朋友一个交代,仅此而已。