复习——线性表

快要考试了,所以准备这几天把数据结构都过一遍,也就是对那些基本算法进行一次温习吧,加油!!!

——————————————————————————————————————————————


首先先从线性表开始,线性表有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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值