快要考试了,所以准备这几天把数据结构都过一遍,也就是对那些基本算法进行一次温习吧,加油!!!
——————————————————————————————————————————————
首先先从线性表开始,线性表有2种存储方式,顺序存储和链式存储。
顺序存储:
l
顺序存储方法:
用
一组地址连续
的存储单元依次存储线性表的元素,可通过
数组
来实现。
代码:
<pre name="code" class="cpp">#define MAXSIZE 100
#define OK 1
#define ERROR -1
#include <iostream>
#include<stdio.h>
using namespace std;
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int lenbgth;
}SqList;
//初始化
void InitList(SqList &L)
{
L.lenbgth = 0;
}
//奖励一个顺序存储的线性表
void CreatSqlist(SqList &L, int n)
{
for (int i = 0; i<n; i++)
cin >> L.data[i];
L.lenbgth = n;
}
//输出顺序表
void Output(SqList L)
{
for (int i = 0; i<L.lenbgth; i++)
cout << L.data[i] << " ";
}
//判断是否为空
bool IsEmpty(SqList L)
{
if (L.lenbgth = 0)
return true;
else
return false;
}
//取表中第i个元素
int GetElem(SqList L, int i)
{
if (i<0 && i >= L.lenbgth)
return ERROR;
else
return L.data[i - 1];
}
//定位,返回L中第一个与x相等的数据元素位置
int LocateElem(SqList L, ElemType x)
{
int k = 0;
while (k<L.lenbgth && L.data[k] != x)
{
k++;
}
if (k<L.lenbgth)
return k;
else
return ERROR;
}
//在第i个元素之前插入元素x
int Insert(SqList &L, ElemType x, int i)
{
int k = 0;
if (k<0 || i>L.lenbgth || L.lenbgth == MAXSIZE)
return ERROR;
else
{
for (k = L.lenbgth; k >= i; k--)
L.data[k] = L.data[k - 1];
L.data[i] = x;
L.lenbgth += 1;
}
return OK;
}
//删除第i个数据元素
int Delete(SqList &L, int i)
{
int k;
if (i<0 || i >= L.lenbgth)
return ERROR;
else
{
for (k = i; k<L.lenbgth; k++)
L.data[k] = L.data[k + 1];
L.lenbgth--;
}
return OK;
}
//清空线性表
void Clear(SqList &L)
{
InitList(L);
}
//合并有序表la和lb到表lc
void MergeList(SqList la, SqList lb, SqList &lc)
{
int i = 0, j = 0, k = 0;
while (i<la.lenbgth && j<lb.lenbgth)
{
if (la.data[i]<lb.data[j])
lc.data[k++] = la.data[i++];
else
if (la.data[i]>lb.data[j])
lc.data[k++] = lb.data[j++];
else
{
lc.data[k++] = lb.data[j++];
i++;
}
}
while (i<la.lenbgth)
{
lc.data[k++] = lb.data[i++];
}
while (j<lb.lenbgth)
{
lc.data[k++] = la.data[j++];
}
lc.lenbgth = k;
}
void output()
{
int i;
for (i = 0; i<10; i++)
cout << " ";
for (i = 0; i<32; i++)
cout << '*';
cout << endl;
}
void mainpp()
{
int i;
output();
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "1.建立一个顺序表";
for (i = 0; i<10; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "2.输出一个顺序表";
for (i = 0; i<10; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "3.在顺序表中查找";
for (i = 0; i<10; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "4.向顺序表中插入一个元素";
for (i = 0; i<2; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "5.删除顺序表中的一个元素";
for (i = 0; i<2; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "6.从顺序表中取出一个元素";
for (i = 0; i<2; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "7.将两个顺序表合并";
for (i = 0; i<8; i++)
cout << " ";
cout << "*" << endl;
for (i = 0; i<10; i++)
cout << " ";
cout << "* ";
cout << "0.退 出";
for (i = 0; i<8; i++)
cout << " ";
cout << "*" << endl;
output();
}
int main()
{
int n, i, k = 1, m, x;
SqList l, la, lc;
mainpp();
while (k)
{
cout << "请选择0--7:";
cin >> m;
getchar();
switch (m)
{
case 0:return 0;
case 1:
{
cout << "输入元素值,构建顺序表:\n";
cout << "请输入元素的个数:";
cin >> n;
cout << "请输入元素的值: ";
CreatSqlist(l, n);
Output(l);
break;
}
case 2:
{
Output(l);
cout << endl;
break;
}
case 3:
{
cout << "请输入要查找的元素值: ";
cin >> x;
k = LocateElem(l, x);
cout << "要输入的元素的定位:\n" << k << endl;
break;
}
case 4:
{
cout << "输入要插入元素的位置和值: ";
cin >> i;
cin >> x;
Insert(l, x, i);
Output(l);
cout << endl;
break;
}
case 5:
{
cout << "输入要删除位置的位置: ";
cin >> i;
Delete(l, i);
Output(l);
break;
}
case 6:
{
cout << "请输入要取出元素的序号: ";
cin >> i;
k = GetElem(l, i);
cout << "取出第" << i << "个元素为: " << k << endl;
break;
}
case 7:
{
InitList(la);
cout << "输入第二个顺序表元素的个数: ";
cin >> m;
CreatSqlist(la, m);
Output(la);
MergeList(l, la, lc);
cout << "输出合并后的顺序表中德元素:\n";
Output(lc);
break;
}
default:
return 0;
}
cout << "继续运行Y(1)/N(0): ";
cin >> k;
if (!k)
return 0;
}
}
链式存储:结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻
实现代码:
//这一次补上链表的注释,代码是空闲的时候敲出来的,如果有错,希望帮忙纠正
//部分给出了详细说明,这里只选取了基本操作,因为更复杂的链表操作太繁琐,这里就不写了
//如果有什么不懂的地方,可以随时询问
#include <iostream>
using namespace std;
typedef int Elemtype;
struct Node
{
Elemtype data;
Node *prior;
Node *next;
};
void Init(Node *L) //主函数里面定义Node型指针变量plist,储存单链表的头指针
{
//Node *L;
// L=new Node;
// *L=NULL;
L = NULL;
cout << "初始化成功!\n";
}
//这里有两种方式表达,
//1.初始化函数形参要给二级指针,相应的主函数里面实参则是对头指针的引用
//2.初始化函数形参直接给头指针,主函数里的实参就是头指针
void Clear_List(Node *head) //清空函数
{
Node *flag;
if (head == NULL)
{
cout << "链表为空!\n";
return;
}
while (head->next != NULL)
{
flag = head->next;
delete(head);
head = flag;
}
cout << "链表已经清空!\n";
}
//加一个标记,移动头指针后赋值flag保存下一个位置,然后删除当前节点
Node *Creat_list(Node *head) //赋值函数
{
//int n=0;
Node *p1, *p2;
p1 = new Node;
p2 = new Node;
//head=NULL;
cout << "请输入链表元素(10个元素,便于测试),以0结束输入:" << endl;
cin >> p1->data; //先输入一个数据
p1->next = NULL;
head = p1;
while (p1->data != 0) //这个是控制输出的
{
//n=n+1;
//if(n==1)
//if(head==NULL) 当头指针为NULL的时候,也就是第一次插入数据的时候,
// 使head=p1;
//else
p2->next = p1;//后面的输入全部执行这里
p2 = p1; //p2暂时保存p1
p1 = new Node; //p1更新
cin >> p1->data;
p1->next = NULL;
}
//cout<<head->data;
return head;
}
//后来想了想p2还是不能删,如果删了虽然不会报错,但是显示程序停止,所以我觉得p2的作用应该是保存之前的节点
//可以想一下,如果删除p2,那么程序首先读入p1,在判断p1数据域非0后,要用p2保存下p1节点,然后p1在向后更新,如此反复。。。
//读入链表元素,在while循环里面每次将当前指针保存下来,然后不断向后更新
void List_length(Node *head)
{
int i = 0;
while (head != NULL)
{
i++;
head = head->next;
}
cout << "链表长度length: " << i << endl;
}
void Out_list(Node *head)
{
// cout<<head->data;
if (head == NULL)
cout << "链表为空!\n";
else
{
while (head != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
}
Elemtype Get_elem(int index, Node *head) //给定下标,求节点元素
{
int j = 0;
//Node *p;
while (head != NULL)
{
j++;
if (j == index)
break;
head = head->next;
}
if (j<index)
{
cout << "选取的范围超出链表长度!\n";
return 0;
}
return head->data;
}
//给定的下标index,只需遍历链表,当节点数符合要求时即可
int locate_elem(Node *head, Elemtype _First) //给定节点元素,求第一个下标(也可以扩展求多个点的下标或者地址)
{
int n = 1;
while (head != NULL)
{
if (head->data == _First)
return n;
else
n++;
head = head->next;
}
cout << "单链表里不存在 " << _First << " 这个元素" << "!\n";
return 0;
}
//同理,遍历查找出给定元素,然后直接返回下标
bool Insert_elem(Node *head, Elemtype insert_elem, int index)
{
Node *p, *q;
if (index<1)
{
cout << "输入下标有误!\n";
return false;
}
int i = 1;
while (head != NULL)
{
i++;
head = head->next;
if (i == index - 1)
{
p = q = new Node;
q = head;
//head=head->next;
(*p).data = insert_elem;
//这里调试了好久。。。开始我是想定义一个节点和一个指针的,输出的时候会报错
//最后还是觉得都定义指针吧,p那里不加括号的话也会报错
(*p).next = head->next;
q->next = p;
//p->next=head->next;
//p->data=insert_elem;
return true;
}
}
return false;
}
//插入步骤稍微多些,要另外定义两个指针,思路就是遍历到给定下标的前一个下标,同时指针q记录下位置
//而另外一个指针p储存节点数据,并且使它指向头指针下一个点的地址,最后使q指向p即可
bool delete_Node(Node *head, int index)
{
int i = 1;
if (index<1)
{
cout << "输入下标值有误!\n";
return false;
}
while (head != NULL)
{
i++;
head = head->next;
if (i == index - 1)
{
Node *p;
p = new Node;
p = head;
head = head->next;
p->next = head->next;
return true;
}
}
return false;
}
//操作类似于插入,不多说
bool Change_Node_Elem(Node *head, int index, Elemtype Example3)
{
int i = 1;
if (head == NULL || index<1)
{
cout << "输入错误或链表为空!\n";
return false;
}
while (head != NULL)
{
i++;
head = head->next;
if (i == index)
{
head->data = Example3;
return true;
}
}
return false;
}
//也是遍历链表找到给定位置,然后更新数据
int main()
{
Node *plist=NULL;
//Node *plist;
Elemtype Example1 = 5, Example2 = 7, Example3 = 9;
cout << "创建一个单链表(plist):\n";
Init(plist); //初始化
plist = Creat_list(plist); //创建单链表,给单链表赋值,返回头指针
cout << "打印原始链表:\n";
Out_list(plist);
cout << endl;
cout << "链表第三个节点的元素值为: " << Get_elem(3, plist) << endl;
cout << endl;
//调用Get_elem函数,返回链表第三个节点内元素值
//cout<<"输出链表长度:\n";
List_length(plist);
cout << endl;
if (locate_elem(plist, Example1))
cout << "链表plist第一次出现 " << Example1 << " 值的下标:" << locate_elem(plist, Example1) << endl;
cout << endl;
//调用locate_elem函数,返回链表内第一个出现Example1元素的节点数
cout << "将元素 " << Example2 << " 插入链表第四个节点上:" << endl;
if (Insert_elem(plist, Example2, 4))
{
cout << "Insert is OK!\n";
cout << "改变后的链表为:" << endl;
Out_list(plist);
}
else
cout << "Insert is not OK!\n";
cout << endl;
cout << "将链表第七个节点删除:" << endl;
if (delete_Node(plist, 7))
{
cout << "Delete is OK!\n";
cout << "改变后的链表为:" << endl;
Out_list(plist);
}
else
cout << "Delete is not OK!\n";
cout << endl;
cout << "将链表plist中第三个节点的元素换成 " << Example3 << endl;
if (Change_Node_Elem(plist, 3, Example3))
{
cout << "改变后的链表为:\n";
Out_list(plist);
}
else
cout << "数值改变失败!\n";
cout << endl;
cout << "执行清空函数:" << endl;
Clear_List(plist);
return 0;
}