最近在看数据结构,发现很多算法是看懂了,可是要写出来,并且实现它,并不是一件简单的事情,算法只是逻辑上的东西,程序是物理实践,不经过物理实践,你是不会发现其中的奥秘之处。后悔大学的时候,学了那么多的逻辑,都没有实践下。实践才能证明你的逻辑是否正确。以下是我对链表的温习后,新的实践。
// Win32Console.cpp : 定义控制台应用程序的入口点。
//
//单链表的创建,尾部插入方法
#include "stdafx.h"
#include "stdio.h"
typedef int elemtype;
typedef struct LNode
{
elemtype Data;
struct LNode *Next;
}LinkNode;
//尾部插入方法
LinkNode *CreateLinkList(int A[],int n)
{
LinkNode *head,*p,*q;
if(n < 0)
{
printf("The Arrary is empty!");
return NULL;
}
head = new LinkNode();
p = head ;
printf("结点地址/t");
printf("结点值域/t");
printf("结点Next/t/n");
for (int i = 0;i<n;i++)
{
//新结点申请
q = new LinkNode();
q->Data = A[i];
p->Next = q;
//跟踪结点的值和结点的地址及下个结点的地址。
printf("%x/t/t",p);
printf("%d/t/t",p->Data);
printf("%x/t/t",p->Next);
printf("/n");
p = q;
}
printf("%x/t/t",p);
printf("%d/t/t",p->Data);
printf("%x/t/t",p->Next);
printf("/n");
return head;
}
//头部插入结点建立单链表
LinkNode *CreateLinkListHead(int A[],int n)
{
LinkNode *head,*p;
if(n < 0)
{
printf("The Arrary is empty!");
return NULL;
}
head = new LinkNode();
//head->Next = NULL;默认的也是head->Next = NULL,所以可以不写。
printf("结点地址/t");
printf("结点值域/t");
printf("结点Next/t/n");
for(int i = 0;i < n; i++)
{
p = new LinkNode();
p->Data = A[i];
p->Next = head->Next;
//跟踪结点的值和结点的地址及下个结点的地址。
printf("%x/t/t",p);
printf("%d/t/t",p->Data);
printf("%x/t/t",p->Next);
printf("/n");
head->Next = p;
}
printf("%x/t/t",head);
printf("%d/t/t",head->Data);
printf("%x/t/t",head->Next);
printf("/n");
return head;
}
//获取链表的长度
int GetLength(LinkNode *head)
{
int len = 0;
while(head->Next != NULL)
{
len ++;
head = head->Next;
}
return len;
}
//清空单链表
void ClearLinkList(LinkNode *head)
{
head->Next = NULL;
}
//判断单链表是否为空,true表示为空,false表示不为空
bool IsEmpty(LinkNode *head)
{
if(head->Next == NULL)
{
return true;
}
else
{
return false;
}
}
//附加操作,即在单链表的表尾增加个结点
void Append(elemtype elem,LinkNode *head)
{
LinkNode *q;
while(head->Next != NULL)
{
head = head->Next;
}
q = new LinkNode();
q->Data = elem;
head->Next = q;
}
//单链表的插入操作,在指定位置的结点前插入
void InsertPre(LinkNode *head,int i,int value)
{
LinkNode *p,*q;
bool flag = false; //用来判断插入位置是否存在。
int count = 1;
p = head->Next;
if(p == NULL || i<0)
{
printf("单链表为空,或插入位置不正确!/n");
return;
}
if(i != 1)
{
while(p != NULL)
{
count++;
if(count == i)
{
flag = true;
break;
}
p = p->Next;
}
if(flag)
{
q = new LinkNode();
q->Data = value;
q->Next = p->Next;
p->Next = q;
}
else
{
printf("插入位置不正确!/n");
}
}
else
{
q = new LinkNode();
q->Data = value;
q->Next = head->Next;
head->Next = q;
}
}
//后插入操作,在指定位置的结点之后插入。
void InsertLast(LinkNode *head,int i,int value)
{
LinkNode *p,*q;
p = head->Next;
int count = 1;
bool flag = false;
if(p == NULL || i < 0)
{
printf("单链表为空!或插入位置不正确/n");
return;
}
while(p->Next != NULL)
{
if(count == i)
{
flag = true;
break;
}
p = p->Next;
count++;
}
if(flag)
{
q = new LinkNode();
q->Data = value;
q->Next = p->Next;
p->Next = q;
}
else
{
printf("插入的位置不正确!/n");
}
}
//删除操作,删除指定位置的结点
void Delete(LinkNode *head,int i)
{
LinkNode *p,*q;
p = head->Next;
bool flag = false;
int j = 1;
if(p == NULL || i< 0)
{
printf("单链表为空或删除位置不正确!/n");
return;
}
if(i == 1)
{
head->Next = p->Next;
printf("删除结点的值为: %d/n",p->Data);
}
else
{
while(p != NULL)
{
if(j == i)
{
flag = true;
break;
}
q = p;
p = p->Next;
j++;
}
if(flag)
{
q->Next = p->Next;
printf("删除结点的值为: %d/n",p->Data);
}
else
{
printf("删除位置不正确!/n");
}
}
}
//取单链表指定位置的数据元素
void GetElem(LinkNode *head,int i)
{
LinkNode *p;
int count = 1;
p = head->Next;
bool flag = false;
if(p == NULL || i < 0)
{
printf("单链表为空或i位置不正确!/n");
return;
}
while(p != NULL)
{
if(count == i)
{
flag = true;
break;
}
p = p->Next;
count++;
}
if(flag)
{
printf("第i位置的数据元素为: %d",p->Data);
printf("/n");
}
else
{
printf("链表中不存在第i个位置!");
printf("/n");
}
}
void Locate(LinkNode *head,elemtype T)
{
LinkNode *p;
p = head->Next;
int count = 1;
if(p == NULL)
{
printf("单链表为空!");
return;
}
while(p != NULL)
{
if(p->Data == T)
{
printf("要查找的数值在单链表中首次出现的位置为: %d",count);
printf("/n/n");
return;
}
count++;
p = p->Next;
}
printf("要查找的数值在单链表中不存在!/n/n");
}
//单链表的转置,返回转置后的单链表Head。通过后插入结点的方法。
void ReversLinkList(LinkNode *Head)
{
LinkNode *p,*q,*r,*s;
p = Head->Next;
q = Head->Next->Next;
int count = 1;
if(p == NULL)
{
printf("单链表为空!/n");
return;
}
p->Next = NULL; //新链表的尾部结点
while(q != NULL)
{
s = new LinkNode();
s->Data = q->Data;
s->Next = p ;
p = s;
q = q->Next;
}
Head->Next = p;
}
//单链表的转置,返回转置后的单链表Head。算法2,通过移动结点指向。
void ReversLinkList2(LinkNode *head)
{
LinkNode *p,*q,*s;
p = head->Next; //指向链表的第一个结点
q = p->Next; //指向链表的第二个结点
s = q->Next; //指向链表的第三个结点
p->Next = NULL; //作为新链表的尾部指针,Next域为NULL。
while(q != NULL)
{
q->Next = p;
p = q;
q = s;
if(s != NULL)
{
s = s->Next;
}
}
head->Next = p;
}
//单链表的转置,采用遍历原先的单链表,插入到新的单链表中去,同时为了节省内存资源把原链表的头指针,作为新链表的头指针。
void ReversLinkList3(LinkNode *head)
{
LinkNode *p,*q;
p = head->Next;
head->Next = NULL;
q = new LinkNode();
while(p != NULL)
{
q = p;
p = p->Next;
q->Next = head->Next;
head->Next = q;
}
}
//遍历单链表,并输出单链表的数据元素
void Print(LinkNode *head)
{
LinkNode *p;
p = head->Next;
if(p == NULL)
{
printf("单链表为空!");
}
else
{
while(p != NULL)
{
printf("%d/t",p->Data);
p = p->Next;
}
}
printf("/n/n");
}
int _tmain(int argc, _TCHAR* argv[])
{
LinkNode *p,*head;
LinkNode *q,*headTop;
int i ,value;
int Arrary[] = {2,4,6,8,10};
int Arrary1[] = {3,4,5,6,9,1,0};
printf("******************************************************/n");
printf(" 单链表算法演示程序 /n");
printf("******************************************************/n/n");
printf("【1】:测试尾部插入结点建立单链表/n");
printf("【2】:测试头部插入结点建立链表/n");
printf("【3】:链表的长度/n");
printf("【4】:清空操作/n");
printf("【5】:判断单链表是否为空/n");
printf("【6】:追加操作,在单链表的表尾增加个元素/n");
printf("【7】:在指定位置前,插入一个结点/n");
printf("【8】:在指定位置之后,插入一个结点/n");
printf("【9】:删除单链表中指定位置的结点/n");
printf("【10】:取单链表中指定位置的数据元素/n");
printf("【11】:按值查找算法演示/n");
printf("【12】:单链表的转置算法演示(通过后插入结点的方法)/n");
printf("【13】:单链表的转置算法演示(移动结点指向的方法)/n");
printf("【14】:单链表的转置算法演示(采用遍历原单链表,插入到新的单链表中去)/n");
printf("【0】:退出演示程序!/n/n");
START:
printf("请输入要测试项的编号: ");
Goto:
scanf("%d",&i);
if(i == 0)
{
printf("按任何键退出程序.......");
}
else
{
printf("/n");
switch(i)
{
case 1:
printf("-------测试尾部插入结点建立链表---------/n");
printf("/n");
head = CreateLinkList(Arrary,5);
p = head->Next;
/* printf("%x/n",head);*/
printf("-----------遍历链表输出数据域-----------/n");
while(p != NULL)
{
printf("%d/t",p->Data);
p = p->Next;
}
printf("/n/n");
goto START;
case 2:
printf("-------测试头部插入结点建立链表---------/n");
printf("/n");
headTop = CreateLinkListHead(Arrary1,7);
q = headTop->Next;
printf("-----------遍历链表输出数据域-----------/n");
while(q != NULL)
{
printf("%d/t",q->Data);
q = q->Next;
}
printf("/n/n");
goto START;
case 3:
headTop = CreateLinkListHead(Arrary1,7);
Print(headTop);
printf("链表的长度为: ");
printf("%d/n/n",GetLength(headTop));
goto START;
case 4:
headTop = CreateLinkListHead(Arrary1,7);
Print(headTop);
printf("清空单链表2前,单链表头指针的Next域为: ");
printf("%x/n",headTop->Next);
printf("清空单链表2后,单链表头指针的Next域为: ");
ClearLinkList(headTop);//清空操作
printf("%x/n/n",headTop->Next);
goto START;
case 5:
head = CreateLinkList(Arrary,5);
Print(head);
headTop = CreateLinkListHead(Arrary1,7);
Print(headTop);
printf("--------判断单链表是否为空-----------/n");
if(IsEmpty(headTop))
{
printf("单链表2为空!/n/n");
}
else
{
printf("单链表2不为空!/n/n");
}
if(IsEmpty(head))
{
printf("单链表1为空!/n/n");
}
else
{
printf("单链表1不为空!/n/n");
}
goto START;
case 6:
head = CreateLinkList(Arrary,5);
printf("---------追加操作,在单链表的表尾增加个元素--------/n");
printf("追加数据元素前,单链表的数据元素为:/n");
Print(head);
Append(13,head);
printf("追加数据元素后,单链表的数据元素为:/n");
Print(head);
printf("/n");
goto START;
case 7:
head = CreateLinkList(Arrary,5);
printf("在指定位置前,插入一个结点/n");
printf("插入之前,单链表1的数据元素为: /n");
Print(head);
printf("请输入指定位置和插入值,格式为(i,value):");
scanf("%d, %d",&i,&value);
printf("/n");
InsertPre(head,i,value);
printf("插入之后,单链表1的数据元素为:/n");
Print(head);
goto START;
case 8:
head = CreateLinkList(Arrary,5);
printf("在指定位置之后,插入一个结点/n");
printf("插入之前,单链表1的数据元素为:/n");
Print(head);
printf("请输入指定位置和插入值,格式为(i,value):");
scanf("%d, %d",&i,&value);
printf("/n");
InsertLast(head,i,value);
printf("插入之后,单链表1的数据元素为:/n");
Print(head);
goto START;
case 9:
// default:
head = CreateLinkList(Arrary,5);
printf("删除单链表中指定位置的结点/n");
printf("删除前,单链表1的数据元素为:/n");
Print(head);
printf("请输入删除结点的位置:(i):");
scanf("%d",&i);
printf("/n");
Delete(head,i);
printf("删除后,单链表中的数据元素为:/n");
Print(head);
goto START;
case 10:
head = CreateLinkList(Arrary,5);
printf("取指定位置结点的数据元素:/n");
printf("单链表目前的数据元素为:/n");
Print(head);
printf("请输入要取结点的位置:(i) ");
scanf("%d",&i);
GetElem(head,i);
goto START;
case 11:
head = CreateLinkList(Arrary,5);
printf("按值查找演示:/n");
printf("单链表目前的数值元素为:/n");
Print(head);
printf("请输入要取查找的值:(value)");
scanf("%d",&value);
Locate(head,value);
goto START;
case 12:
head = CreateLinkList(Arrary,5);
printf("单链表转置算法演示:/n");
printf("原单链表的数据元素为:/n");
Print(head);
printf("转置后的单链表的数据元素为:/n");
ReversLinkList(head);
Print(head);
goto START;
case 13:
head = CreateLinkList(Arrary,5);
printf("单链表转置算法演示:/n");
printf("原单链表的数据元素为:/n");
Print(head);
printf("转置后的单链表的数据元素为:/n");
ReversLinkList2(head);
Print(head);
goto START;
case 14:
head = CreateLinkList(Arrary,5);
printf("单链表转置算法演示:/n");
printf("原单链表的数据元素为:/n");
Print(head);
printf("转置后的单链表的数据元素为:/n");
ReversLinkList3(head);
Print(head);
goto START;
default:
printf("编号输入错误,请重新输入 :");
goto Goto;
}
}
getchar();//如果不加此句,执行scanf("%d, %d",&i,&value);时,当输入两个值后,按下回车,会出先程序自动结束。
getchar();//防止程序的自动结束。
return 0;
}
本文介绍了单链表的基本操作,包括创建、遍历、插入、删除等算法,并提供了详细的C++实现代码。通过实例演示了如何运用这些算法解决实际问题。
1万+

被折叠的 条评论
为什么被折叠?



